diff --git a/composer.json b/composer.json index 5806de5fa..231c86244 100644 --- a/composer.json +++ b/composer.json @@ -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", diff --git a/composer.lock b/composer.lock index 63a0c2e1c..aecc1bc94 100644 --- a/composer.lock +++ b/composer.lock @@ -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" } diff --git a/core/asynctask.class.inc.php b/core/asynctask.class.inc.php index 5c7d329bf..69eb4e1a4 100644 --- a/core/asynctask.class.inc.php +++ b/core/asynctask.class.inc.php @@ -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); diff --git a/core/email.class.inc.php b/core/email.class.inc.php index 1470befaf..ab50f1ef1 100644 --- a/core/email.class.inc.php +++ b/core/email.class.inc.php @@ -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')); } @@ -72,12 +78,18 @@ class EMail { return serialize($this->m_aData); } - + /** * 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) { @@ -223,51 +239,65 @@ class EMail throw $e; } } - + /** * 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(''.$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(''.$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; @@ -496,77 +615,4 @@ 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(); - } } \ No newline at end of file diff --git a/lib/composer/ClassLoader.php b/lib/composer/ClassLoader.php index 0cd6055d1..afef3fa2a 100644 --- a/lib/composer/ClassLoader.php +++ b/lib/composer/ClassLoader.php @@ -149,7 +149,7 @@ class ClassLoader /** * @return string[] Array of classname => path - * @psalm-var array + * @psalm-return array */ public function getClassMap() { diff --git a/lib/composer/InstalledVersions.php b/lib/composer/InstalledVersions.php index 7c5502ca4..d50e0c9fc 100644 --- a/lib/composer/InstalledVersions.php +++ b/lib/composer/InstalledVersions.php @@ -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}|array{}|null + */ private static $installed; + + /** + * @var bool|null + */ private static $canGetVendors; + + /** + * @var array[] + * @psalm-var array}> + */ private static $installedByVendor = array(); /** diff --git a/lib/composer/autoload_classmap.php b/lib/composer/autoload_classmap.php index f8ce6c4f2..ee7d2c4ca 100644 --- a/lib/composer/autoload_classmap.php +++ b/lib/composer/autoload_classmap.php @@ -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', diff --git a/lib/composer/autoload_files.php b/lib/composer/autoload_files.php index 65bc196d3..7346798aa 100644 --- a/lib/composer/autoload_files.php +++ b/lib/composer/autoload_files.php @@ -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', ); diff --git a/lib/composer/autoload_psr4.php b/lib/composer/autoload_psr4.php index 20234ce5e..ddd4c36f4 100644 --- a/lib/composer/autoload_psr4.php +++ b/lib/composer/autoload_psr4.php @@ -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'), ); diff --git a/lib/composer/autoload_real.php b/lib/composer/autoload_real.php index 661cd2543..9a33b711c 100644 --- a/lib/composer/autoload_real.php +++ b/lib/composer/autoload_real.php @@ -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; } } diff --git a/lib/composer/autoload_static.php b/lib/composer/autoload_static.php index 2234e0245..8b5ea4430 100644 --- a/lib/composer/autoload_static.php +++ b/lib/composer/autoload_static.php @@ -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', diff --git a/lib/composer/installed.json b/lib/composer/installed.json index 36d4536cd..21c21d7b9 100644 --- a/lib/composer/installed.json +++ b/lib/composer/installed.json @@ -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", diff --git a/lib/composer/installed.php b/lib/composer/installed.php index 1e691e0f2..a6adbf5c3 100644 --- a/lib/composer/installed.php +++ b/lib/composer/installed.php @@ -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', + ), + ), ), ); diff --git a/lib/laminas/laminas-loader/CHANGELOG.md b/lib/laminas/laminas-loader/CHANGELOG.md new file mode 100644 index 000000000..1238128a4 --- /dev/null +++ b/lib/laminas/laminas-loader/CHANGELOG.md @@ -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. diff --git a/lib/laminas/laminas-loader/COPYRIGHT.md b/lib/laminas/laminas-loader/COPYRIGHT.md new file mode 100644 index 000000000..c4fc4fee1 --- /dev/null +++ b/lib/laminas/laminas-loader/COPYRIGHT.md @@ -0,0 +1,2 @@ +Copyright (c) 2019, Laminas Foundation. +All rights reserved. (https://getlaminas.org/) diff --git a/lib/laminas/laminas-loader/LICENSE.md b/lib/laminas/laminas-loader/LICENSE.md new file mode 100644 index 000000000..09f53edc1 --- /dev/null +++ b/lib/laminas/laminas-loader/LICENSE.md @@ -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. diff --git a/lib/laminas/laminas-loader/README.md b/lib/laminas/laminas-loader/README.md new file mode 100644 index 000000000..c83525416 --- /dev/null +++ b/lib/laminas/laminas-loader/README.md @@ -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/ diff --git a/lib/laminas/laminas-loader/composer.json b/lib/laminas/laminas-loader/composer.json new file mode 100644 index 000000000..c9874b45f --- /dev/null +++ b/lib/laminas/laminas-loader/composer.json @@ -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" + } +} diff --git a/lib/laminas/laminas-loader/src/AutoloaderFactory.php b/lib/laminas/laminas-loader/src/AutoloaderFactory.php new file mode 100644 index 000000000..11c882516 --- /dev/null +++ b/lib/laminas/laminas-loader/src/AutoloaderFactory.php @@ -0,0 +1,210 @@ + + * array( + * '' => $autoloaderOptions, + * ) + * + * + * 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); + } +} diff --git a/lib/laminas/laminas-loader/src/ClassMapAutoloader.php b/lib/laminas/laminas-loader/src/ClassMapAutoloader.php new file mode 100644 index 000000000..ae4787c9f --- /dev/null +++ b/lib/laminas/laminas-loader/src/ClassMapAutoloader.php @@ -0,0 +1,220 @@ +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; + } + } +} diff --git a/lib/laminas/laminas-loader/src/Exception/BadMethodCallException.php b/lib/laminas/laminas-loader/src/Exception/BadMethodCallException.php new file mode 100644 index 000000000..028c2318c --- /dev/null +++ b/lib/laminas/laminas-loader/src/Exception/BadMethodCallException.php @@ -0,0 +1,16 @@ + 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; + } +} diff --git a/lib/laminas/laminas-loader/src/PluginClassLoader.php b/lib/laminas/laminas-loader/src/PluginClassLoader.php new file mode 100644 index 000000000..90a0892e5 --- /dev/null +++ b/lib/laminas/laminas-loader/src/PluginClassLoader.php @@ -0,0 +1,216 @@ + 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); + } +} diff --git a/lib/laminas/laminas-loader/src/PluginClassLocator.php b/lib/laminas/laminas-loader/src/PluginClassLocator.php new file mode 100644 index 000000000..078983f47 --- /dev/null +++ b/lib/laminas/laminas-loader/src/PluginClassLocator.php @@ -0,0 +1,42 @@ + + * spl_autoload_register(array($this, 'autoload')); + * + * + * @return void + */ + public function register(); +} diff --git a/lib/laminas/laminas-loader/src/StandardAutoloader.php b/lib/laminas/laminas-loader/src/StandardAutoloader.php new file mode 100644 index 000000000..5a1f29a1a --- /dev/null +++ b/lib/laminas/laminas-loader/src/StandardAutoloader.php @@ -0,0 +1,327 @@ +setOptions($options); + } + } + + /** + * Configure autoloader + * + * Allows specifying both "namespace" and "prefix" pairs, using the + * following structure: + * + * array( + * 'namespaces' => array( + * 'Laminas' => '/path/to/Laminas/library', + * 'Doctrine' => '/path/to/Doctrine/library', + * ), + * 'prefixes' => array( + * 'Phly_' => '/path/to/Phly/library', + * ), + * 'fallback_autoloader' => true, + * ) + * + * + * @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.+\\\)?(?P[^\\\]+$)/', $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; + } +} diff --git a/lib/laminas/laminas-mail/CHANGELOG.md b/lib/laminas/laminas-mail/CHANGELOG.md new file mode 100644 index 000000000..78f6911ec --- /dev/null +++ b/lib/laminas/laminas-mail/CHANGELOG.md @@ -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)?` 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<->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. diff --git a/lib/laminas/laminas-mail/COPYRIGHT.md b/lib/laminas/laminas-mail/COPYRIGHT.md new file mode 100644 index 000000000..0a8cccc06 --- /dev/null +++ b/lib/laminas/laminas-mail/COPYRIGHT.md @@ -0,0 +1 @@ +Copyright (c) 2020 Laminas Project a Series of LF Projects, LLC. (https://getlaminas.org/) diff --git a/lib/laminas/laminas-mail/LICENSE.md b/lib/laminas/laminas-mail/LICENSE.md new file mode 100644 index 000000000..10b40f142 --- /dev/null +++ b/lib/laminas/laminas-mail/LICENSE.md @@ -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. diff --git a/lib/laminas/laminas-mail/README.md b/lib/laminas/laminas-mail/README.md new file mode 100644 index 000000000..3ffca6e7a --- /dev/null +++ b/lib/laminas/laminas-mail/README.md @@ -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/ diff --git a/lib/laminas/laminas-mail/composer.json b/lib/laminas/laminas-mail/composer.json new file mode 100644 index 000000000..d43eba1e0 --- /dev/null +++ b/lib/laminas/laminas-mail/composer.json @@ -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" + } +} diff --git a/lib/laminas/laminas-mail/src/Address.php b/lib/laminas/laminas-mail/src/Address.php new file mode 100644 index 000000000..45b7a12b4 --- /dev/null +++ b/lib/laminas/laminas-mail/src/Address.php @@ -0,0 +1,166 @@ +.*)<(?P[^>]+)>|(?P.+))$/', $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); + } +} diff --git a/lib/laminas/laminas-mail/src/Address/AddressInterface.php b/lib/laminas/laminas-mail/src/Address/AddressInterface.php new file mode 100644 index 000000000..cf521940b --- /dev/null +++ b/lib/laminas/laminas-mail/src/Address/AddressInterface.php @@ -0,0 +1,33 @@ +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 + * + * @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); + } +} diff --git a/lib/laminas/laminas-mail/src/ConfigProvider.php b/lib/laminas/laminas-mail/src/ConfigProvider.php new file mode 100644 index 000000000..2e7fa83e5 --- /dev/null +++ b/lib/laminas/laminas-mail/src/ConfigProvider.php @@ -0,0 +1,42 @@ + $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, + ], + ]; + } +} diff --git a/lib/laminas/laminas-mail/src/Exception/BadMethodCallException.php b/lib/laminas/laminas-mail/src/Exception/BadMethodCallException.php new file mode 100644 index 000000000..a37a60073 --- /dev/null +++ b/lib/laminas/laminas-mail/src/Exception/BadMethodCallException.php @@ -0,0 +1,17 @@ +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( + \\\\.| + [^\\\\)] + )+) + \\)/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 + ); + } +} diff --git a/lib/laminas/laminas-mail/src/Header/Bcc.php b/lib/laminas/laminas-mail/src/Header/Bcc.php new file mode 100644 index 000000000..ce93b7588 --- /dev/null +++ b/lib/laminas/laminas-mail/src/Header/Bcc.php @@ -0,0 +1,22 @@ +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; + } +} diff --git a/lib/laminas/laminas-mail/src/Header/ContentTransferEncoding.php b/lib/laminas/laminas-mail/src/Header/ContentTransferEncoding.php new file mode 100644 index 000000000..73da55aa3 --- /dev/null +++ b/lib/laminas/laminas-mail/src/Header/ContentTransferEncoding.php @@ -0,0 +1,114 @@ +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; + } +} diff --git a/lib/laminas/laminas-mail/src/Header/ContentType.php b/lib/laminas/laminas-mail/src/Header/ContentType.php new file mode 100644 index 000000000..3b57df460 --- /dev/null +++ b/lib/laminas/laminas-mail/src/Header/ContentType.php @@ -0,0 +1,202 @@ +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; + } +} diff --git a/lib/laminas/laminas-mail/src/Header/Date.php b/lib/laminas/laminas-mail/src/Header/Date.php new file mode 100644 index 000000000..7032c3f8e --- /dev/null +++ b/lib/laminas/laminas-mail/src/Header/Date.php @@ -0,0 +1,69 @@ +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(); + } +} diff --git a/lib/laminas/laminas-mail/src/Header/Exception/BadMethodCallException.php b/lib/laminas/laminas-mail/src/Header/Exception/BadMethodCallException.php new file mode 100644 index 000000000..0b3f219ff --- /dev/null +++ b/lib/laminas/laminas-mail/src/Header/Exception/BadMethodCallException.php @@ -0,0 +1,15 @@ +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; + } +} diff --git a/lib/laminas/laminas-mail/src/Header/GenericMultiHeader.php b/lib/laminas/laminas-mail/src/Header/GenericMultiHeader.php new file mode 100644 index 000000000..583c3082b --- /dev/null +++ b/lib/laminas/laminas-mail/src/Header/GenericMultiHeader.php @@ -0,0 +1,55 @@ +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); + } +} diff --git a/lib/laminas/laminas-mail/src/Header/HeaderInterface.php b/lib/laminas/laminas-mail/src/Header/HeaderInterface.php new file mode 100644 index 000000000..3aa74fab3 --- /dev/null +++ b/lib/laminas/laminas-mail/src/Header/HeaderInterface.php @@ -0,0 +1,75 @@ + 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, + ]; +} diff --git a/lib/laminas/laminas-mail/src/Header/HeaderLocator.php b/lib/laminas/laminas-mail/src/Header/HeaderLocator.php new file mode 100644 index 000000000..060466650 --- /dev/null +++ b/lib/laminas/laminas-mail/src/Header/HeaderLocator.php @@ -0,0 +1,75 @@ + 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); + } +} diff --git a/lib/laminas/laminas-mail/src/Header/HeaderLocatorInterface.php b/lib/laminas/laminas-mail/src/Header/HeaderLocatorInterface.php new file mode 100644 index 000000000..b7cbb8a1c --- /dev/null +++ b/lib/laminas/laminas-mail/src/Header/HeaderLocatorInterface.php @@ -0,0 +1,25 @@ + 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'); + } + } +} diff --git a/lib/laminas/laminas-mail/src/Header/HeaderValue.php b/lib/laminas/laminas-mail/src/Header/HeaderValue.php new file mode 100644 index 000000000..8bfbb0c6c --- /dev/null +++ b/lib/laminas/laminas-mail/src/Header/HeaderValue.php @@ -0,0 +1,116 @@ + 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'); + } + } +} diff --git a/lib/laminas/laminas-mail/src/Header/HeaderWrap.php b/lib/laminas/laminas-mail/src/Header/HeaderWrap.php new file mode 100644 index 000000000..13c255bf7 --- /dev/null +++ b/lib/laminas/laminas-mail/src/Header/HeaderWrap.php @@ -0,0 +1,161 @@ +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); + } +} diff --git a/lib/laminas/laminas-mail/src/Header/IdentificationField.php b/lib/laminas/laminas-mail/src/Header/IdentificationField.php new file mode 100644 index 000000000..0d00b4a53 --- /dev/null +++ b/lib/laminas/laminas-mail/src/Header/IdentificationField.php @@ -0,0 +1,143 @@ +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; + } +} diff --git a/lib/laminas/laminas-mail/src/Header/InReplyTo.php b/lib/laminas/laminas-mail/src/Header/InReplyTo.php new file mode 100644 index 000000000..125295de0 --- /dev/null +++ b/lib/laminas/laminas-mail/src/Header/InReplyTo.php @@ -0,0 +1,15 @@ +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; + } +} diff --git a/lib/laminas/laminas-mail/src/Header/MimeVersion.php b/lib/laminas/laminas-mail/src/Header/MimeVersion.php new file mode 100644 index 000000000..02bdac8d0 --- /dev/null +++ b/lib/laminas/laminas-mail/src/Header/MimeVersion.php @@ -0,0 +1,87 @@ +\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; + } +} diff --git a/lib/laminas/laminas-mail/src/Header/MultipleHeadersInterface.php b/lib/laminas/laminas-mail/src/Header/MultipleHeadersInterface.php new file mode 100644 index 000000000..efbc804e5 --- /dev/null +++ b/lib/laminas/laminas-mail/src/Header/MultipleHeadersInterface.php @@ -0,0 +1,14 @@ +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); + } +} diff --git a/lib/laminas/laminas-mail/src/Header/References.php b/lib/laminas/laminas-mail/src/Header/References.php new file mode 100644 index 000000000..c13559626 --- /dev/null +++ b/lib/laminas/laminas-mail/src/Header/References.php @@ -0,0 +1,15 @@ + 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.+)\s)?(?(name)<|[^\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; + } +} diff --git a/lib/laminas/laminas-mail/src/Header/StructuredInterface.php b/lib/laminas/laminas-mail/src/Header/StructuredInterface.php new file mode 100644 index 000000000..396f54745 --- /dev/null +++ b/lib/laminas/laminas-mail/src/Header/StructuredInterface.php @@ -0,0 +1,19 @@ +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); + } +} diff --git a/lib/laminas/laminas-mail/src/Header/To.php b/lib/laminas/laminas-mail/src/Header/To.php new file mode 100644 index 000000000..ea9655ee3 --- /dev/null +++ b/lib/laminas/laminas-mail/src/Header/To.php @@ -0,0 +1,15 @@ + 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); + } +} diff --git a/lib/laminas/laminas-mail/src/Message.php b/lib/laminas/laminas-mail/src/Message.php new file mode 100644 index 000000000..c6526dd14 --- /dev/null +++ b/lib/laminas/laminas-mail/src/Message.php @@ -0,0 +1,576 @@ +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; + } +} diff --git a/lib/laminas/laminas-mail/src/MessageFactory.php b/lib/laminas/laminas-mail/src/MessageFactory.php new file mode 100644 index 000000000..7290b7508 --- /dev/null +++ b/lib/laminas/laminas-mail/src/MessageFactory.php @@ -0,0 +1,64 @@ + $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, + [ + '-' => ' ', + '_' => ' ', + ] + ) + ) + ); + } +} diff --git a/lib/laminas/laminas-mail/src/Module.php b/lib/laminas/laminas-mail/src/Module.php new file mode 100644 index 000000000..bed90fdc6 --- /dev/null +++ b/lib/laminas/laminas-mail/src/Module.php @@ -0,0 +1,25 @@ + $provider->getDependencyConfig(), + ]; + } +} diff --git a/lib/laminas/laminas-mail/src/Protocol/AbstractProtocol.php b/lib/laminas/laminas-mail/src/Protocol/AbstractProtocol.php new file mode 100644 index 000000000..0882e1e0f --- /dev/null +++ b/lib/laminas/laminas-mail/src/Protocol/AbstractProtocol.php @@ -0,0 +1,356 @@ +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; + } +} diff --git a/lib/laminas/laminas-mail/src/Protocol/Exception/ExceptionInterface.php b/lib/laminas/laminas-mail/src/Protocol/Exception/ExceptionInterface.php new file mode 100644 index 000000000..b8b1aacf6 --- /dev/null +++ b/lib/laminas/laminas-mail/src/Protocol/Exception/ExceptionInterface.php @@ -0,0 +1,15 @@ +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}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}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 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 {..}) + * 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 []; + } +} diff --git a/lib/laminas/laminas-mail/src/Protocol/Pop3.php b/lib/laminas/laminas-mail/src/Protocol/Pop3.php new file mode 100644 index 000000000..92aa35542 --- /dev/null +++ b/lib/laminas/laminas-mail/src/Protocol/Pop3.php @@ -0,0 +1,401 @@ +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 "." + * @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'); + } +} diff --git a/lib/laminas/laminas-mail/src/Protocol/ProtocolTrait.php b/lib/laminas/laminas-mail/src/Protocol/ProtocolTrait.php new file mode 100644 index 000000000..eaf6e296e --- /dev/null +++ b/lib/laminas/laminas-mail/src/Protocol/ProtocolTrait.php @@ -0,0 +1,119 @@ +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; + } +} diff --git a/lib/laminas/laminas-mail/src/Protocol/Smtp.php b/lib/laminas/laminas-mail/src/Protocol/Smtp.php new file mode 100644 index 000000000..dcb7ebe01 --- /dev/null +++ b/lib/laminas/laminas-mail/src/Protocol/Smtp.php @@ -0,0 +1,460 @@ +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; + } +} diff --git a/lib/laminas/laminas-mail/src/Protocol/Smtp/Auth/Crammd5.php b/lib/laminas/laminas-mail/src/Protocol/Smtp/Auth/Crammd5.php new file mode 100644 index 000000000..50099163f --- /dev/null +++ b/lib/laminas/laminas-mail/src/Protocol/Smtp/Auth/Crammd5.php @@ -0,0 +1,138 @@ +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); + } +} diff --git a/lib/laminas/laminas-mail/src/Protocol/Smtp/Auth/Login.php b/lib/laminas/laminas-mail/src/Protocol/Smtp/Auth/Login.php new file mode 100644 index 000000000..8be7ba694 --- /dev/null +++ b/lib/laminas/laminas-mail/src/Protocol/Smtp/Auth/Login.php @@ -0,0 +1,126 @@ +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; + } +} diff --git a/lib/laminas/laminas-mail/src/Protocol/Smtp/Auth/Plain.php b/lib/laminas/laminas-mail/src/Protocol/Smtp/Auth/Plain.php new file mode 100644 index 000000000..8cf6c3724 --- /dev/null +++ b/lib/laminas/laminas-mail/src/Protocol/Smtp/Auth/Plain.php @@ -0,0 +1,124 @@ +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; + } +} diff --git a/lib/laminas/laminas-mail/src/Protocol/SmtpPluginManager.php b/lib/laminas/laminas-mail/src/Protocol/SmtpPluginManager.php new file mode 100644 index 000000000..05c5516d9 --- /dev/null +++ b/lib/laminas/laminas-mail/src/Protocol/SmtpPluginManager.php @@ -0,0 +1,114 @@ + Smtp\Auth\Crammd5::class, + 'cramMd5' => Smtp\Auth\Crammd5::class, + 'CramMd5' => Smtp\Auth\Crammd5::class, + 'cramMD5' => Smtp\Auth\Crammd5::class, + 'CramMD5' => Smtp\Auth\Crammd5::class, + 'login' => Smtp\Auth\Login::class, + 'Login' => Smtp\Auth\Login::class, + 'plain' => Smtp\Auth\Plain::class, + 'Plain' => Smtp\Auth\Plain::class, + 'smtp' => Smtp::class, + 'Smtp' => Smtp::class, + 'SMTP' => Smtp::class, + + // Legacy Zend Framework aliases + \Zend\Mail\Protocol\Smtp\Auth\Crammd5::class => Smtp\Auth\Crammd5::class, + \Zend\Mail\Protocol\Smtp\Auth\Login::class => Smtp\Auth\Login::class, + \Zend\Mail\Protocol\Smtp\Auth\Plain::class => Smtp\Auth\Plain::class, + \Zend\Mail\Protocol\Smtp::class => Smtp::class, + + // v2 normalized FQCNs + 'zendmailprotocolsmtpauthcrammd5' => Smtp\Auth\Crammd5::class, + 'zendmailprotocolsmtpauthlogin' => Smtp\Auth\Login::class, + 'zendmailprotocolsmtpauthplain' => Smtp\Auth\Plain::class, + 'zendmailprotocolsmtp' => Smtp::class, + ]; + + /** + * Service factories + * + * @var array + */ + protected $factories = [ + Smtp\Auth\Crammd5::class => InvokableFactory::class, + Smtp\Auth\Login::class => InvokableFactory::class, + Smtp\Auth\Plain::class => InvokableFactory::class, + Smtp::class => InvokableFactory::class, + + // v2 normalized service names + + 'laminasmailprotocolsmtpauthcrammd5' => InvokableFactory::class, + 'laminasmailprotocolsmtpauthlogin' => InvokableFactory::class, + 'laminasmailprotocolsmtpauthplain' => InvokableFactory::class, + 'laminasmailprotocolsmtp' => InvokableFactory::class, + ]; + + /** + * Plugins must be an instance of the Smtp class + * + * @var string + */ + protected $instanceOf = Smtp::class; + + /** + * Validate a retrieved plugin instance (v3). + * + * @param object $plugin + * @throws InvalidServiceException + */ + public function validate($plugin) + { + if (! $plugin instanceof $this->instanceOf) { + throw new InvalidServiceException(sprintf( + 'Plugin of type %s is invalid; must extend %s', + (is_object($plugin) ? get_class($plugin) : gettype($plugin)), + $this->instanceOf + )); + } + } + + /** + * Validate a retrieved plugin instance (v2). + * + * @param object $plugin + * @throws Exception\InvalidArgumentException + */ + public function validatePlugin($plugin) + { + try { + $this->validate($plugin); + } catch (InvalidServiceException $e) { + throw new Exception\InvalidArgumentException( + $e->getMessage(), + $e->getCode(), + $e + ); + } + } +} diff --git a/lib/laminas/laminas-mail/src/Protocol/SmtpPluginManagerFactory.php b/lib/laminas/laminas-mail/src/Protocol/SmtpPluginManagerFactory.php new file mode 100644 index 000000000..7a8834a05 --- /dev/null +++ b/lib/laminas/laminas-mail/src/Protocol/SmtpPluginManagerFactory.php @@ -0,0 +1,54 @@ +creationOptions); + } + + /** + * laminas-servicemanager v2 support for invocation options. + * + * @param array $options + * @return void + */ + public function setCreationOptions(array $options) + { + $this->creationOptions = $options; + } +} diff --git a/lib/laminas/laminas-mail/src/Storage.php b/lib/laminas/laminas-mail/src/Storage.php new file mode 100644 index 000000000..81f13197f --- /dev/null +++ b/lib/laminas/laminas-mail/src/Storage.php @@ -0,0 +1,23 @@ + true, + 'delete' => false, + 'create' => false, + 'top' => false, + 'fetchPart' => true, + 'flags' => false, + ]; + + /** + * current iteration position + * @var int + */ + protected $iterationPos = 0; + + /** + * maximum iteration position (= message count) + * @var null|int + */ + protected $iterationMax = null; + + /** + * used message class, change it in an extended class to extend the returned message class + * @var string + */ + protected $messageClass = Message::class; + + /** + * Getter for has-properties. The standard has properties + * are: hasFolder, hasUniqueid, hasDelete, hasCreate, hasTop + * + * The valid values for the has-properties are: + * - true if a feature is supported + * - false if a feature is not supported + * - null is it's not yet known or it can't be know if a feature is supported + * + * @param string $var property name + * @throws Exception\InvalidArgumentException + * @return bool supported or not + */ + public function __get($var) + { + if (strpos($var, 'has') === 0) { + $var = strtolower(substr($var, 3)); + return isset($this->has[$var]) ? $this->has[$var] : null; + } + + throw new Exception\InvalidArgumentException($var . ' not found'); + } + + /** + * Get a full list of features supported by the specific mail lib and the server + * + * @return array list of features as array(feature_name => true|false[|null]) + */ + public function getCapabilities() + { + return $this->has; + } + + /** + * Count messages messages in current box/folder + * + * @return int number of messages + * @throws Exception\ExceptionInterface + */ + abstract public function countMessages(); + + /** + * Get a list of messages with number and size + * + * @param int $id number of message + * @return int|array size of given message of list with all messages as array(num => size) + */ + abstract public function getSize($id = 0); + + /** + * Get a message with headers and body + * + * @param $id int number of message + * @return Message + */ + abstract public function getMessage($id); + + /** + * Get raw header of message or part + * + * @param int $id number of message + * @param null|array|string $part path to part or null for message header + * @param int $topLines include this many lines with header (after an empty line) + * @return string raw header + */ + abstract public function getRawHeader($id, $part = null, $topLines = 0); + + /** + * Get raw content of message or part + * + * @param int $id number of message + * @param null|array|string $part path to part or null for message content + * @return string raw content + */ + abstract public function getRawContent($id, $part = null); + + /** + * Create instance with parameters + * + * @param array $params mail reader specific parameters + * @throws Exception\ExceptionInterface + */ + abstract public function __construct($params); + + /** + * Destructor calls close() and therefore closes the resource. + */ + public function __destruct() + { + $this->close(); + } + + /** + * Close resource for mail lib. If you need to control, when the resource + * is closed. Otherwise the destructor would call this. + */ + abstract public function close(); + + /** + * Keep the resource alive. + */ + abstract public function noop(); + + /** + * delete a message from current box/folder + * + * @param $id + */ + abstract public function removeMessage($id); + + /** + * get unique id for one or all messages + * + * if storage does not support unique ids it's the same as the message number + * + * @param int|null $id message number + * @return array|string message number for given message or all messages as array + * @throws Exception\ExceptionInterface + */ + abstract public function getUniqueId($id = null); + + /** + * get a message number from a unique id + * + * I.e. if you have a webmailer that supports deleting messages you should use unique ids + * as parameter and use this method to translate it to message number right before calling removeMessage() + * + * @param string $id unique id + * @return int message number + * @throws Exception\ExceptionInterface + */ + abstract public function getNumberByUniqueId($id); + + // interface implementations follows + + /** + * Countable::count() + * + * @return int + */ + public function count() + { + return $this->countMessages(); + } + + /** + * ArrayAccess::offsetExists() + * + * @param int $id + * @return bool + */ + public function offsetExists($id) + { + try { + if ($this->getMessage($id)) { + return true; + } + } catch (Exception\ExceptionInterface $e) { + } + + return false; + } + + /** + * ArrayAccess::offsetGet() + * + * @param int $id + * @return \Laminas\Mail\Storage\Message message object + */ + public function offsetGet($id) + { + return $this->getMessage($id); + } + + /** + * ArrayAccess::offsetSet() + * + * @param mixed $id + * @param mixed $value + * @throws Exception\RuntimeException + */ + public function offsetSet($id, $value) + { + throw new Exception\RuntimeException('cannot write mail messages via array access'); + } + + /** + * ArrayAccess::offsetUnset() + * + * @param int $id + * @return bool success + */ + public function offsetUnset($id) + { + return $this->removeMessage($id); + } + + /** + * Iterator::rewind() + * + * Rewind always gets the new count from the storage. Thus if you use + * the interfaces and your scripts take long you should use reset() + * from time to time. + */ + public function rewind() + { + $this->iterationMax = $this->countMessages(); + $this->iterationPos = 1; + } + + /** + * Iterator::current() + * + * @return Message current message + */ + public function current() + { + return $this->getMessage($this->iterationPos); + } + + /** + * Iterator::key() + * + * @return int id of current position + */ + public function key() + { + return $this->iterationPos; + } + + /** + * Iterator::next() + */ + public function next() + { + ++$this->iterationPos; + } + + /** + * Iterator::valid() + * + * @return bool + */ + public function valid() + { + if ($this->iterationMax === null) { + $this->iterationMax = $this->countMessages(); + } + return $this->iterationPos && $this->iterationPos <= $this->iterationMax; + } + + /** + * SeekableIterator::seek() + * + * @param int $pos + * @throws Exception\OutOfBoundsException + */ + public function seek($pos) + { + if ($this->iterationMax === null) { + $this->iterationMax = $this->countMessages(); + } + + if ($pos > $this->iterationMax) { + throw new Exception\OutOfBoundsException('this position does not exist'); + } + $this->iterationPos = $pos; + } +} diff --git a/lib/laminas/laminas-mail/src/Storage/Exception/ExceptionInterface.php b/lib/laminas/laminas-mail/src/Storage/Exception/ExceptionInterface.php new file mode 100644 index 000000000..a049e2cf7 --- /dev/null +++ b/lib/laminas/laminas-mail/src/Storage/Exception/ExceptionInterface.php @@ -0,0 +1,15 @@ + \Laminas\Mail\Storage\Folder folder) + * @var array + */ + protected $folders; + + /** + * local name (name of folder in parent folder) + * @var string + */ + protected $localName; + + /** + * global name (absolute name of folder) + * @var string + */ + protected $globalName; + + /** + * folder is selectable if folder is able to hold messages, otherwise it is a parent folder + * @var bool + */ + protected $selectable = true; + + /** + * create a new mail folder instance + * + * @param string $localName name of folder in current subdirectory + * @param string $globalName absolute name of folder + * @param bool $selectable if true folder holds messages, if false it's + * just a parent for subfolders (Default: true) + * @param array $folders init with given instances of Folder as subfolders + */ + public function __construct($localName, $globalName = '', $selectable = true, array $folders = []) + { + $this->localName = $localName; + $this->globalName = $globalName ? $globalName : $localName; + $this->selectable = $selectable; + $this->folders = $folders; + } + + /** + * implements RecursiveIterator::hasChildren() + * + * @return bool current element has children + */ + public function hasChildren() + { + $current = $this->current(); + return $current && $current instanceof Folder && ! $current->isLeaf(); + } + + /** + * implements RecursiveIterator::getChildren() + * + * @return \Laminas\Mail\Storage\Folder same as self::current() + */ + public function getChildren() + { + return $this->current(); + } + + /** + * implements Iterator::valid() + * + * @return bool check if there's a current element + */ + public function valid() + { + return key($this->folders) !== null; + } + + /** + * implements Iterator::next() + */ + public function next() + { + next($this->folders); + } + + /** + * implements Iterator::key() + * + * @return string key/local name of current element + */ + public function key() + { + return key($this->folders); + } + + /** + * implements Iterator::current() + * + * @return \Laminas\Mail\Storage\Folder current folder + */ + public function current() + { + return current($this->folders); + } + + /** + * implements Iterator::rewind() + */ + public function rewind() + { + reset($this->folders); + } + + /** + * get subfolder named $name + * + * @param string $name wanted subfolder + * @throws Exception\InvalidArgumentException + * @return \Laminas\Mail\Storage\Folder folder named $folder + */ + public function __get($name) + { + if (! isset($this->folders[$name])) { + throw new Exception\InvalidArgumentException("no subfolder named $name"); + } + + return $this->folders[$name]; + } + + /** + * add or replace subfolder named $name + * + * @param string $name local name of subfolder + * @param \Laminas\Mail\Storage\Folder $folder instance for new subfolder + */ + public function __set($name, Folder $folder) + { + $this->folders[$name] = $folder; + } + + /** + * remove subfolder named $name + * + * @param string $name local name of subfolder + */ + public function __unset($name) + { + unset($this->folders[$name]); + } + + /** + * magic method for easy output of global name + * + * @return string global name of folder + */ + public function __toString() + { + return (string) $this->getGlobalName(); + } + + /** + * get local name + * + * @return string local name + */ + public function getLocalName() + { + return $this->localName; + } + + /** + * get global name + * + * @return string global name + */ + public function getGlobalName() + { + return $this->globalName; + } + + /** + * is this folder selectable? + * + * @return bool selectable + */ + public function isSelectable() + { + return $this->selectable; + } + + /** + * check if folder has no subfolder + * + * @return bool true if no subfolders + */ + public function isLeaf() + { + return empty($this->folders); + } +} diff --git a/lib/laminas/laminas-mail/src/Storage/Folder/FolderInterface.php b/lib/laminas/laminas-mail/src/Storage/Folder/FolderInterface.php new file mode 100644 index 000000000..d2f17b236 --- /dev/null +++ b/lib/laminas/laminas-mail/src/Storage/Folder/FolderInterface.php @@ -0,0 +1,38 @@ +dirname) || ! is_dir($params->dirname)) { + throw new Exception\InvalidArgumentException('no valid dirname given in params'); + } + + $this->rootdir = rtrim($params->dirname, DIRECTORY_SEPARATOR) . DIRECTORY_SEPARATOR; + + $this->delim = isset($params->delim) ? $params->delim : '.'; + + $this->buildFolderTree(); + $this->selectFolder(! empty($params->folder) ? $params->folder : 'INBOX'); + $this->has['top'] = true; + $this->has['flags'] = true; + } + + /** + * find all subfolders and mbox files for folder structure + * + * Result is save in Storage\Folder instances with the root in $this->rootFolder. + * $parentFolder and $parentGlobalName are only used internally for recursion. + * + * @throws Exception\RuntimeException + */ + protected function buildFolderTree() + { + $this->rootFolder = new Storage\Folder('/', '/', false); + $this->rootFolder->INBOX = new Storage\Folder('INBOX', 'INBOX', true); + + ErrorHandler::start(E_WARNING); + $dh = opendir($this->rootdir); + $error = ErrorHandler::stop(); + if (! $dh) { + throw new Exception\RuntimeException("can't read folders in maildir", 0, $error); + } + $dirs = []; + + while (($entry = readdir($dh)) !== false) { + // maildir++ defines folders must start with . + if ($entry[0] != '.' || $entry == '.' || $entry == '..') { + continue; + } + + if ($this->isMaildir($this->rootdir . $entry)) { + $dirs[] = $entry; + } + } + closedir($dh); + + sort($dirs); + $stack = [null]; + $folderStack = [null]; + $parentFolder = $this->rootFolder; + $parent = '.'; + + foreach ($dirs as $dir) { + do { + if (strpos($dir, $parent) === 0) { + $local = substr($dir, strlen($parent)); + if (strpos($local, $this->delim) !== false) { + throw new Exception\RuntimeException('error while reading maildir'); + } + array_push($stack, $parent); + $parent = $dir . $this->delim; + $folder = new Storage\Folder($local, substr($dir, 1), true); + $parentFolder->$local = $folder; + array_push($folderStack, $parentFolder); + $parentFolder = $folder; + break; + } elseif ($stack) { + $parent = array_pop($stack); + $parentFolder = array_pop($folderStack); + } + } while ($stack); + if (! $stack) { + throw new Exception\RuntimeException('error while reading maildir'); + } + } + } + + /** + * get root folder or given folder + * + * @param string $rootFolder get folder structure for given folder, else root + * @throws \Laminas\Mail\Storage\Exception\InvalidArgumentException + * @return \Laminas\Mail\Storage\Folder root or wanted folder + */ + public function getFolders($rootFolder = null) + { + if (! $rootFolder || $rootFolder == 'INBOX') { + return $this->rootFolder; + } + + // rootdir is same as INBOX in maildir + if (strpos($rootFolder, 'INBOX' . $this->delim) === 0) { + $rootFolder = substr($rootFolder, 6); + } + $currentFolder = $this->rootFolder; + $subname = trim($rootFolder, $this->delim); + + while ($currentFolder) { + ErrorHandler::start(E_NOTICE); + list($entry, $subname) = explode($this->delim, $subname, 2); + ErrorHandler::stop(); + $currentFolder = $currentFolder->$entry; + if (! $subname) { + break; + } + } + + if ($currentFolder->getGlobalName() != rtrim($rootFolder, $this->delim)) { + throw new Exception\InvalidArgumentException("folder $rootFolder not found"); + } + return $currentFolder; + } + + /** + * select given folder + * + * folder must be selectable! + * + * @param Storage\Folder|string $globalName global name of folder or + * instance for subfolder + * @throws Exception\RuntimeException + */ + public function selectFolder($globalName) + { + $this->currentFolder = (string) $globalName; + + // getting folder from folder tree for validation + $folder = $this->getFolders($this->currentFolder); + + try { + $this->openMaildir($this->rootdir . '.' . $folder->getGlobalName()); + } catch (Exception\ExceptionInterface $e) { + // check what went wrong + if (! $folder->isSelectable()) { + throw new Exception\RuntimeException("{$this->currentFolder} is not selectable", 0, $e); + } + // seems like file has vanished; rebuilding folder tree - but it's still an exception + $this->buildFolderTree(); + throw new Exception\RuntimeException( + 'seems like the maildir has vanished; I have rebuilt the folder tree; ' + . 'search for another folder and try again', + 0, + $e + ); + } + } + + /** + * get Storage\Folder instance for current folder + * + * @return Storage\Folder instance of current folder + */ + public function getCurrentFolder() + { + return $this->currentFolder; + } +} diff --git a/lib/laminas/laminas-mail/src/Storage/Folder/Mbox.php b/lib/laminas/laminas-mail/src/Storage/Folder/Mbox.php new file mode 100644 index 000000000..e05a9a57a --- /dev/null +++ b/lib/laminas/laminas-mail/src/Storage/Folder/Mbox.php @@ -0,0 +1,213 @@ +filename)) { + throw new Exception\InvalidArgumentException(sprintf('use %s for a single file', Storage\Mbox::class)); + } + + if (! isset($params->dirname) || ! is_dir($params->dirname)) { + throw new Exception\InvalidArgumentException('no valid dirname given in params'); + } + + $this->rootdir = rtrim($params->dirname, DIRECTORY_SEPARATOR) . DIRECTORY_SEPARATOR; + + $this->buildFolderTree($this->rootdir); + $this->selectFolder(! empty($params->folder) ? $params->folder : 'INBOX'); + $this->has['top'] = true; + $this->has['uniqueid'] = false; + } + + /** + * find all subfolders and mbox files for folder structure + * + * Result is save in Storage\Folder instances with the root in $this->rootFolder. + * $parentFolder and $parentGlobalName are only used internally for recursion. + * + * @param string $currentDir call with root dir, also used for recursion. + * @param Storage\Folder|null $parentFolder used for recursion + * @param string $parentGlobalName used for recursion + * @throws Exception\InvalidArgumentException + */ + protected function buildFolderTree($currentDir, $parentFolder = null, $parentGlobalName = '') + { + if (! $parentFolder) { + $this->rootFolder = new Storage\Folder('/', '/', false); + $parentFolder = $this->rootFolder; + } + + ErrorHandler::start(E_WARNING); + $dh = opendir($currentDir); + ErrorHandler::stop(); + if (! $dh) { + throw new Exception\InvalidArgumentException("can't read dir $currentDir"); + } + while (($entry = readdir($dh)) !== false) { + // ignore hidden files for mbox + if ($entry[0] == '.') { + continue; + } + $absoluteEntry = $currentDir . $entry; + $globalName = $parentGlobalName . DIRECTORY_SEPARATOR . $entry; + if (is_file($absoluteEntry) && $this->isMboxFile($absoluteEntry)) { + $parentFolder->$entry = new Storage\Folder($entry, $globalName); + continue; + } + if (! is_dir($absoluteEntry) /* || $entry == '.' || $entry == '..' */) { + continue; + } + $folder = new Storage\Folder($entry, $globalName, false); + $parentFolder->$entry = $folder; + $this->buildFolderTree($absoluteEntry . DIRECTORY_SEPARATOR, $folder, $globalName); + } + + closedir($dh); + } + + /** + * get root folder or given folder + * + * @param string $rootFolder get folder structure for given folder, else root + * @return Storage\Folder root or wanted folder + * @throws Exception\InvalidArgumentException + */ + public function getFolders($rootFolder = null) + { + if (! $rootFolder) { + return $this->rootFolder; + } + + $currentFolder = $this->rootFolder; + $subname = trim($rootFolder, DIRECTORY_SEPARATOR); + while ($currentFolder) { + ErrorHandler::start(E_NOTICE); + list($entry, $subname) = explode(DIRECTORY_SEPARATOR, $subname, 2); + ErrorHandler::stop(); + $currentFolder = $currentFolder->$entry; + if (! $subname) { + break; + } + } + + if ($currentFolder->getGlobalName() != DIRECTORY_SEPARATOR . trim($rootFolder, DIRECTORY_SEPARATOR)) { + throw new Exception\InvalidArgumentException("folder $rootFolder not found"); + } + return $currentFolder; + } + + /** + * select given folder + * + * folder must be selectable! + * + * @param Storage\Folder|string $globalName global name of folder or + * instance for subfolder + * @throws Exception\RuntimeException + */ + public function selectFolder($globalName) + { + $this->currentFolder = (string) $globalName; + + // getting folder from folder tree for validation + $folder = $this->getFolders($this->currentFolder); + + try { + $this->openMboxFile($this->rootdir . $folder->getGlobalName()); + } catch (Exception\ExceptionInterface $e) { + // check what went wrong + if (! $folder->isSelectable()) { + throw new Exception\RuntimeException("{$this->currentFolder} is not selectable", 0, $e); + } + // seems like file has vanished; rebuilding folder tree - but it's still an exception + $this->buildFolderTree($this->rootdir); + throw new Exception\RuntimeException( + 'seems like the mbox file has vanished; I have rebuilt the folder tree; ' + . 'search for another folder and try again', + 0, + $e + ); + } + } + + /** + * get Storage\Folder instance for current folder + * + * @return Storage\Folder instance of current folder + * @throws Exception\ExceptionInterface + */ + public function getCurrentFolder() + { + return $this->currentFolder; + } + + /** + * magic method for serialize() + * + * with this method you can cache the mbox class + * + * @return array name of variables + */ + public function __sleep() + { + return array_merge(parent::__sleep(), ['currentFolder', 'rootFolder', 'rootdir']); + } + + /** + * magic method for unserialize(), with this method you can cache the mbox class + */ + public function __wakeup() + { + // if cache is stall selectFolder() rebuilds the tree on error + parent::__wakeup(); + } +} diff --git a/lib/laminas/laminas-mail/src/Storage/Imap.php b/lib/laminas/laminas-mail/src/Storage/Imap.php new file mode 100644 index 000000000..e4acf9e1e --- /dev/null +++ b/lib/laminas/laminas-mail/src/Storage/Imap.php @@ -0,0 +1,551 @@ + Mail\Storage::FLAG_PASSED, + '\Answered' => Mail\Storage::FLAG_ANSWERED, + '\Seen' => Mail\Storage::FLAG_SEEN, + '\Unseen' => Mail\Storage::FLAG_UNSEEN, + '\Deleted' => Mail\Storage::FLAG_DELETED, + '\Draft' => Mail\Storage::FLAG_DRAFT, + '\Flagged' => Mail\Storage::FLAG_FLAGGED, + ]; + + /** + * IMAP flags to search criteria + * @var array + */ + protected static $searchFlags = [ + '\Recent' => 'RECENT', + '\Answered' => 'ANSWERED', + '\Seen' => 'SEEN', + '\Unseen' => 'UNSEEN', + '\Deleted' => 'DELETED', + '\Draft' => 'DRAFT', + '\Flagged' => 'FLAGGED', + ]; + + /** + * Count messages all messages in current box + * + * @param null $flags + * @throws Exception\RuntimeException + * @throws Protocol\Exception\RuntimeException + * @return int number of messages + */ + public function countMessages($flags = null) + { + if (! $this->currentFolder) { + throw new Exception\RuntimeException('No selected folder to count'); + } + + if ($flags === null) { + return count($this->protocol->search(['ALL'])); + } + + $params = []; + foreach ((array) $flags as $flag) { + if (isset(static::$searchFlags[$flag])) { + $params[] = static::$searchFlags[$flag]; + } else { + $params[] = 'KEYWORD'; + $params[] = $this->protocol->escapeString($flag); + } + } + return count($this->protocol->search($params)); + } + + /** + * get a list of messages with number and size + * + * @param int $id number of message + * @return int|array size of given message of list with all messages as [num => size] + * @throws Protocol\Exception\RuntimeException + */ + public function getSize($id = 0) + { + if ($id) { + return $this->protocol->fetch('RFC822.SIZE', $id); + } + return $this->protocol->fetch('RFC822.SIZE', 1, INF); + } + + /** + * Fetch a message + * + * @param int $id number of message + * @return Message + * @throws Protocol\Exception\RuntimeException + */ + public function getMessage($id) + { + $data = $this->protocol->fetch(['FLAGS', 'RFC822.HEADER'], $id); + $header = $data['RFC822.HEADER']; + + $flags = []; + foreach ($data['FLAGS'] as $flag) { + $flags[] = isset(static::$knownFlags[$flag]) ? static::$knownFlags[$flag] : $flag; + } + + return new $this->messageClass(['handler' => $this, 'id' => $id, 'headers' => $header, 'flags' => $flags]); + } + + /* + * Get raw header of message or part + * + * @param int $id number of message + * @param null|array|string $part path to part or null for message header + * @param int $topLines include this many lines with header (after an empty line) + * @param int $topLines include this many lines with header (after an empty line) + * @return string raw header + * @throws Exception\RuntimeException + * @throws Protocol\Exception\RuntimeException + */ + public function getRawHeader($id, $part = null, $topLines = 0) + { + if ($part !== null) { + // TODO: implement + throw new Exception\RuntimeException('not implemented'); + } + + // TODO: toplines + return $this->protocol->fetch('RFC822.HEADER', $id); + } + + /* + * Get raw content of message or part + * + * @param int $id number of message + * @param null|array|string $part path to part or null for message content + * @return string raw content + * @throws Protocol\Exception\RuntimeException + * @throws Exception\RuntimeException + */ + public function getRawContent($id, $part = null) + { + if ($part !== null) { + // TODO: implement + throw new Exception\RuntimeException('not implemented'); + } + + return $this->protocol->fetch('RFC822.TEXT', $id); + } + + /** + * create instance with parameters + * + * Supported parameters are + * + * - user username + * - host hostname or ip address of IMAP server [optional, default = 'localhost'] + * - password password for user 'username' [optional, default = ''] + * - port port for IMAP server [optional, default = 110] + * - ssl 'SSL' or 'TLS' for secure sockets + * - folder select this folder [optional, default = 'INBOX'] + * + * @param array|Protocol\Imap $params mail reader specific parameters or configured Imap protocol object + * @throws Exception\RuntimeException + * @throws Exception\InvalidArgumentException + * @throws Protocol\Exception\RuntimeException + */ + public function __construct($params) + { + if (is_array($params)) { + $params = (object) $params; + } + + $this->has['flags'] = true; + + if ($params instanceof Protocol\Imap) { + $this->protocol = $params; + try { + $this->selectFolder('INBOX'); + } catch (Exception\ExceptionInterface $e) { + throw new Exception\RuntimeException('cannot select INBOX, is this a valid transport?', 0, $e); + } + return; + } + + if (! isset($params->user)) { + throw new Exception\InvalidArgumentException('need at least user in params'); + } + + $host = isset($params->host) ? $params->host : 'localhost'; + $password = isset($params->password) ? $params->password : ''; + $port = isset($params->port) ? $params->port : null; + $ssl = isset($params->ssl) ? $params->ssl : false; + + $this->protocol = new Protocol\Imap(); + + if (isset($params->novalidatecert)) { + $this->protocol->setNoValidateCert((bool)$params->novalidatecert); + } + + $this->protocol->connect($host, $port, $ssl); + if (! $this->protocol->login($params->user, $password)) { + throw new Exception\RuntimeException('cannot login, user or password wrong'); + } + $this->selectFolder(isset($params->folder) ? $params->folder : 'INBOX'); + } + + /** + * Close resource for mail lib. + * + * If you need to control, when the resource is closed. Otherwise the + * destructor would call this. + */ + public function close() + { + $this->currentFolder = ''; + $this->protocol->logout(); + } + + /** + * Keep the server busy. + * + * @throws Exception\RuntimeException + */ + public function noop() + { + if (! $this->protocol->noop()) { + throw new Exception\RuntimeException('could not do nothing'); + } + } + + /** + * Remove a message from server. + * + * If you're doing that from a web environment you should be careful and + * use a uniqueid as parameter if possible to identify the message. + * + * @param int $id number of message + * @throws Exception\RuntimeException + */ + public function removeMessage($id) + { + if (! $this->protocol->store([Mail\Storage::FLAG_DELETED], $id, null, '+')) { + throw new Exception\RuntimeException('cannot set deleted flag'); + } + // TODO: expunge here or at close? we can handle an error here better and are more fail safe + if (! $this->protocol->expunge()) { + throw new Exception\RuntimeException('message marked as deleted, but could not expunge'); + } + } + + /** + * get unique id for one or all messages + * + * if storage does not support unique ids it's the same as the message + * number. + * + * @param int|null $id message number + * @return array|string message number for given message or all messages as array + * @throws Protocol\Exception\RuntimeException + */ + public function getUniqueId($id = null) + { + if ($id) { + return $this->protocol->fetch('UID', $id); + } + + return $this->protocol->fetch('UID', 1, INF); + } + + /** + * get a message number from a unique id + * + * I.e. if you have a webmailer that supports deleting messages you should + * use unique ids as parameter and use this method to translate it to + * message number right before calling removeMessage() + * + * @param string $id unique id + * @throws Exception\InvalidArgumentException + * @return int message number + */ + public function getNumberByUniqueId($id) + { + // TODO: use search to find number directly + $ids = $this->getUniqueId(); + foreach ($ids as $k => $v) { + if ($v == $id) { + return $k; + } + } + + throw new Exception\InvalidArgumentException('unique id not found'); + } + + /** + * get root folder or given folder + * + * @param string $rootFolder get folder structure for given folder, else root + * @throws Exception\RuntimeException + * @throws Exception\InvalidArgumentException + * @throws Protocol\Exception\RuntimeException + * @return Folder root or wanted folder + */ + public function getFolders($rootFolder = null) + { + $folders = $this->protocol->listMailbox((string) $rootFolder); + if (! $folders) { + throw new Exception\InvalidArgumentException('folder not found'); + } + + ksort($folders, SORT_STRING); + $root = new Folder('/', '/', false); + $stack = [null]; + $folderStack = [null]; + $parentFolder = $root; + $parent = ''; + + foreach ($folders as $globalName => $data) { + do { + if (! $parent || strpos($globalName, $parent) === 0) { + $pos = strrpos($globalName, $data['delim']); + if ($pos === false) { + $localName = $globalName; + } else { + $localName = substr($globalName, $pos + 1); + } + $selectable = ! $data['flags'] || ! in_array('\\Noselect', $data['flags']); + + array_push($stack, $parent); + $parent = $globalName . $data['delim']; + $folder = new Folder($localName, $globalName, $selectable); + $parentFolder->$localName = $folder; + array_push($folderStack, $parentFolder); + $parentFolder = $folder; + $this->delimiter = $data['delim']; + break; + } elseif ($stack) { + $parent = array_pop($stack); + $parentFolder = array_pop($folderStack); + } + } while ($stack); + if (! $stack) { + throw new Exception\RuntimeException('error while constructing folder tree'); + } + } + + return $root; + } + + /** + * select given folder + * + * folder must be selectable! + * + * @param Folder|string $globalName global name of folder or instance for subfolder + * @throws Exception\RuntimeException + * @throws Protocol\Exception\RuntimeException + */ + public function selectFolder($globalName) + { + $this->currentFolder = $globalName; + if (! $this->protocol->select($this->currentFolder)) { + $this->currentFolder = ''; + throw new Exception\RuntimeException('cannot change folder, maybe it does not exist'); + } + } + + /** + * get Folder instance for current folder + * + * @return Folder instance of current folder + */ + public function getCurrentFolder() + { + return $this->currentFolder; + } + + /** + * create a new folder + * + * This method also creates parent folders if necessary. Some mail storages + * may restrict, which folder may be used as parent or which chars may be + * used in the folder name + * + * @param string $name global name of folder, local name if $parentFolder + * is set + * @param string|Folder $parentFolder parent folder for new folder, else + * root folder is parent + * @throws Exception\RuntimeException + */ + public function createFolder($name, $parentFolder = null) + { + // TODO: we assume / as the hierarchy delim - need to get that from the folder class! + if ($parentFolder instanceof Folder) { + $folder = $parentFolder->getGlobalName() . '/' . $name; + } elseif ($parentFolder !== null) { + $folder = $parentFolder . '/' . $name; + } else { + $folder = $name; + } + + if (! $this->protocol->create($folder)) { + throw new Exception\RuntimeException('cannot create folder'); + } + } + + /** + * remove a folder + * + * @param string|Folder $name name or instance of folder + * @throws Exception\RuntimeException + */ + public function removeFolder($name) + { + if ($name instanceof Folder) { + $name = $name->getGlobalName(); + } + + if (! $this->protocol->delete($name)) { + throw new Exception\RuntimeException('cannot delete folder'); + } + } + + /** + * rename and/or move folder + * + * The new name has the same restrictions as in createFolder() + * + * @param string|Folder $oldName name or instance of folder + * @param string $newName new global name of folder + * @throws Exception\RuntimeException + */ + public function renameFolder($oldName, $newName) + { + if ($oldName instanceof Folder) { + $oldName = $oldName->getGlobalName(); + } + + if (! $this->protocol->rename($oldName, $newName)) { + throw new Exception\RuntimeException('cannot rename folder'); + } + } + + /** + * append a new message to mail storage + * + * @param string $message message as string or instance of message class + * @param null|string|Folder $folder folder for new message, else current + * folder is taken + * @param null|array $flags set flags for new message, else a default set + * is used + * @throws Exception\RuntimeException + */ + public function appendMessage($message, $folder = null, $flags = null) + { + if ($folder === null) { + $folder = $this->currentFolder; + } + + if ($flags === null) { + $flags = [Mail\Storage::FLAG_SEEN]; + } + + // TODO: handle class instances for $message + if (! $this->protocol->append($folder, $message, $flags)) { + throw new Exception\RuntimeException( + 'cannot create message, please check if the folder exists and your flags' + ); + } + } + + /** + * copy an existing message + * + * @param int $id number of message + * @param string|Folder $folder name or instance of target folder + * @throws Exception\RuntimeException + */ + public function copyMessage($id, $folder) + { + if (! $this->protocol->copy($folder, $id)) { + throw new Exception\RuntimeException('cannot copy message, does the folder exist?'); + } + } + + /** + * move an existing message + * + * NOTE: IMAP has no native move command, thus it's emulated with copy and delete + * + * @param int $id number of message + * @param string|Folder $folder name or instance of target folder + * @throws Exception\RuntimeException + */ + public function moveMessage($id, $folder) + { + $this->copyMessage($id, $folder); + $this->removeMessage($id); + } + + /** + * set flags for message + * + * NOTE: this method can't set the recent flag. + * + * @param int $id number of message + * @param array $flags new flags for message + * @throws Exception\RuntimeException + */ + public function setFlags($id, $flags) + { + if (! $this->protocol->store($flags, $id)) { + throw new Exception\RuntimeException( + 'cannot set flags, have you tried to set the recent flag or special chars?' + ); + } + } + + /** + * get IMAP delimiter + * + * @return string|null + */ + public function delimiter() + { + if (! isset($this->delimiter)) { + $this->getFolders(); + } + return $this->delimiter; + } +} diff --git a/lib/laminas/laminas-mail/src/Storage/Maildir.php b/lib/laminas/laminas-mail/src/Storage/Maildir.php new file mode 100644 index 000000000..aab9d0c56 --- /dev/null +++ b/lib/laminas/laminas-mail/src/Storage/Maildir.php @@ -0,0 +1,416 @@ + Mail\Storage::FLAG_DRAFT, + 'F' => Mail\Storage::FLAG_FLAGGED, + 'P' => Mail\Storage::FLAG_PASSED, + 'R' => Mail\Storage::FLAG_ANSWERED, + 'S' => Mail\Storage::FLAG_SEEN, + 'T' => Mail\Storage::FLAG_DELETED, + ]; + + // TODO: getFlags($id) for fast access if headers are not needed (i.e. just setting flags)? + + /** + * Count messages all messages in current box + * + * @param mixed $flags + * @return int number of messages + */ + public function countMessages($flags = null) + { + if ($flags === null) { + return count($this->files); + } + + $count = 0; + if (! is_array($flags)) { + foreach ($this->files as $file) { + if (isset($file['flaglookup'][$flags])) { + ++$count; + } + } + return $count; + } + + $flags = array_flip($flags); + foreach ($this->files as $file) { + foreach ($flags as $flag => $v) { + if (! isset($file['flaglookup'][$flag])) { + continue 2; + } + } + ++$count; + } + return $count; + } + + /** + * Get one or all fields from file structure. Also checks if message is valid + * + * @param int $id message number + * @param string|null $field wanted field + * @throws Exception\InvalidArgumentException + * @return string|array wanted field or all fields as array + */ + protected function getFileData($id, $field = null) + { + if (! isset($this->files[$id - 1])) { + throw new Exception\InvalidArgumentException('id does not exist'); + } + + if (! $field) { + return $this->files[$id - 1]; + } + + if (! isset($this->files[$id - 1][$field])) { + throw new Exception\InvalidArgumentException('field does not exist'); + } + + return $this->files[$id - 1][$field]; + } + + /** + * Get a list of messages with number and size + * + * @param int|null $id number of message or null for all messages + * @return int|array size of given message of list with all messages as array(num => size) + */ + public function getSize($id = null) + { + if ($id !== null) { + $filedata = $this->getFileData($id); + return isset($filedata['size']) ? $filedata['size'] : filesize($filedata['filename']); + } + + $result = []; + foreach ($this->files as $num => $data) { + $result[$num + 1] = isset($data['size']) ? $data['size'] : filesize($data['filename']); + } + + return $result; + } + + /** + * Fetch a message + * + * @param int $id number of message + * @return \Laminas\Mail\Storage\Message\File + * @throws \Laminas\Mail\Storage\Exception\ExceptionInterface + */ + public function getMessage($id) + { + // TODO that's ugly, would be better to let the message class decide + if (\trim($this->messageClass, '\\') === Message\File::class + || is_subclass_of($this->messageClass, Message\File::class) + ) { + return new $this->messageClass([ + 'file' => $this->getFileData($id, 'filename'), + 'flags' => $this->getFileData($id, 'flags'), + ]); + } + + return new $this->messageClass([ + 'handler' => $this, + 'id' => $id, + 'headers' => $this->getRawHeader($id), + 'flags' => $this->getFileData($id, 'flags'), + ]); + } + + /* + * Get raw header of message or part + * + * @param int $id number of message + * @param null|array|string $part path to part or null for message header + * @param int $topLines include this many lines with header (after an empty line) + * @throws Exception\RuntimeException + * @return string raw header + */ + public function getRawHeader($id, $part = null, $topLines = 0) + { + if ($part !== null) { + // TODO: implement + throw new Exception\RuntimeException('not implemented'); + } + + $fh = fopen($this->getFileData($id, 'filename'), 'r'); + + $content = ''; + while (! feof($fh)) { + $line = fgets($fh); + if (! trim($line)) { + break; + } + $content .= $line; + } + + fclose($fh); + return $content; + } + + /* + * Get raw content of message or part + * + * @param int $id number of message + * @param null|array|string $part path to part or null for message content + * @throws Exception\RuntimeException + * @return string raw content + */ + public function getRawContent($id, $part = null) + { + if ($part !== null) { + // TODO: implement + throw new Exception\RuntimeException('not implemented'); + } + + $fh = fopen($this->getFileData($id, 'filename'), 'r'); + + while (! feof($fh)) { + $line = fgets($fh); + if (! trim($line)) { + break; + } + } + + $content = stream_get_contents($fh); + fclose($fh); + return $content; + } + + /** + * Create instance with parameters + * Supported parameters are: + * - dirname dirname of mbox file + * + * @param $params array mail reader specific parameters + * @throws Exception\InvalidArgumentException + */ + public function __construct($params) + { + if (is_array($params)) { + $params = (object) $params; + } + + if (! isset($params->dirname) || ! is_dir($params->dirname)) { + throw new Exception\InvalidArgumentException('no valid dirname given in params'); + } + + if (! $this->isMaildir($params->dirname)) { + throw new Exception\InvalidArgumentException('invalid maildir given'); + } + + $this->has['top'] = true; + $this->has['flags'] = true; + $this->openMaildir($params->dirname); + } + + /** + * check if a given dir is a valid maildir + * + * @param string $dirname name of dir + * @return bool dir is valid maildir + */ + protected function isMaildir($dirname) + { + if (file_exists($dirname . '/new') && ! is_dir($dirname . '/new')) { + return false; + } + if (file_exists($dirname . '/tmp') && ! is_dir($dirname . '/tmp')) { + return false; + } + return is_dir($dirname . '/cur'); + } + + /** + * open given dir as current maildir + * + * @param string $dirname name of maildir + * @throws Exception\RuntimeException + */ + protected function openMaildir($dirname) + { + if ($this->files) { + $this->close(); + } + + ErrorHandler::start(E_WARNING); + $dh = opendir($dirname . '/cur/'); + $error = ErrorHandler::stop(); + if (! $dh) { + throw new Exception\RuntimeException('cannot open maildir', 0, $error); + } + $this->getMaildirFiles($dh, $dirname . '/cur/'); + closedir($dh); + + ErrorHandler::start(E_WARNING); + $dh = opendir($dirname . '/new/'); + $error = ErrorHandler::stop(); + if (! $dh) { + throw new Exception\RuntimeException('cannot read recent mails in maildir', 0, $error); + } + + $this->getMaildirFiles($dh, $dirname . '/new/', [Mail\Storage::FLAG_RECENT]); + closedir($dh); + } + + /** + * find all files in opened dir handle and add to maildir files + * + * @param resource $dh dir handle used for search + * @param string $dirname dirname of dir in $dh + * @param array $defaultFlags default flags for given dir + */ + protected function getMaildirFiles($dh, $dirname, $defaultFlags = []) + { + while (($entry = readdir($dh)) !== false) { + if ($entry[0] == '.' || ! is_file($dirname . $entry)) { + continue; + } + + ErrorHandler::start(E_NOTICE); + list($uniq, $info) = explode(':', $entry, 2); + list(, $size) = explode(',', $uniq, 2); + ErrorHandler::stop(); + if ($size && $size[0] == 'S' && $size[1] == '=') { + $size = substr($size, 2); + } + if (! ctype_digit($size)) { + $size = null; + } + + ErrorHandler::start(E_NOTICE); + list($version, $flags) = explode(',', $info, 2); + ErrorHandler::stop(); + if ($version != 2) { + $flags = ''; + } + + $namedFlags = $defaultFlags; + $length = strlen($flags); + for ($i = 0; $i < $length; ++$i) { + $flag = $flags[$i]; + $namedFlags[$flag] = isset(static::$knownFlags[$flag]) ? static::$knownFlags[$flag] : $flag; + } + + $data = [ + 'uniq' => $uniq, + 'flags' => $namedFlags, + 'flaglookup' => array_flip($namedFlags), + 'filename' => $dirname . $entry + ]; + if ($size !== null) { + $data['size'] = (int) $size; + } + $this->files[] = $data; + } + \usort($this->files, function ($a, $b) { + return \strcmp($a['filename'], $b['filename']); + }); + } + + /** + * Close resource for mail lib. If you need to control, when the resource + * is closed. Otherwise the destructor would call this. + * + */ + public function close() + { + $this->files = []; + } + + /** + * Waste some CPU cycles doing nothing. + * + * @return bool always return true + */ + public function noop() + { + return true; + } + + /** + * stub for not supported message deletion + * + * @param $id + * @throws Exception\RuntimeException + */ + public function removeMessage($id) + { + throw new Exception\RuntimeException('maildir is (currently) read-only'); + } + + /** + * get unique id for one or all messages + * + * if storage does not support unique ids it's the same as the message number + * + * @param int|null $id message number + * @return array|string message number for given message or all messages as array + */ + public function getUniqueId($id = null) + { + if ($id) { + return $this->getFileData($id, 'uniq'); + } + + $ids = []; + foreach ($this->files as $num => $file) { + $ids[$num + 1] = $file['uniq']; + } + return $ids; + } + + /** + * get a message number from a unique id + * + * I.e. if you have a webmailer that supports deleting messages you should use unique ids + * as parameter and use this method to translate it to message number right before calling removeMessage() + * + * @param string $id unique id + * @throws Exception\InvalidArgumentException + * @return int message number + */ + public function getNumberByUniqueId($id) + { + foreach ($this->files as $num => $file) { + if ($file['uniq'] == $id) { + return $num + 1; + } + } + + throw new Exception\InvalidArgumentException('unique id not found'); + } +} diff --git a/lib/laminas/laminas-mail/src/Storage/Mbox.php b/lib/laminas/laminas-mail/src/Storage/Mbox.php new file mode 100644 index 000000000..eb98b59d8 --- /dev/null +++ b/lib/laminas/laminas-mail/src/Storage/Mbox.php @@ -0,0 +1,415 @@ + start, 'separator' => headersep, 'end' => end) + * @var array + */ + protected $positions; + + /** + * used message class, change it in an extended class to extend the returned message class + * @var string + */ + protected $messageClass = Message\File::class; + + /** + * end of Line for messages + * + * @var string|null + */ + protected $messageEOL; + + /** + * Count messages all messages in current box + * + * @return int number of messages + * @throws \Laminas\Mail\Storage\Exception\ExceptionInterface + */ + public function countMessages() + { + return count($this->positions); + } + + /** + * Get a list of messages with number and size + * + * @param int|null $id number of message or null for all messages + * @return int|array size of given message of list with all messages as array(num => size) + */ + public function getSize($id = 0) + { + if ($id) { + $pos = $this->positions[$id - 1]; + return $pos['end'] - $pos['start']; + } + + $result = []; + foreach ($this->positions as $num => $pos) { + $result[$num + 1] = $pos['end'] - $pos['start']; + } + + return $result; + } + + /** + * Get positions for mail message or throw exception if id is invalid + * + * @param int $id number of message + * @throws Exception\InvalidArgumentException + * @return array positions as in positions + */ + protected function getPos($id) + { + if (! isset($this->positions[$id - 1])) { + throw new Exception\InvalidArgumentException('id does not exist'); + } + + return $this->positions[$id - 1]; + } + + /** + * Fetch a message + * + * @param int $id number of message + * @return \Laminas\Mail\Storage\Message\File + * @throws \Laminas\Mail\Storage\Exception\ExceptionInterface + */ + public function getMessage($id) + { + // TODO that's ugly, would be better to let the message class decide + if (is_subclass_of($this->messageClass, Message\File::class) + || strtolower($this->messageClass) === strtolower(Message\File::class)) { + // TODO top/body lines + $messagePos = $this->getPos($id); + + $messageClassParams = [ + 'file' => $this->fh, + 'startPos' => $messagePos['start'], + 'endPos' => $messagePos['end'] + ]; + + if (isset($this->messageEOL)) { + $messageClassParams['EOL'] = $this->messageEOL; + } + + return new $this->messageClass($messageClassParams); + } + + $bodyLines = 0; // TODO: need a way to change that + + $message = $this->getRawHeader($id); + // file pointer is after headers now + if ($bodyLines) { + $message .= "\n"; + while ($bodyLines-- && ftell($this->fh) < $this->positions[$id - 1]['end']) { + $message .= fgets($this->fh); + } + } + + return new $this->messageClass(['handler' => $this, 'id' => $id, 'headers' => $message]); + } + + /* + * Get raw header of message or part + * + * @param int $id number of message + * @param null|array|string $part path to part or null for message header + * @param int $topLines include this many lines with header (after an empty line) + * @return string raw header + * @throws \Laminas\Mail\Protocol\Exception\ExceptionInterface + * @throws \Laminas\Mail\Storage\Exception\ExceptionInterface + */ + public function getRawHeader($id, $part = null, $topLines = 0) + { + if ($part !== null) { + // TODO: implement + throw new Exception\RuntimeException('not implemented'); + } + $messagePos = $this->getPos($id); + // TODO: toplines + return stream_get_contents($this->fh, $messagePos['separator'] - $messagePos['start'], $messagePos['start']); + } + + /* + * Get raw content of message or part + * + * @param int $id number of message + * @param null|array|string $part path to part or null for message content + * @return string raw content + * @throws \Laminas\Mail\Protocol\Exception\ExceptionInterface + * @throws \Laminas\Mail\Storage\Exception\ExceptionInterface + */ + public function getRawContent($id, $part = null) + { + if ($part !== null) { + // TODO: implement + throw new Exception\RuntimeException('not implemented'); + } + $messagePos = $this->getPos($id); + return stream_get_contents($this->fh, $messagePos['end'] - $messagePos['separator'], $messagePos['separator']); + } + + /** + * Create instance with parameters + * Supported parameters are: + * - filename filename of mbox file + * + * @param $params array mail reader specific parameters + * @throws Exception\InvalidArgumentException + */ + public function __construct($params) + { + if (is_array($params)) { + $params = (object) $params; + } + + if (! isset($params->filename)) { + throw new Exception\InvalidArgumentException('no valid filename given in params'); + } + + if (isset($params->messageEOL)) { + $this->messageEOL = (string) $params->messageEOL; + } + + $this->openMboxFile($params->filename); + $this->has['top'] = true; + $this->has['uniqueid'] = false; + } + + /** + * check if given file is a mbox file + * + * if $file is a resource its file pointer is moved after the first line + * + * @param resource|string $file stream resource of name of file + * @param bool $fileIsString file is string or resource + * @return bool file is mbox file + */ + protected function isMboxFile($file, $fileIsString = true) + { + if ($fileIsString) { + ErrorHandler::start(E_WARNING); + $file = fopen($file, 'r'); + ErrorHandler::stop(); + if (! $file) { + return false; + } + } else { + fseek($file, 0); + } + + $result = false; + + $line = fgets($file) ?: ''; + if (strpos($line, 'From ') === 0) { + $result = true; + } + + if ($fileIsString) { + ErrorHandler::start(E_WARNING); + fclose($file); + ErrorHandler::stop(); + } + + return $result; + } + + /** + * open given file as current mbox file + * + * @param string $filename filename of mbox file + * @throws Exception\RuntimeException + * @throws Exception\InvalidArgumentException + */ + protected function openMboxFile($filename) + { + if ($this->fh) { + $this->close(); + } + + if (is_dir($filename)) { + throw new Exception\InvalidArgumentException('file is not a valid mbox file'); + } + + ErrorHandler::start(); + $this->fh = fopen($filename, 'r'); + $error = ErrorHandler::stop(); + if (! $this->fh) { + throw new Exception\RuntimeException('cannot open mbox file', 0, $error); + } + $this->filename = $filename; + $this->filemtime = filemtime($this->filename); + + if (! $this->isMboxFile($this->fh, false)) { + ErrorHandler::start(E_WARNING); + fclose($this->fh); + $error = ErrorHandler::stop(); + throw new Exception\InvalidArgumentException('file is not a valid mbox format', 0, $error); + } + + $messagePos = ['start' => ftell($this->fh), 'separator' => 0, 'end' => 0]; + while (($line = fgets($this->fh)) !== false) { + if (strpos($line, 'From ') === 0) { + $messagePos['end'] = ftell($this->fh) - strlen($line) - 2; // + newline + if (! $messagePos['separator']) { + $messagePos['separator'] = $messagePos['end']; + } + $this->positions[] = $messagePos; + $messagePos = ['start' => ftell($this->fh), 'separator' => 0, 'end' => 0]; + } + if (! $messagePos['separator'] && ! trim($line)) { + $messagePos['separator'] = ftell($this->fh); + } + } + + $messagePos['end'] = ftell($this->fh); + if (! $messagePos['separator']) { + $messagePos['separator'] = $messagePos['end']; + } + $this->positions[] = $messagePos; + } + + /** + * Close resource for mail lib. If you need to control, when the resource + * is closed. Otherwise the destructor would call this. + * + */ + public function close() + { + ErrorHandler::start(E_WARNING); + fclose($this->fh); + ErrorHandler::stop(); + $this->positions = []; + } + + + /** + * Waste some CPU cycles doing nothing. + * + * @return bool always return true + */ + public function noop() + { + return true; + } + + + /** + * stub for not supported message deletion + * + * @param $id + * @throws Exception\RuntimeException + */ + public function removeMessage($id) + { + throw new Exception\RuntimeException('mbox is read-only'); + } + + /** + * get unique id for one or all messages + * + * Mbox does not support unique ids (yet) - it's always the same as the message number. + * That shouldn't be a problem, because we can't change mbox files. Therefor the message + * number is save enough. + * + * @param int|null $id message number + * @return array|string message number for given message or all messages as array + * @throws \Laminas\Mail\Storage\Exception\ExceptionInterface + */ + public function getUniqueId($id = null) + { + if ($id) { + // check if id exists + $this->getPos($id); + return $id; + } + + $range = range(1, $this->countMessages()); + return array_combine($range, $range); + } + + /** + * get a message number from a unique id + * + * I.e. if you have a webmailer that supports deleting messages you should use unique ids + * as parameter and use this method to translate it to message number right before calling removeMessage() + * + * @param string $id unique id + * @return int message number + * @throws \Laminas\Mail\Storage\Exception\ExceptionInterface + */ + public function getNumberByUniqueId($id) + { + // check if id exists + $this->getPos($id); + return $id; + } + + /** + * magic method for serialize() + * + * with this method you can cache the mbox class + * + * @return array name of variables + */ + public function __sleep() + { + return ['filename', 'positions', 'filemtime']; + } + + /** + * magic method for unserialize() + * + * with this method you can cache the mbox class + * for cache validation the mtime of the mbox file is used + * + * @throws Exception\RuntimeException + */ + public function __wakeup() + { + ErrorHandler::start(); + $filemtime = filemtime($this->filename); + ErrorHandler::stop(); + if ($this->filemtime != $filemtime) { + $this->close(); + $this->openMboxFile($this->filename); + } else { + ErrorHandler::start(); + $this->fh = fopen($this->filename, 'r'); + $error = ErrorHandler::stop(); + if (! $this->fh) { + throw new Exception\RuntimeException('cannot open mbox file', 0, $error); + } + } + } +} diff --git a/lib/laminas/laminas-mail/src/Storage/Message.php b/lib/laminas/laminas-mail/src/Storage/Message.php new file mode 100644 index 000000000..04fca5e63 --- /dev/null +++ b/lib/laminas/laminas-mail/src/Storage/Message.php @@ -0,0 +1,86 @@ +flags = array_combine($params['flags'], $params['flags']); + } + + parent::__construct($params); + } + + /** + * return toplines as found after headers + * + * @return string toplines + */ + public function getTopLines() + { + return $this->topLines; + } + + /** + * check if flag is set + * + * @param mixed $flag a flag name, use constants defined in \Laminas\Mail\Storage + * @return bool true if set, otherwise false + */ + public function hasFlag($flag) + { + return isset($this->flags[$flag]); + } + + /** + * get all set flags + * + * @return array array with flags, key and value are the same for easy lookup + */ + public function getFlags() + { + return $this->flags; + } +} diff --git a/lib/laminas/laminas-mail/src/Storage/Message/File.php b/lib/laminas/laminas-mail/src/Storage/Message/File.php new file mode 100644 index 000000000..9034eb7e3 --- /dev/null +++ b/lib/laminas/laminas-mail/src/Storage/Message/File.php @@ -0,0 +1,70 @@ +flags = array_combine($params['flags'], $params['flags']); + } + + parent::__construct($params); + } + + /** + * return toplines as found after headers + * + * @return string toplines + */ + public function getTopLines() + { + return $this->topLines; + } + + /** + * check if flag is set + * + * @param mixed $flag a flag name, use constants defined in \Laminas\Mail\Storage + * @return bool true if set, otherwise false + */ + public function hasFlag($flag) + { + return isset($this->flags[$flag]); + } + + /** + * get all set flags + * + * @return array array with flags, key and value are the same for easy lookup + */ + public function getFlags() + { + return $this->flags; + } +} diff --git a/lib/laminas/laminas-mail/src/Storage/Message/MessageInterface.php b/lib/laminas/laminas-mail/src/Storage/Message/MessageInterface.php new file mode 100644 index 000000000..6f924efdd --- /dev/null +++ b/lib/laminas/laminas-mail/src/Storage/Message/MessageInterface.php @@ -0,0 +1,34 @@ + value) or string, if a content part is found it's used as toplines + * - noToplines ignore content found after headers in param 'headers' + * - content content as string + * - strict strictly parse raw content + * + * @param array $params full message with or without headers + * @throws Exception\InvalidArgumentException + */ + public function __construct(array $params) + { + if (isset($params['handler'])) { + if (! $params['handler'] instanceof AbstractStorage) { + throw new Exception\InvalidArgumentException('handler is not a valid mail handler'); + } + if (! isset($params['id'])) { + throw new Exception\InvalidArgumentException('need a message id with a handler'); + } + + $this->mail = $params['handler']; + $this->messageNum = $params['id']; + } + + $params['strict'] = isset($params['strict']) ? $params['strict'] : false; + + if (isset($params['raw'])) { + Mime\Decode::splitMessage( + $params['raw'], + $this->headers, + $this->content, + Mime\Mime::LINEEND, + $params['strict'] + ); + } elseif (isset($params['headers'])) { + if (is_array($params['headers'])) { + $this->headers = new Headers(); + $this->headers->addHeaders($params['headers']); + } else { + if (empty($params['noToplines'])) { + Mime\Decode::splitMessage($params['headers'], $this->headers, $this->topLines); + } else { + $this->headers = Headers::fromString($params['headers']); + } + } + + if (isset($params['content'])) { + $this->content = $params['content']; + } + } + } + + /** + * Check if part is a multipart message + * + * @return bool if part is multipart + */ + public function isMultipart() + { + try { + return stripos($this->contentType, 'multipart/') === 0; + } catch (Exception\ExceptionInterface $e) { + return false; + } + } + + + /** + * Body of part + * + * If part is multipart the raw content of this part with all sub parts is returned + * + * @throws Exception\RuntimeException + * @return string body + */ + public function getContent() + { + if ($this->content !== null) { + return $this->content; + } + + if ($this->mail) { + return $this->mail->getRawContent($this->messageNum); + } + + throw new Exception\RuntimeException('no content'); + } + + /** + * Return size of part + * + * Quite simple implemented currently (not decoding). Handle with care. + * + * @return int size + */ + public function getSize() + { + return strlen($this->getContent()); + } + + + /** + * Cache content and split in parts if multipart + * + * @throws Exception\RuntimeException + * @return null + */ + protected function cacheContent() + { + // caching content if we can't fetch parts + if ($this->content === null && $this->mail) { + $this->content = $this->mail->getRawContent($this->messageNum); + } + + if (! $this->isMultipart()) { + return; + } + + // split content in parts + $boundary = $this->getHeaderField('content-type', 'boundary'); + if (! $boundary) { + throw new Exception\RuntimeException('no boundary found in content type to split message'); + } + $parts = Mime\Decode::splitMessageStruct($this->content, $boundary); + if ($parts === null) { + return; + } + $counter = 1; + foreach ($parts as $part) { + $this->parts[$counter++] = new static(['headers' => $part['header'], 'content' => $part['body']]); + } + } + + /** + * Get part of multipart message + * + * @param int $num number of part starting with 1 for first part + * @throws Exception\RuntimeException + * @return Part wanted part + */ + public function getPart($num) + { + if (isset($this->parts[$num])) { + return $this->parts[$num]; + } + + if (! $this->mail && $this->content === null) { + throw new Exception\RuntimeException('part not found'); + } + + if ($this->mail && $this->mail->hasFetchPart) { + // TODO: fetch part + // return + } + + $this->cacheContent(); + + if (! isset($this->parts[$num])) { + throw new Exception\RuntimeException('part not found'); + } + + return $this->parts[$num]; + } + + /** + * Count parts of a multipart part + * + * @return int number of sub-parts + */ + public function countParts() + { + if ($this->countParts) { + return $this->countParts; + } + + $this->countParts = count($this->parts); + if ($this->countParts) { + return $this->countParts; + } + + if ($this->mail && $this->mail->hasFetchPart) { + // TODO: fetch part + // return + } + + $this->cacheContent(); + + $this->countParts = count($this->parts); + return $this->countParts; + } + + /** + * Access headers collection + * + * Lazy-loads if not already attached. + * + * @return Headers + * @throws Exception\RuntimeException + */ + public function getHeaders() + { + if (null === $this->headers) { + if ($this->mail) { + $part = $this->mail->getRawHeader($this->messageNum); + $this->headers = Headers::fromString($part); + } else { + $this->headers = new Headers(); + } + } + if (! $this->headers instanceof Headers) { + throw new Exception\RuntimeException( + '$this->headers must be an instance of Headers' + ); + } + + return $this->headers; + } + + /** + * Get a header in specified format + * + * Internally headers that occur more than once are saved as array, all other as string. If $format + * is set to string implode is used to concat the values (with Mime::LINEEND as delim). + * + * @param string $name name of header, matches case-insensitive, but camel-case is replaced with dashes + * @param string $format change type of return value to 'string' or 'array' + * @throws Exception\InvalidArgumentException + * @return string|array|HeaderInterface|\ArrayIterator value of header in wanted or internal format + */ + public function getHeader($name, $format = null) + { + $header = $this->getHeaders()->get($name); + if ($header === false) { + $lowerName = strtolower(preg_replace('%([a-z])([A-Z])%', '\1-\2', $name)); + $header = $this->getHeaders()->get($lowerName); + if ($header === false) { + throw new Exception\InvalidArgumentException( + "Header with Name $name or $lowerName not found" + ); + } + } + + switch ($format) { + case 'string': + if ($header instanceof HeaderInterface) { + $return = $header->getFieldValue(HeaderInterface::FORMAT_RAW); + } else { + $return = ''; + foreach ($header as $h) { + $return .= $h->getFieldValue(HeaderInterface::FORMAT_RAW) + . Mime\Mime::LINEEND; + } + $return = trim($return, Mime\Mime::LINEEND); + } + break; + case 'array': + if ($header instanceof HeaderInterface) { + $return = [$header->getFieldValue()]; + } else { + $return = []; + foreach ($header as $h) { + $return[] = $h->getFieldValue(HeaderInterface::FORMAT_RAW); + } + } + break; + default: + $return = $header; + } + + return $return; + } + + /** + * Get a specific field from a header like content type or all fields as array + * + * If the header occurs more than once, only the value from the first header + * is returned. + * + * Throws an Exception if the requested header does not exist. If + * the specific header field does not exist, returns null. + * + * @param string $name name of header, like in getHeader() + * @param string $wantedPart the wanted part, default is first, if null an array with all parts is returned + * @param string $firstName key name for the first part + * @return string|array wanted part or all parts as array($firstName => firstPart, partname => value) + * @throws \Laminas\Mime\Exception\RuntimeException + */ + public function getHeaderField($name, $wantedPart = '0', $firstName = '0') + { + return Mime\Decode::splitHeaderField(current($this->getHeader($name, 'array')), $wantedPart, $firstName); + } + + /** + * Getter for mail headers - name is matched in lowercase + * + * This getter is short for Part::getHeader($name, 'string') + * + * @see Part::getHeader() + * + * @param string $name header name + * @return string value of header + * @throws Exception\ExceptionInterface + */ + public function __get($name) + { + return $this->getHeader($name, 'string'); + } + + /** + * Isset magic method proxy to hasHeader + * + * This method is short syntax for Part::hasHeader($name); + * + * @see Part::hasHeader + * + * @param string + * @return bool + */ + public function __isset($name) + { + return $this->getHeaders()->has($name); + } + + /** + * magic method to get content of part + * + * @return string content + */ + public function __toString() + { + return $this->getContent(); + } + + /** + * implements RecursiveIterator::hasChildren() + * + * @return bool current element has children/is multipart + */ + public function hasChildren() + { + $current = $this->current(); + return $current && $current instanceof Part && $current->isMultipart(); + } + + /** + * implements RecursiveIterator::getChildren() + * + * @return Part same as self::current() + */ + public function getChildren() + { + return $this->current(); + } + + /** + * implements Iterator::valid() + * + * @return bool check if there's a current element + */ + public function valid() + { + if ($this->countParts === null) { + $this->countParts(); + } + return $this->iterationPos && $this->iterationPos <= $this->countParts; + } + + /** + * implements Iterator::next() + */ + public function next() + { + ++$this->iterationPos; + } + + /** + * implements Iterator::key() + * + * @return string key/number of current part + */ + public function key() + { + return $this->iterationPos; + } + + /** + * implements Iterator::current() + * + * @return Part current part + */ + public function current() + { + return $this->getPart($this->iterationPos); + } + + /** + * implements Iterator::rewind() + */ + public function rewind() + { + $this->countParts(); + $this->iterationPos = 1; + } +} diff --git a/lib/laminas/laminas-mail/src/Storage/Part/Exception/ExceptionInterface.php b/lib/laminas/laminas-mail/src/Storage/Part/Exception/ExceptionInterface.php new file mode 100644 index 000000000..d6b387b0c --- /dev/null +++ b/lib/laminas/laminas-mail/src/Storage/Part/Exception/ExceptionInterface.php @@ -0,0 +1,15 @@ +fh = fopen($params['file'], 'r'); + } else { + $this->fh = $params['file']; + } + if (! $this->fh) { + throw new Exception\RuntimeException('could not open file'); + } + if (isset($params['startPos'])) { + fseek($this->fh, $params['startPos']); + } + $header = ''; + $endPos = isset($params['endPos']) ? $params['endPos'] : null; + while (($endPos === null || ftell($this->fh) < $endPos) && trim($line = fgets($this->fh))) { + $header .= $line; + } + + if (isset($params['EOL'])) { + $this->headers = Headers::fromString($header, $params['EOL']); + } else { + $this->headers = Headers::fromString($header); + } + + $this->contentPos[0] = ftell($this->fh); + if ($endPos !== null) { + $this->contentPos[1] = $endPos; + } else { + fseek($this->fh, 0, SEEK_END); + $this->contentPos[1] = ftell($this->fh); + } + if (! $this->isMultipart()) { + return; + } + + $boundary = $this->getHeaderField('content-type', 'boundary'); + if (! $boundary) { + throw new Exception\RuntimeException('no boundary found in content type to split message'); + } + + $part = []; + $pos = $this->contentPos[0]; + fseek($this->fh, $pos); + while (! feof($this->fh) && ($endPos === null || $pos < $endPos)) { + $line = fgets($this->fh); + if ($line === false) { + if (feof($this->fh)) { + break; + } + throw new Exception\RuntimeException('error reading file'); + } + + $lastPos = $pos; + $pos = ftell($this->fh); + $line = trim($line); + + if ($line == '--' . $boundary) { + if ($part) { + // not first part + $part[1] = $lastPos; + $this->partPos[] = $part; + } + $part = [$pos]; + } elseif ($line == '--' . $boundary . '--') { + $part[1] = $lastPos; + $this->partPos[] = $part; + break; + } + } + $this->countParts = count($this->partPos); + } + + /** + * Body of part + * + * If part is multipart the raw content of this part with all sub parts is returned + * + * @param resource $stream Optional + * @return string body + */ + public function getContent($stream = null) + { + fseek($this->fh, $this->contentPos[0]); + if ($stream !== null) { + return stream_copy_to_stream($this->fh, $stream, $this->contentPos[1] - $this->contentPos[0]); + } + $length = $this->contentPos[1] - $this->contentPos[0]; + return $length < 1 ? '' : fread($this->fh, $length); + } + + /** + * Return size of part + * + * Quite simple implemented currently (not decoding). Handle with care. + * + * @return int size + */ + public function getSize() + { + return $this->contentPos[1] - $this->contentPos[0]; + } + + /** + * Get part of multipart message + * + * @param int $num number of part starting with 1 for first part + * @throws Exception\RuntimeException + * @return Part wanted part + */ + public function getPart($num) + { + --$num; + if (! isset($this->partPos[$num])) { + throw new Exception\RuntimeException('part not found'); + } + + return new static(['file' => $this->fh, 'startPos' => $this->partPos[$num][0], + 'endPos' => $this->partPos[$num][1]]); + } +} diff --git a/lib/laminas/laminas-mail/src/Storage/Part/PartInterface.php b/lib/laminas/laminas-mail/src/Storage/Part/PartInterface.php new file mode 100644 index 000000000..54bc6990c --- /dev/null +++ b/lib/laminas/laminas-mail/src/Storage/Part/PartInterface.php @@ -0,0 +1,123 @@ + firstPart, partname => value] + * @throws Exception\ExceptionInterface + */ + public function getHeaderField($name, $wantedPart = '0', $firstName = '0'); + + /** + * Getter for mail headers - name is matched in lowercase + * + * This getter is short for PartInterface::getHeader($name, 'string') + * + * @see PartInterface::getHeader() + * @param string $name header name + * @return string value of header + * @throws Exception\ExceptionInterface + */ + public function __get($name); + + /** + * magic method to get content of part + * + * @return string content + */ + public function __toString(); +} diff --git a/lib/laminas/laminas-mail/src/Storage/Pop3.php b/lib/laminas/laminas-mail/src/Storage/Pop3.php new file mode 100644 index 000000000..3549763ab --- /dev/null +++ b/lib/laminas/laminas-mail/src/Storage/Pop3.php @@ -0,0 +1,283 @@ +protocol->status($count, $octets); + return (int) $count; + } + + /** + * get a list of messages with number and size + * + * @param int $id number of message + * @return int|array size of given message of list with all messages as array(num => size) + * @throws \Laminas\Mail\Protocol\Exception\ExceptionInterface + */ + public function getSize($id = 0) + { + $id = $id ? $id : null; + return $this->protocol->getList($id); + } + + /** + * Fetch a message + * + * @param int $id number of message + * @return \Laminas\Mail\Storage\Message + * @throws \Laminas\Mail\Protocol\Exception\ExceptionInterface + */ + public function getMessage($id) + { + $bodyLines = 0; + $message = $this->protocol->top($id, $bodyLines, true); + + return new $this->messageClass(['handler' => $this, 'id' => $id, 'headers' => $message, + 'noToplines' => $bodyLines < 1]); + } + + /* + * Get raw header of message or part + * + * @param int $id number of message + * @param null|array|string $part path to part or null for message header + * @param int $topLines include this many lines with header (after an empty line) + * @return string raw header + * @throws \Laminas\Mail\Protocol\Exception\ExceptionInterface + * @throws \Laminas\Mail\Storage\Exception\ExceptionInterface + */ + public function getRawHeader($id, $part = null, $topLines = 0) + { + if ($part !== null) { + // TODO: implement + throw new Exception\RuntimeException('not implemented'); + } + + return $this->protocol->top($id, 0, true); + } + + /* + * Get raw content of message or part + * + * @param int $id number of message + * @param null|array|string $part path to part or null for message content + * @return string raw content + * @throws \Laminas\Mail\Protocol\Exception\ExceptionInterface + * @throws \Laminas\Mail\Storage\Exception\ExceptionInterface + */ + public function getRawContent($id, $part = null) + { + if ($part !== null) { + // TODO: implement + throw new Exception\RuntimeException('not implemented'); + } + + $content = $this->protocol->retrieve($id); + // TODO: find a way to avoid decoding the headers + $headers = null; // "Declare" variable since it's passed by reference + $body = null; // "Declare" variable before first usage. + Mime\Decode::splitMessage($content, $headers, $body); + return $body; + } + + /** + * create instance with parameters + * Supported parameters are + * - host hostname or ip address of POP3 server + * - user username + * - password password for user 'username' [optional, default = ''] + * - port port for POP3 server [optional, default = 110] + * - ssl 'SSL' or 'TLS' for secure sockets + * + * @param array|Protocol\Pop3 $params mail reader specific parameters or configured Pop3 protocol object + * @throws \Laminas\Mail\Storage\Exception\InvalidArgumentException + * @throws \Laminas\Mail\Protocol\Exception\RuntimeException + */ + public function __construct($params) + { + if (is_array($params)) { + $params = (object) $params; + } + + $this->has['fetchPart'] = false; + $this->has['top'] = null; + $this->has['uniqueid'] = null; + + if ($params instanceof Protocol\Pop3) { + $this->protocol = $params; + return; + } + + if (! isset($params->user)) { + throw new Exception\InvalidArgumentException('need at least user in params'); + } + + $host = isset($params->host) ? $params->host : 'localhost'; + $password = isset($params->password) ? $params->password : ''; + $port = isset($params->port) ? $params->port : null; + $ssl = isset($params->ssl) ? $params->ssl : false; + + $this->protocol = new Protocol\Pop3(); + + if (isset($params->novalidatecert)) { + $this->protocol->setNoValidateCert((bool)$params->novalidatecert); + } + + $this->protocol->connect($host, $port, $ssl); + $this->protocol->login($params->user, $password); + } + + /** + * Close resource for mail lib. If you need to control, when the resource + * is closed. Otherwise the destructor would call this. + */ + public function close() + { + $this->protocol->logout(); + } + + /** + * Keep the server busy. + * + * @throws \Laminas\Mail\Protocol\Exception\RuntimeException + */ + public function noop() + { + $this->protocol->noop(); + } + + /** + * Remove a message from server. If you're doing that from a web environment + * you should be careful and use a uniqueid as parameter if possible to + * identify the message. + * + * @param int $id number of message + * @throws \Laminas\Mail\Protocol\Exception\RuntimeException + */ + public function removeMessage($id) + { + $this->protocol->delete($id); + } + + /** + * get unique id for one or all messages + * + * if storage does not support unique ids it's the same as the message number + * + * @param int|null $id message number + * @return array|string message number for given message or all messages as array + * @throws \Laminas\Mail\Storage\Exception\ExceptionInterface + */ + public function getUniqueId($id = null) + { + if (! $this->hasUniqueid) { + if ($id) { + return $id; + } + $count = $this->countMessages(); + if ($count < 1) { + return []; + } + $range = range(1, $count); + return array_combine($range, $range); + } + + return $this->protocol->uniqueid($id); + } + + /** + * get a message number from a unique id + * + * I.e. if you have a webmailer that supports deleting messages you should use unique ids + * as parameter and use this method to translate it to message number right before calling removeMessage() + * + * @param string $id unique id + * @throws Exception\InvalidArgumentException + * @return int message number + */ + public function getNumberByUniqueId($id) + { + if (! $this->hasUniqueid) { + return $id; + } + + $ids = $this->getUniqueId(); + foreach ($ids as $k => $v) { + if ($v == $id) { + return $k; + } + } + + throw new Exception\InvalidArgumentException('unique id not found'); + } + + /** + * Special handling for hasTop and hasUniqueid. The headers of the first message is + * retrieved if Top wasn't needed/tried yet. + * + * @see AbstractStorage::__get() + * @param string $var + * @return string + */ + public function __get($var) + { + $result = parent::__get($var); + if ($result !== null) { + return $result; + } + + if (strtolower($var) == 'hastop') { + if ($this->protocol->hasTop === null) { + // need to make a real call, because not all server are honest in their capas + try { + $this->protocol->top(1, 0, false); + } catch (MailException\ExceptionInterface $e) { + // ignoring error + } + } + $this->has['top'] = $this->protocol->hasTop; + return $this->protocol->hasTop; + } + + if (strtolower($var) == 'hasuniqueid') { + $id = null; + try { + $id = $this->protocol->uniqueid(1); + } catch (MailException\ExceptionInterface $e) { + // ignoring error + } + $this->has['uniqueid'] = (bool) $id; + return $this->has['uniqueid']; + } + + return $result; + } +} diff --git a/lib/laminas/laminas-mail/src/Storage/Writable/Maildir.php b/lib/laminas/laminas-mail/src/Storage/Writable/Maildir.php new file mode 100644 index 000000000..b8c301746 --- /dev/null +++ b/lib/laminas/laminas-mail/src/Storage/Writable/Maildir.php @@ -0,0 +1,953 @@ +create) + && isset($params->dirname) + && ! file_exists($params->dirname . DIRECTORY_SEPARATOR . 'cur') + ) { + self::initMaildir($params->dirname); + } + + parent::__construct($params); + } + + /** + * create a new folder + * + * This method also creates parent folders if necessary. Some mail storages may restrict, which folder + * may be used as parent or which chars may be used in the folder name + * + * @param string $name global name of folder, local name if $parentFolder is set + * @param string|\Laminas\Mail\Storage\Folder $parentFolder parent of new folder, else root folder is parent + * @throws \Laminas\Mail\Storage\Exception\RuntimeException + * @return string only used internally (new created maildir) + */ + public function createFolder($name, $parentFolder = null) + { + if ($parentFolder instanceof Folder) { + $folder = $parentFolder->getGlobalName() . $this->delim . $name; + } elseif ($parentFolder !== null) { + $folder = rtrim($parentFolder, $this->delim) . $this->delim . $name; + } else { + $folder = $name; + } + + $folder = trim($folder, $this->delim); + + // first we check if we try to create a folder that does exist + $exists = null; + try { + $exists = $this->getFolders($folder); + } catch (MailException\ExceptionInterface $e) { + // ok + } + if ($exists) { + throw new StorageException\RuntimeException('folder already exists'); + } + + if (strpos($folder, $this->delim . $this->delim) !== false) { + throw new StorageException\RuntimeException('invalid name - folder parts may not be empty'); + } + + if (strpos($folder, 'INBOX' . $this->delim) === 0) { + $folder = substr($folder, 6); + } + + $fulldir = $this->rootdir . '.' . $folder; + + // check if we got tricked and would create a dir outside of the rootdir or not as direct child + if (strpos($folder, DIRECTORY_SEPARATOR) !== false || strpos($folder, '/') !== false + || dirname($fulldir) . DIRECTORY_SEPARATOR != $this->rootdir + ) { + throw new StorageException\RuntimeException('invalid name - no directory separator allowed in folder name'); + } + + // has a parent folder? + $parent = null; + if (strpos($folder, $this->delim)) { + // let's see if the parent folder exists + $parent = substr($folder, 0, strrpos($folder, $this->delim)); + try { + $this->getFolders($parent); + } catch (MailException\ExceptionInterface $e) { + // does not - create parent folder + $this->createFolder($parent); + } + } + + ErrorHandler::start(); + if (! mkdir($fulldir) || ! mkdir($fulldir . DIRECTORY_SEPARATOR . 'cur')) { + $error = ErrorHandler::stop(); + throw new StorageException\RuntimeException( + 'error while creating new folder, may be created incompletely', + 0, + $error + ); + } + ErrorHandler::stop(); + + mkdir($fulldir . DIRECTORY_SEPARATOR . 'new'); + mkdir($fulldir . DIRECTORY_SEPARATOR . 'tmp'); + + $localName = $parent ? substr($folder, strlen($parent) + 1) : $folder; + $this->getFolders($parent)->$localName = new Folder($localName, $folder, true); + + return $fulldir; + } + + /** + * remove a folder + * + * @param string|Folder $name name or instance of folder + * @throws \Laminas\Mail\Storage\Exception\RuntimeException + */ + public function removeFolder($name) + { + // TODO: This could fail in the middle of the task, which is not optimal. + // But there is no defined standard way to mark a folder as removed and there is no atomar fs-op + // to remove a directory. Also moving the folder to a/the trash folder is not possible, as + // all parent folders must be created. What we could do is add a dash to the front of the + // directory name and it should be ignored as long as other processes obey the standard. + + if ($name instanceof Folder) { + $name = $name->getGlobalName(); + } + + $name = trim($name, $this->delim); + if (strpos($name, 'INBOX' . $this->delim) === 0) { + $name = substr($name, 6); + } + + // check if folder exists and has no children + if (! $this->getFolders($name)->isLeaf()) { + throw new StorageException\RuntimeException('delete children first'); + } + + if ($name == 'INBOX' || $name == DIRECTORY_SEPARATOR || $name == '/') { + throw new StorageException\RuntimeException('wont delete INBOX'); + } + + if ($name == $this->getCurrentFolder()) { + throw new StorageException\RuntimeException('wont delete selected folder'); + } + + foreach (['tmp', 'new', 'cur', '.'] as $subdir) { + $dir = $this->rootdir . '.' . $name . DIRECTORY_SEPARATOR . $subdir; + if (! file_exists($dir)) { + continue; + } + $dh = opendir($dir); + if (! $dh) { + throw new StorageException\RuntimeException("error opening $subdir"); + } + while (($entry = readdir($dh)) !== false) { + if ($entry == '.' || $entry == '..') { + continue; + } + if (! unlink($dir . DIRECTORY_SEPARATOR . $entry)) { + throw new StorageException\RuntimeException("error cleaning $subdir"); + } + } + closedir($dh); + if ($subdir !== '.') { + if (! rmdir($dir)) { + throw new StorageException\RuntimeException("error removing $subdir"); + } + } + } + + if (! rmdir($this->rootdir . '.' . $name)) { + // at least we should try to make it a valid maildir again + mkdir($this->rootdir . '.' . $name . DIRECTORY_SEPARATOR . 'cur'); + throw new StorageException\RuntimeException("error removing maindir"); + } + + $parent = strpos($name, $this->delim) ? substr($name, 0, strrpos($name, $this->delim)) : null; + $localName = $parent ? substr($name, strlen($parent) + 1) : $name; + unset($this->getFolders($parent)->$localName); + } + + /** + * rename and/or move folder + * + * The new name has the same restrictions as in createFolder() + * + * @param string|\Laminas\Mail\Storage\Folder $oldName name or instance of folder + * @param string $newName new global name of folder + * @throws \Laminas\Mail\Storage\Exception\RuntimeException + */ + public function renameFolder($oldName, $newName) + { + // TODO: This is also not atomar and has similar problems as removeFolder() + + if ($oldName instanceof Folder) { + $oldName = $oldName->getGlobalName(); + } + + $oldName = trim($oldName, $this->delim); + if (strpos($oldName, 'INBOX' . $this->delim) === 0) { + $oldName = substr($oldName, 6); + } + + $newName = trim($newName, $this->delim); + if (strpos($newName, 'INBOX' . $this->delim) === 0) { + $newName = substr($newName, 6); + } + + if (strpos($newName, $oldName . $this->delim) === 0) { + throw new StorageException\RuntimeException('new folder cannot be a child of old folder'); + } + + // check if folder exists and has no children + $folder = $this->getFolders($oldName); + + if ($oldName == 'INBOX' || $oldName == DIRECTORY_SEPARATOR || $oldName == '/') { + throw new StorageException\RuntimeException('wont rename INBOX'); + } + + if ($oldName == $this->getCurrentFolder()) { + throw new StorageException\RuntimeException('wont rename selected folder'); + } + + $newdir = $this->createFolder($newName); + + if (! $folder->isLeaf()) { + foreach ($folder as $k => $v) { + $this->renameFolder($v->getGlobalName(), $newName . $this->delim . $k); + } + } + + $olddir = $this->rootdir . '.' . $folder; + foreach (['tmp', 'new', 'cur'] as $subdir) { + $subdir = DIRECTORY_SEPARATOR . $subdir; + if (! file_exists($olddir . $subdir)) { + continue; + } + // using copy or moving files would be even better - but also much slower + if (! rename($olddir . $subdir, $newdir . $subdir)) { + throw new StorageException\RuntimeException('error while moving ' . $subdir); + } + } + // create a dummy if removing fails - otherwise we can't read it next time + mkdir($olddir . DIRECTORY_SEPARATOR . 'cur'); + $this->removeFolder($oldName); + } + + /** + * create a uniqueid for maildir filename + * + * This is nearly the format defined in the maildir standard. The microtime() call should already + * create a uniqueid, the pid is for multicore/-cpu machine that manage to call this function at the + * exact same time, and uname() gives us the hostname for multiple machines accessing the same storage. + * + * If someone disables posix we create a random number of the same size, so this method should also + * work on Windows - if you manage to get maildir working on Windows. + * Microtime could also be disabled, although I've never seen it. + * + * @return string new uniqueid + */ + protected function createUniqueId() + { + $id = ''; + $id .= microtime(true); + $id .= '.' . getmypid(); + $id .= '.' . php_uname('n'); + + return $id; + } + + /** + * open a temporary maildir file + * + * makes sure tmp/ exists and create a file with a unique name + * you should close the returned filehandle! + * + * @param string $folder name of current folder without leading . + * @throws \Laminas\Mail\Storage\Exception\RuntimeException + * @return array array('dirname' => dir of maildir folder, 'uniq' => unique id, 'filename' => name of create file + * 'handle' => file opened for writing) + */ + protected function createTmpFile($folder = 'INBOX') + { + if ($folder == 'INBOX') { + $tmpdir = $this->rootdir . DIRECTORY_SEPARATOR . 'tmp' . DIRECTORY_SEPARATOR; + } else { + $tmpdir = $this->rootdir . '.' . $folder . DIRECTORY_SEPARATOR . 'tmp' . DIRECTORY_SEPARATOR; + } + if (! file_exists($tmpdir)) { + if (! mkdir($tmpdir)) { + throw new StorageException\RuntimeException('problems creating tmp dir'); + } + } + + // we should retry to create a unique id if a file with the same name exists + // to avoid a script timeout we only wait 1 second (instead of 2) and stop + // after a defined retry count + // if you change this variable take into account that it can take up to $maxTries seconds + // normally we should have a valid unique name after the first try, we're just following the "standard" here + $maxTries = 5; + for ($i = 0; $i < $maxTries; ++$i) { + $uniq = $this->createUniqueId(); + if (! file_exists($tmpdir . $uniq)) { + // here is the race condition! - as defined in the standard + // to avoid having a long time between stat()ing the file and creating it we're opening it here + // to mark the filename as taken + $fh = fopen($tmpdir . $uniq, 'w'); + if (! $fh) { + throw new StorageException\RuntimeException('could not open temp file'); + } + break; + } + sleep(1); + } + + if (! $fh) { + throw new StorageException\RuntimeException( + "tried {$maxTries} unique ids for a temp file, but all were taken - giving up" + ); + } + + return ['dirname' => $this->rootdir . '.' . $folder, + 'uniq' => $uniq, + 'filename' => $tmpdir . $uniq, + 'handle' => $fh]; + } + + /** + * create an info string for filenames with given flags + * + * @param array $flags wanted flags, with the reference you'll get the set + * flags with correct key (= char for flag) + * @return string info string for version 2 filenames including the leading colon + * @throws StorageException\InvalidArgumentException + */ + protected function getInfoString(&$flags) + { + // accessing keys is easier, faster and it removes duplicated flags + $wantedFlags = array_flip($flags); + if (isset($wantedFlags[Storage::FLAG_RECENT])) { + throw new StorageException\InvalidArgumentException('recent flag may not be set'); + } + + $info = ':2,'; + $flags = []; + foreach (Storage\Maildir::$knownFlags as $char => $flag) { + if (! isset($wantedFlags[$flag])) { + continue; + } + $info .= $char; + $flags[$char] = $flag; + unset($wantedFlags[$flag]); + } + + if (! empty($wantedFlags)) { + $wantedFlags = implode(', ', array_keys($wantedFlags)); + throw new StorageException\InvalidArgumentException('unknown flag(s): ' . $wantedFlags); + } + + return $info; + } + + /** + * append a new message to mail storage + * + * @param string|resource $message message as string or stream resource. + * @param null|string|Folder $folder folder for new message, else current + * folder is taken. + * @param null|array $flags set flags for new message, else a default set + * is used. + * @param bool $recent handle this mail as if recent flag has been set, + * should only be used in delivery. + * @throws StorageException\RuntimeException + */ + public function appendMessage($message, $folder = null, $flags = null, $recent = false) + { + if ($this->quota && $this->checkQuota()) { + throw new StorageException\RuntimeException('storage is over quota!'); + } + + if ($folder === null) { + $folder = $this->currentFolder; + } + + if (! ($folder instanceof Folder)) { + $folder = $this->getFolders($folder); + } + + if ($flags === null) { + $flags = [Storage::FLAG_SEEN]; + } + $info = $this->getInfoString($flags); + $tempFile = $this->createTmpFile($folder->getGlobalName()); + + // TODO: handle class instances for $message + if (is_resource($message) && get_resource_type($message) == 'stream') { + stream_copy_to_stream($message, $tempFile['handle']); + } else { + fwrite($tempFile['handle'], $message); + } + fclose($tempFile['handle']); + + // we're adding the size to the filename for maildir++ + $size = filesize($tempFile['filename']); + if ($size !== false) { + $info = ',S=' . $size . $info; + } + $newFilename = $tempFile['dirname'] . DIRECTORY_SEPARATOR; + $newFilename .= $recent ? 'new' : 'cur'; + $newFilename .= DIRECTORY_SEPARATOR . $tempFile['uniq'] . $info; + + // we're throwing any exception after removing our temp file and saving it to this variable instead + $exception = null; + + if (! link($tempFile['filename'], $newFilename)) { + $exception = new StorageException\RuntimeException('cannot link message file to final dir'); + } + + ErrorHandler::start(E_WARNING); + unlink($tempFile['filename']); + ErrorHandler::stop(); + + if ($exception) { + throw $exception; + } + + $this->files[] = ['uniq' => $tempFile['uniq'], + 'flags' => $flags, + 'filename' => $newFilename]; + if ($this->quota) { + $this->addQuotaEntry((int) $size, 1); + } + } + + /** + * copy an existing message + * + * @param int $id number of message + * @param string|\Laminas\Mail\Storage\Folder $folder name or instance of targer folder + * @throws \Laminas\Mail\Storage\Exception\RuntimeException + */ + public function copyMessage($id, $folder) + { + if ($this->quota && $this->checkQuota()) { + throw new StorageException\RuntimeException('storage is over quota!'); + } + + if (! ($folder instanceof Folder)) { + $folder = $this->getFolders($folder); + } + + $filedata = $this->getFileData($id); + $oldFile = $filedata['filename']; + $flags = $filedata['flags']; + + // copied message can't be recent + while (($key = array_search(Storage::FLAG_RECENT, $flags)) !== false) { + unset($flags[$key]); + } + $info = $this->getInfoString($flags); + + // we're creating the copy as temp file before moving to cur/ + $tempFile = $this->createTmpFile($folder->getGlobalName()); + // we don't write directly to the file + fclose($tempFile['handle']); + + // we're adding the size to the filename for maildir++ + $size = filesize($oldFile); + if ($size !== false) { + $info = ',S=' . $size . $info; + } + + $newFile = $tempFile['dirname'] . DIRECTORY_SEPARATOR . 'cur' . DIRECTORY_SEPARATOR . $tempFile['uniq'] . $info; + + // we're throwing any exception after removing our temp file and saving it to this variable instead + $exception = null; + + if (! copy($oldFile, $tempFile['filename'])) { + $exception = new StorageException\RuntimeException('cannot copy message file'); + } elseif (! link($tempFile['filename'], $newFile)) { + $exception = new StorageException\RuntimeException('cannot link message file to final dir'); + } + + ErrorHandler::start(E_WARNING); + unlink($tempFile['filename']); + ErrorHandler::stop(); + + if ($exception) { + throw $exception; + } + + if ($folder->getGlobalName() == $this->currentFolder + || ($this->currentFolder == 'INBOX' && $folder->getGlobalName() == '/') + ) { + $this->files[] = ['uniq' => $tempFile['uniq'], + 'flags' => $flags, + 'filename' => $newFile]; + } + + if ($this->quota) { + $this->addQuotaEntry((int) $size, 1); + } + } + + /** + * move an existing message + * + * @param int $id number of message + * @param string|\Laminas\Mail\Storage\Folder $folder name or instance of targer folder + * @throws \Laminas\Mail\Storage\Exception\RuntimeException + */ + public function moveMessage($id, $folder) + { + if (! ($folder instanceof Folder)) { + $folder = $this->getFolders($folder); + } + + if ($folder->getGlobalName() == $this->currentFolder + || ($this->currentFolder == 'INBOX' && $folder->getGlobalName() == '/') + ) { + throw new StorageException\RuntimeException('target is current folder'); + } + + $filedata = $this->getFileData($id); + $oldFile = $filedata['filename']; + $flags = $filedata['flags']; + + // moved message can't be recent + while (($key = array_search(Storage::FLAG_RECENT, $flags)) !== false) { + unset($flags[$key]); + } + $info = $this->getInfoString($flags); + + // reserving a new name + $tempFile = $this->createTmpFile($folder->getGlobalName()); + fclose($tempFile['handle']); + + // we're adding the size to the filename for maildir++ + $size = filesize($oldFile); + if ($size !== false) { + $info = ',S=' . $size . $info; + } + + $newFile = $tempFile['dirname'] . DIRECTORY_SEPARATOR . 'cur' . DIRECTORY_SEPARATOR . $tempFile['uniq'] . $info; + + // we're throwing any exception after removing our temp file and saving it to this variable instead + $exception = null; + + if (! rename($oldFile, $newFile)) { + $exception = new StorageException\RuntimeException('cannot move message file'); + } + + ErrorHandler::start(E_WARNING); + unlink($tempFile['filename']); + ErrorHandler::stop(); + + if ($exception) { + throw $exception; + } + + unset($this->files[$id - 1]); + // remove the gap + $this->files = array_values($this->files); + } + + /** + * set flags for message + * + * NOTE: this method can't set the recent flag. + * + * @param int $id number of message + * @param array $flags new flags for message + * @throws \Laminas\Mail\Storage\Exception\RuntimeException + */ + public function setFlags($id, $flags) + { + $info = $this->getInfoString($flags); + $filedata = $this->getFileData($id); + + // NOTE: double dirname to make sure we always move to cur. if recent + // flag has been set (message is in new) it will be moved to cur. + $newFilename = dirname(dirname($filedata['filename'])) + . DIRECTORY_SEPARATOR + . 'cur' + . DIRECTORY_SEPARATOR + . "$filedata[uniq]$info"; + + ErrorHandler::start(); + $test = rename($filedata['filename'], $newFilename); + $error = ErrorHandler::stop(); + if (! $test) { + throw new StorageException\RuntimeException('cannot rename file', 0, $error); + } + + $filedata['flags'] = $flags; + $filedata['filename'] = $newFilename; + + $this->files[$id - 1] = $filedata; + } + + /** + * stub for not supported message deletion + * + * @param $id + * @throws \Laminas\Mail\Storage\Exception\RuntimeException + */ + public function removeMessage($id) + { + $filename = $this->getFileData($id, 'filename'); + + if ($this->quota) { + $size = filesize($filename); + } + + ErrorHandler::start(); + $test = unlink($filename); + $error = ErrorHandler::stop(); + if (! $test) { + throw new StorageException\RuntimeException('cannot remove message', 0, $error); + } + unset($this->files[$id - 1]); + // remove the gap + $this->files = array_values($this->files); + if ($this->quota) { + $this->addQuotaEntry(0 - (int) $size, -1); + } + } + + /** + * enable/disable quota and set a quota value if wanted or needed + * + * You can enable/disable quota with true/false. If you don't have + * a MDA or want to enforce a quota value you can also set this value + * here. Use array('size' => SIZE_QUOTA, 'count' => MAX_MESSAGE) do + * define your quota. Order of these fields does matter! + * + * @param bool|array $value new quota value + */ + public function setQuota($value) + { + $this->quota = $value; + } + + /** + * get currently set quota + * + * @see \Laminas\Mail\Storage\Writable\Maildir::setQuota() + * @param bool $fromStorage + * @throws \Laminas\Mail\Storage\Exception\RuntimeException + * @return bool|array + */ + public function getQuota($fromStorage = false) + { + if ($fromStorage) { + ErrorHandler::start(E_WARNING); + $fh = fopen($this->rootdir . 'maildirsize', 'r'); + $error = ErrorHandler::stop(); + if (! $fh) { + throw new StorageException\RuntimeException('cannot open maildirsize', 0, $error); + } + $definition = fgets($fh); + fclose($fh); + $definition = explode(',', trim($definition)); + $quota = []; + foreach ($definition as $member) { + $key = $member[strlen($member) - 1]; + if ($key == 'S' || $key == 'C') { + $key = $key == 'C' ? 'count' : 'size'; + } + $quota[$key] = substr($member, 0, -1); + } + return $quota; + } + + return $this->quota; + } + + /** + * @see http://www.inter7.com/courierimap/README.maildirquota.html "Calculating maildirsize" + * @throws \Laminas\Mail\Storage\Exception\RuntimeException + * @return array + */ + protected function calculateMaildirsize() + { + $timestamps = []; + $messages = 0; + $totalSize = 0; + + if (is_array($this->quota)) { + $quota = $this->quota; + } else { + try { + $quota = $this->getQuota(true); + } catch (StorageException\ExceptionInterface $e) { + throw new StorageException\RuntimeException('no quota definition found', 0, $e); + } + } + + $folders = new RecursiveIteratorIterator($this->getFolders(), RecursiveIteratorIterator::SELF_FIRST); + foreach ($folders as $folder) { + $subdir = $folder->getGlobalName(); + if ($subdir == 'INBOX') { + $subdir = ''; + } else { + $subdir = '.' . $subdir; + } + if ($subdir == 'Trash') { + continue; + } + + foreach (['cur', 'new'] as $subsubdir) { + $dirname = $this->rootdir . $subdir . DIRECTORY_SEPARATOR . $subsubdir . DIRECTORY_SEPARATOR; + if (! file_exists($dirname)) { + continue; + } + // NOTE: we are using mtime instead of "the latest timestamp". The latest would be atime + // and as we are accessing the directory it would make the whole calculation useless. + $timestamps[$dirname] = filemtime($dirname); + + $dh = opendir($dirname); + // NOTE: Should have been checked in constructor. Not throwing an exception here, quotas will + // therefore not be fully enforced, but next request will fail anyway, if problem persists. + if (! $dh) { + continue; + } + + while (($entry = readdir()) !== false) { + if ($entry[0] == '.' || ! is_file($dirname . $entry)) { + continue; + } + + if (strpos($entry, ',S=')) { + strtok($entry, '='); + $filesize = strtok(':'); + if (is_numeric($filesize)) { + $totalSize += $filesize; + ++$messages; + continue; + } + } + $size = filesize($dirname . $entry); + if ($size === false) { + // ignore, as we assume file got removed + continue; + } + $totalSize += $size; + ++$messages; + } + } + } + + $tmp = $this->createTmpFile(); + $fh = $tmp['handle']; + $definition = []; + foreach ($quota as $type => $value) { + if ($type == 'size' || $type == 'count') { + $type = $type == 'count' ? 'C' : 'S'; + } + $definition[] = $value . $type; + } + $definition = implode(',', $definition); + fwrite($fh, "$definition\n"); + fwrite($fh, "$totalSize $messages\n"); + fclose($fh); + rename($tmp['filename'], $this->rootdir . 'maildirsize'); + foreach ($timestamps as $dir => $timestamp) { + if ($timestamp < filemtime($dir)) { + unlink($this->rootdir . 'maildirsize'); + break; + } + } + + return ['size' => $totalSize, + 'count' => $messages, + 'quota' => $quota]; + } + + /** + * @see http://www.inter7.com/courierimap/README.maildirquota.html "Calculating the quota for a Maildir++" + * @param bool $forceRecalc + * @return array + */ + protected function calculateQuota($forceRecalc = false) + { + $fh = null; + $totalSize = 0; + $messages = 0; + $maildirsize = ''; + if (! $forceRecalc + && file_exists($this->rootdir . 'maildirsize') + && filesize($this->rootdir . 'maildirsize') < 5120 + ) { + $fh = fopen($this->rootdir . 'maildirsize', 'r'); + } + if ($fh) { + $maildirsize = fread($fh, 5120); + if (strlen($maildirsize) >= 5120) { + fclose($fh); + $fh = null; + $maildirsize = ''; + } + } + if (! $fh) { + $result = $this->calculateMaildirsize(); + $totalSize = $result['size']; + $messages = $result['count']; + $quota = $result['quota']; + } else { + $maildirsize = explode("\n", $maildirsize); + if (is_array($this->quota)) { + $quota = $this->quota; + } else { + $definition = explode(',', $maildirsize[0]); + $quota = []; + foreach ($definition as $member) { + $key = $member[strlen($member) - 1]; + if ($key == 'S' || $key == 'C') { + $key = $key == 'C' ? 'count' : 'size'; + } + $quota[$key] = substr($member, 0, -1); + } + } + unset($maildirsize[0]); + foreach ($maildirsize as $line) { + list($size, $count) = explode(' ', trim($line)); + $totalSize += $size; + $messages += $count; + } + } + + $overQuota = false; + $overQuota = $overQuota || (isset($quota['size']) && $totalSize > $quota['size']); + $overQuota = $overQuota || (isset($quota['count']) && $messages > $quota['count']); + // NOTE: $maildirsize equals false if it wasn't set (AKA we recalculated) or it's only + // one line, because $maildirsize[0] gets unsetted. + // Also we're using local time to calculate the 15 minute offset. Touching a file just for known the + // local time of the file storage isn't worth the hassle. + if ($overQuota && ($maildirsize || filemtime($this->rootdir . 'maildirsize') > time() - 900)) { + $result = $this->calculateMaildirsize(); + $totalSize = $result['size']; + $messages = $result['count']; + $quota = $result['quota']; + $overQuota = false; + $overQuota = $overQuota || (isset($quota['size']) && $totalSize > $quota['size']); + $overQuota = $overQuota || (isset($quota['count']) && $messages > $quota['count']); + } + + if ($fh) { + // TODO is there a safe way to keep the handle open for writing? + fclose($fh); + } + + return ['size' => $totalSize, + 'count' => $messages, + 'quota' => $quota, + 'over_quota' => $overQuota]; + } + + protected function addQuotaEntry($size, $count = 1) + { + if (! file_exists($this->rootdir . 'maildirsize')) { + // TODO: should get file handler from calculateQuota + } + $size = (int) $size; + $count = (int) $count; + file_put_contents($this->rootdir . 'maildirsize', "$size $count\n", FILE_APPEND); + } + + /** + * check if storage is currently over quota + * + * @see calculateQuota() + * @param bool $detailedResponse return known data of quota and current size and message count + * @param bool $forceRecalc + * @return bool|array over quota state or detailed response + */ + public function checkQuota($detailedResponse = false, $forceRecalc = false) + { + $result = $this->calculateQuota($forceRecalc); + return $detailedResponse ? $result : $result['over_quota']; + } +} diff --git a/lib/laminas/laminas-mail/src/Storage/Writable/WritableInterface.php b/lib/laminas/laminas-mail/src/Storage/Writable/WritableInterface.php new file mode 100644 index 000000000..84f3b991d --- /dev/null +++ b/lib/laminas/laminas-mail/src/Storage/Writable/WritableInterface.php @@ -0,0 +1,92 @@ +from; + } + + /** + * Set MAIL FROM + * + * @param string $from + */ + public function setFrom($from) + { + $this->from = (string) $from; + } + + /** + * Get RCPT TO + * + * @return string|null + */ + public function getTo() + { + return $this->to; + } + + /** + * Set RCPT TO + * + * @param string $to + */ + public function setTo($to) + { + $this->to = $to; + } +} diff --git a/lib/laminas/laminas-mail/src/Transport/Exception/DomainException.php b/lib/laminas/laminas-mail/src/Transport/Exception/DomainException.php new file mode 100644 index 000000000..9269e13eb --- /dev/null +++ b/lib/laminas/laminas-mail/src/Transport/Exception/DomainException.php @@ -0,0 +1,18 @@ + File::class, + 'inmemory' => InMemory::class, + 'memory' => InMemory::class, + 'null' => InMemory::class, + 'sendmail' => Sendmail::class, + 'smtp' => Smtp::class, + ]; + + /** + * @param array $spec + * @return TransportInterface + * @throws Exception\InvalidArgumentException + * @throws Exception\DomainException + */ + public static function create($spec = []) + { + if ($spec instanceof Traversable) { + $spec = ArrayUtils::iteratorToArray($spec); + } + + if (! is_array($spec)) { + throw new Exception\InvalidArgumentException(sprintf( + '%s expects an array or Traversable argument; received "%s"', + __METHOD__, + (is_object($spec) ? get_class($spec) : gettype($spec)) + )); + } + + $type = isset($spec['type']) ? $spec['type'] : 'sendmail'; + + $normalizedType = strtolower($type); + + if (isset(static::$classMap[$normalizedType])) { + $type = static::$classMap[$normalizedType]; + } + + if (! class_exists($type)) { + throw new Exception\DomainException(sprintf( + '%s expects the "type" attribute to resolve to an existing class; received "%s"', + __METHOD__, + $type + )); + } + + $transport = new $type; + + if (! $transport instanceof TransportInterface) { + throw new Exception\DomainException(sprintf( + '%s expects the "type" attribute to resolve to a valid %s instance; received "%s"', + __METHOD__, + TransportInterface::class, + $type + )); + } + + if ($transport instanceof Smtp && isset($spec['options'])) { + $transport->setOptions(new SmtpOptions($spec['options'])); + } + + if ($transport instanceof File && isset($spec['options'])) { + $transport->setOptions(new FileOptions($spec['options'])); + } + + return $transport; + } +} diff --git a/lib/laminas/laminas-mail/src/Transport/File.php b/lib/laminas/laminas-mail/src/Transport/File.php new file mode 100644 index 000000000..3b4b9783f --- /dev/null +++ b/lib/laminas/laminas-mail/src/Transport/File.php @@ -0,0 +1,96 @@ +setOptions($options); + } + + /** + * @return FileOptions + */ + public function getOptions() + { + return $this->options; + } + + /** + * Sets options + * + * @param FileOptions $options + */ + public function setOptions(FileOptions $options) + { + $this->options = $options; + } + + /** + * Saves e-mail message to a file + * + * @param Message $message + * @throws Exception\RuntimeException on not writable target directory or + * on file_put_contents() failure + */ + public function send(Message $message) + { + $options = $this->options; + $filename = call_user_func($options->getCallback(), $this); + $file = $options->getPath() . DIRECTORY_SEPARATOR . $filename; + $email = $message->toString(); + + if (false === file_put_contents($file, $email)) { + throw new Exception\RuntimeException(sprintf( + 'Unable to write mail to file (directory "%s")', + $options->getPath() + )); + } + + $this->lastFile = $file; + } + + /** + * Get the name of the last file written to + * + * @return string + */ + public function getLastFile() + { + return $this->lastFile; + } +} diff --git a/lib/laminas/laminas-mail/src/Transport/FileOptions.php b/lib/laminas/laminas-mail/src/Transport/FileOptions.php new file mode 100644 index 000000000..2307a84d1 --- /dev/null +++ b/lib/laminas/laminas-mail/src/Transport/FileOptions.php @@ -0,0 +1,95 @@ +path = $path; + return $this; + } + + /** + * Get path + * + * If none is set, uses value from sys_get_temp_dir() + * + * @return string + */ + public function getPath() + { + if (null === $this->path) { + $this->setPath(sys_get_temp_dir()); + } + return $this->path; + } + + /** + * Set callback used to generate a file name + * + * @param callable $callback + * @throws \Laminas\Mail\Exception\InvalidArgumentException + * @return FileOptions + */ + public function setCallback($callback) + { + if (! is_callable($callback)) { + throw new Exception\InvalidArgumentException(sprintf( + '%s expects a valid callback; received "%s"', + __METHOD__, + (is_object($callback) ? get_class($callback) : gettype($callback)) + )); + } + $this->callback = $callback; + return $this; + } + + /** + * Get callback used to generate a file name + * + * @return callable + */ + public function getCallback() + { + if (null === $this->callback) { + $this->setCallback(function () { + return 'LaminasMail_' . time() . '_' . mt_rand() . '.eml'; + }); + } + return $this->callback; + } +} diff --git a/lib/laminas/laminas-mail/src/Transport/InMemory.php b/lib/laminas/laminas-mail/src/Transport/InMemory.php new file mode 100644 index 000000000..c21917b88 --- /dev/null +++ b/lib/laminas/laminas-mail/src/Transport/InMemory.php @@ -0,0 +1,46 @@ +lastMessage = $message; + } + + /** + * Get the last message sent. + * + * @return null|Message + */ + public function getLastMessage() + { + return $this->lastMessage; + } +} diff --git a/lib/laminas/laminas-mail/src/Transport/Sendmail.php b/lib/laminas/laminas-mail/src/Transport/Sendmail.php new file mode 100644 index 000000000..e92f577db --- /dev/null +++ b/lib/laminas/laminas-mail/src/Transport/Sendmail.php @@ -0,0 +1,336 @@ +setParameters($parameters); + } + $this->callable = [$this, 'mailHandler']; + } + + /** + * Set sendmail parameters + * + * Used to populate the additional_parameters argument to mail() + * + * @param null|string|array|Traversable $parameters + * @throws \Laminas\Mail\Transport\Exception\InvalidArgumentException + * @return Sendmail + */ + public function setParameters($parameters) + { + if ($parameters === null || is_string($parameters)) { + $this->parameters = $parameters; + return $this; + } + + if (! is_array($parameters) && ! $parameters instanceof Traversable) { + throw new Exception\InvalidArgumentException(sprintf( + '%s expects a string, array, or Traversable object of parameters; received "%s"', + __METHOD__, + (is_object($parameters) ? get_class($parameters) : gettype($parameters)) + )); + } + + $string = ''; + foreach ($parameters as $param) { + $string .= ' ' . $param; + } + + $this->parameters = trim($string); + return $this; + } + + /** + * Set callback to use for mail + * + * Primarily for testing purposes, but could be used to curry arguments. + * + * @param callable $callable + * @throws \Laminas\Mail\Transport\Exception\InvalidArgumentException + * @return Sendmail + */ + public function setCallable($callable) + { + if (! is_callable($callable)) { + throw new Exception\InvalidArgumentException(sprintf( + '%s expects a callable argument; received "%s"', + __METHOD__, + (is_object($callable) ? get_class($callable) : gettype($callable)) + )); + } + $this->callable = $callable; + return $this; + } + + /** + * Send a message + * + * @param \Laminas\Mail\Message $message + */ + public function send(Mail\Message $message) + { + $to = $this->prepareRecipients($message); + $subject = $this->prepareSubject($message); + $body = $this->prepareBody($message); + $headers = $this->prepareHeaders($message); + $params = $this->prepareParameters($message); + + // On *nix platforms, we need to replace \r\n with \n + // sendmail is not an SMTP server, it is a unix command - it expects LF + if (! $this->isWindowsOs()) { + $to = str_replace("\r\n", "\n", $to); + $subject = str_replace("\r\n", "\n", $subject); + $body = str_replace("\r\n", "\n", $body); + $headers = str_replace("\r\n", "\n", $headers); + } + + call_user_func($this->callable, $to, $subject, $body, $headers, $params); + } + + /** + * Prepare recipients list + * + * @param \Laminas\Mail\Message $message + * @throws \Laminas\Mail\Transport\Exception\RuntimeException + * @return string + */ + protected function prepareRecipients(Mail\Message $message) + { + $headers = $message->getHeaders(); + + $hasTo = $headers->has('to'); + if (! $hasTo && ! $headers->has('cc') && ! $headers->has('bcc')) { + throw new Exception\RuntimeException( + 'Invalid email; contains no at least one of "To", "Cc", and "Bcc" header' + ); + } + + if (! $hasTo) { + return ''; + } + + /** @var Mail\Header\To $to */ + $to = $headers->get('to'); + $list = $to->getAddressList(); + if (0 == count($list)) { + throw new Exception\RuntimeException('Invalid "To" header; contains no addresses'); + } + + // If not on Windows, return normal string + if (! $this->isWindowsOs()) { + return $to->getFieldValue(HeaderInterface::FORMAT_ENCODED); + } + + // Otherwise, return list of emails + $addresses = []; + foreach ($list as $address) { + $addresses[] = $address->getEmail(); + } + $addresses = implode(', ', $addresses); + return $addresses; + } + + /** + * Prepare the subject line string + * + * @param \Laminas\Mail\Message $message + * @return string + */ + protected function prepareSubject(Mail\Message $message) + { + $headers = $message->getHeaders(); + if (! $headers->has('subject')) { + return; + } + $header = $headers->get('subject'); + return $header->getFieldValue(HeaderInterface::FORMAT_ENCODED); + } + + /** + * Prepare the body string + * + * @param \Laminas\Mail\Message $message + * @return string + */ + protected function prepareBody(Mail\Message $message) + { + if (! $this->isWindowsOs()) { + // *nix platforms can simply return the body text + return $message->getBodyText(); + } + + // On windows, lines beginning with a full stop need to be fixed + $text = $message->getBodyText(); + $text = str_replace("\n.", "\n..", $text); + return $text; + } + + /** + * Prepare the textual representation of headers + * + * @param \Laminas\Mail\Message $message + * @return string + */ + protected function prepareHeaders(Mail\Message $message) + { + // Strip the "to" and "subject" headers + $headers = clone $message->getHeaders(); + $headers->removeHeader('To'); + $headers->removeHeader('Subject'); + + /** @var Mail\Header\From $from Sanitize the From header*/ + $from = $headers->get('From'); + if ($from) { + foreach ($from->getAddressList() as $address) { + if (strpos($address->getEmail(), '\\"') !== false) { + throw new Exception\RuntimeException('Potential code injection in From header'); + } + } + } + return $headers->toString(); + } + + /** + * Prepare additional_parameters argument + * + * Basically, overrides the MAIL FROM envelope with either the Sender or + * From address. + * + * @param \Laminas\Mail\Message $message + * @return string + */ + protected function prepareParameters(Mail\Message $message) + { + if ($this->isWindowsOs()) { + return; + } + + $parameters = (string) $this->parameters; + if (preg_match('/(^| )\-f.+/', $parameters)) { + return $parameters; + } + + $sender = $message->getSender(); + if ($sender instanceof AddressInterface) { + $parameters .= ' -f' . \escapeshellarg($sender->getEmail()); + return $parameters; + } + + $from = $message->getFrom(); + if (count($from)) { + $from->rewind(); + $sender = $from->current(); + $parameters .= ' -f' . \escapeshellarg($sender->getEmail()); + return $parameters; + } + + return $parameters; + } + + /** + * Send mail using PHP native mail() + * + * @param string $to + * @param string $subject + * @param string $message + * @param string $headers + * @param $parameters + * @throws \Laminas\Mail\Transport\Exception\RuntimeException + */ + public function mailHandler($to, $subject, $message, $headers, $parameters) + { + set_error_handler([$this, 'handleMailErrors']); + if ($parameters === null) { + $result = mail($to, $subject, $message, $headers); + } else { + $result = mail($to, $subject, $message, $headers, $parameters); + } + restore_error_handler(); + + if ($this->errstr !== null || ! $result) { + $errstr = $this->errstr; + if (empty($errstr)) { + $errstr = 'Unknown error'; + } + throw new Exception\RuntimeException('Unable to send mail: ' . $errstr); + } + } + + /** + * Temporary error handler for PHP native mail(). + * + * @param int $errno + * @param string $errstr + * @param string $errfile + * @param string $errline + * @param array $errcontext + * @return bool always true + */ + public function handleMailErrors($errno, $errstr, $errfile = null, $errline = null, array $errcontext = null) + { + $this->errstr = $errstr; + return true; + } + + /** + * Is this a windows OS? + * + * @return bool + */ + protected function isWindowsOs() + { + if (! $this->operatingSystem) { + $this->operatingSystem = strtoupper(substr(PHP_OS, 0, 3)); + } + return ($this->operatingSystem == 'WIN'); + } +} diff --git a/lib/laminas/laminas-mail/src/Transport/Smtp.php b/lib/laminas/laminas-mail/src/Transport/Smtp.php new file mode 100644 index 000000000..52ec0e489 --- /dev/null +++ b/lib/laminas/laminas-mail/src/Transport/Smtp.php @@ -0,0 +1,406 @@ +setOptions($options); + } + + /** + * Set options + * + * @param SmtpOptions $options + * @return Smtp + */ + public function setOptions(SmtpOptions $options) + { + $this->options = $options; + return $this; + } + + /** + * Get options + * + * @return SmtpOptions + */ + public function getOptions() + { + return $this->options; + } + + /** + * Set options + * + * @param Envelope $envelope + */ + public function setEnvelope(Envelope $envelope) + { + $this->envelope = $envelope; + } + + /** + * Get envelope + * + * @return Envelope|null + */ + public function getEnvelope() + { + return $this->envelope; + } + + /** + * Set plugin manager for obtaining SMTP protocol connection + * + * @param Protocol\SmtpPluginManager $plugins + * @throws Exception\InvalidArgumentException + * @return Smtp + */ + public function setPluginManager(Protocol\SmtpPluginManager $plugins) + { + $this->plugins = $plugins; + return $this; + } + + /** + * Get plugin manager for loading SMTP protocol connection + * + * @return Protocol\SmtpPluginManager + */ + public function getPluginManager() + { + if (null === $this->plugins) { + $this->setPluginManager(new Protocol\SmtpPluginManager(new ServiceManager())); + } + return $this->plugins; + } + + /** + * Set the automatic disconnection when destruct + * + * @param bool $flag + * @return Smtp + */ + public function setAutoDisconnect($flag) + { + $this->autoDisconnect = (bool) $flag; + return $this; + } + + /** + * Get the automatic disconnection value + * + * @return bool + */ + public function getAutoDisconnect() + { + return $this->autoDisconnect; + } + + /** + * Return an SMTP connection + * + * @param string $name + * @param array|null $options + * @return Protocol\Smtp + */ + public function plugin($name, array $options = null) + { + return $this->getPluginManager()->get($name, $options); + } + + /** + * Class destructor to ensure all open connections are closed + */ + public function __destruct() + { + if (! $this->getConnection() instanceof Protocol\Smtp) { + return; + } + + try { + $this->getConnection()->quit(); + } catch (ProtocolException\ExceptionInterface $e) { + // ignore + } + + if ($this->autoDisconnect) { + $this->getConnection()->disconnect(); + } + } + + /** + * Sets the connection protocol instance + * + * @param Protocol\AbstractProtocol $connection + */ + public function setConnection(Protocol\AbstractProtocol $connection) + { + $this->connection = $connection; + if (($connection instanceof Protocol\Smtp) + && ($this->getOptions()->getConnectionTimeLimit() !== null) + ) { + $connection->setUseCompleteQuit(false); + } + } + + /** + * Gets the connection protocol instance + * + * @return Protocol\Smtp + */ + public function getConnection() + { + $timeLimit = $this->getOptions()->getConnectionTimeLimit(); + if ($timeLimit !== null + && $this->connectedTime !== null + && ((time() - $this->connectedTime) > $timeLimit) + ) { + $this->connection = null; + } + return $this->connection; + } + + /** + * Disconnect the connection protocol instance + * + * @return void + */ + public function disconnect() + { + if ($this->getConnection() instanceof Protocol\Smtp) { + $this->getConnection()->disconnect(); + $this->connectedTime = null; + } + } + + /** + * Send an email via the SMTP connection protocol + * + * The connection via the protocol adapter is made just-in-time to allow a + * developer to add a custom adapter if required before mail is sent. + * + * @param Message $message + * @throws Exception\RuntimeException + */ + public function send(Message $message) + { + // If sending multiple messages per session use existing adapter + $connection = $this->getConnection(); + + if (! ($connection instanceof Protocol\Smtp) || ! $connection->hasSession()) { + $connection = $this->connect(); + } else { + // Reset connection to ensure reliable transaction + $connection->rset(); + } + + // Prepare message + $from = $this->prepareFromAddress($message); + $recipients = $this->prepareRecipients($message); + $headers = $this->prepareHeaders($message); + $body = $this->prepareBody($message); + + if ((count($recipients) == 0) && (! empty($headers) || ! empty($body))) { + // Per RFC 2821 3.3 (page 18) + throw new Exception\RuntimeException( + sprintf( + '%s transport expects at least one recipient if the message has at least one header or body', + __CLASS__ + ) + ); + } + + // Set sender email address + $connection->mail($from); + + // Set recipient forward paths + foreach ($recipients as $recipient) { + $connection->rcpt($recipient); + } + + // Issue DATA command to client + $connection->data($headers . Headers::EOL . $body); + } + + /** + * Retrieve email address for envelope FROM + * + * @param Message $message + * @throws Exception\RuntimeException + * @return string + */ + protected function prepareFromAddress(Message $message) + { + if ($this->getEnvelope() && $this->getEnvelope()->getFrom()) { + return $this->getEnvelope()->getFrom(); + } + + $sender = $message->getSender(); + if ($sender instanceof Address\AddressInterface) { + return $sender->getEmail(); + } + + $from = $message->getFrom(); + if (! count($from)) { + // Per RFC 2822 3.6 + throw new Exception\RuntimeException(sprintf( + '%s transport expects either a Sender or at least one From address in the Message; none provided', + __CLASS__ + )); + } + + $from->rewind(); + $sender = $from->current(); + return $sender->getEmail(); + } + + /** + * Prepare array of email address recipients + * + * @param Message $message + * @return array + */ + protected function prepareRecipients(Message $message) + { + if ($this->getEnvelope() && $this->getEnvelope()->getTo()) { + return (array) $this->getEnvelope()->getTo(); + } + + $recipients = []; + foreach ($message->getTo() as $address) { + $recipients[] = $address->getEmail(); + } + foreach ($message->getCc() as $address) { + $recipients[] = $address->getEmail(); + } + foreach ($message->getBcc() as $address) { + $recipients[] = $address->getEmail(); + } + + $recipients = array_unique($recipients); + return $recipients; + } + + /** + * Prepare header string from message + * + * @param Message $message + * @return string + */ + protected function prepareHeaders(Message $message) + { + $headers = clone $message->getHeaders(); + $headers->removeHeader('Bcc'); + return $headers->toString(); + } + + /** + * Prepare body string from message + * + * @param Message $message + * @return string + */ + protected function prepareBody(Message $message) + { + return $message->getBodyText(); + } + + /** + * Lazy load the connection + * + * @return Protocol\Smtp + */ + protected function lazyLoadConnection() + { + // Check if authentication is required and determine required class + $options = $this->getOptions(); + $config = $options->getConnectionConfig(); + $config['host'] = $options->getHost(); + $config['port'] = $options->getPort(); + + $this->setConnection($this->plugin($options->getConnectionClass(), $config)); + + return $this->connect(); + } + + /** + * Connect the connection, and pass it helo + * + * @return Protocol\Smtp + */ + protected function connect() + { + if (! $this->connection instanceof Protocol\Smtp) { + return $this->lazyLoadConnection(); + } + + $this->connection->connect(); + + $this->connectedTime = time(); + + $this->connection->helo($this->getOptions()->getName()); + + return $this->connection; + } +} diff --git a/lib/laminas/laminas-mail/src/Transport/SmtpOptions.php b/lib/laminas/laminas-mail/src/Transport/SmtpOptions.php new file mode 100644 index 000000000..0f14aaacd --- /dev/null +++ b/lib/laminas/laminas-mail/src/Transport/SmtpOptions.php @@ -0,0 +1,209 @@ +name; + } + + /** + * Set the local client hostname or IP + * + * @todo hostname/IP validation + * @param string $name + * @throws \Laminas\Mail\Exception\InvalidArgumentException + * @return SmtpOptions + */ + public function setName($name) + { + if (! is_string($name) && $name !== null) { + throw new Exception\InvalidArgumentException(sprintf( + 'Name must be a string or null; argument of type "%s" provided', + (is_object($name) ? get_class($name) : gettype($name)) + )); + } + $this->name = $name; + return $this; + } + + /** + * Get connection class + * + * This should be either the class Laminas\Mail\Protocol\Smtp or a class + * extending it -- typically a class in the Laminas\Mail\Protocol\Smtp\Auth + * namespace. + * + * @return string + */ + public function getConnectionClass() + { + return $this->connectionClass; + } + + /** + * Set connection class + * + * @param string $connectionClass the value to be set + * @throws \Laminas\Mail\Exception\InvalidArgumentException + * @return SmtpOptions + */ + public function setConnectionClass($connectionClass) + { + if (! is_string($connectionClass) && $connectionClass !== null) { + throw new Exception\InvalidArgumentException(sprintf( + 'Connection class must be a string or null; argument of type "%s" provided', + (is_object($connectionClass) ? get_class($connectionClass) : gettype($connectionClass)) + )); + } + $this->connectionClass = $connectionClass; + return $this; + } + + /** + * Get connection configuration array + * + * @return array + */ + public function getConnectionConfig() + { + return $this->connectionConfig; + } + + /** + * Set connection configuration array + * + * @param array $connectionConfig + * @return SmtpOptions + */ + public function setConnectionConfig(array $connectionConfig) + { + $this->connectionConfig = $connectionConfig; + return $this; + } + + /** + * Get the host name + * + * @return string + */ + public function getHost() + { + return $this->host; + } + + /** + * Set the SMTP host + * + * @todo hostname/IP validation + * @param string $host + * @return SmtpOptions + */ + public function setHost($host) + { + $this->host = (string) $host; + return $this; + } + + /** + * Get the port the SMTP server runs on + * + * @return int + */ + public function getPort() + { + return $this->port; + } + + /** + * Set the port the SMTP server runs on + * + * @param int $port + * @throws \Laminas\Mail\Exception\InvalidArgumentException + * @return SmtpOptions + */ + public function setPort($port) + { + $port = (int) $port; + if ($port < 1) { + throw new Exception\InvalidArgumentException(sprintf( + 'Port must be greater than 1; received "%d"', + $port + )); + } + $this->port = $port; + return $this; + } + + /** + * @return int|null + */ + public function getConnectionTimeLimit() + { + return $this->connectionTimeLimit; + } + + /** + * @param int|null $seconds + * @return self + */ + public function setConnectionTimeLimit($seconds) + { + $this->connectionTimeLimit = $seconds === null + ? null + : (int) $seconds; + + return $this; + } +} diff --git a/lib/laminas/laminas-mail/src/Transport/TransportInterface.php b/lib/laminas/laminas-mail/src/Transport/TransportInterface.php new file mode 100644 index 000000000..fe7719ca3 --- /dev/null +++ b/lib/laminas/laminas-mail/src/Transport/TransportInterface.php @@ -0,0 +1,25 @@ + array(name => value), 'body' => content), null if no parts found + * @throws Exception\RuntimeException + */ + public static function splitMessageStruct($message, $boundary, $EOL = Mime::LINEEND) + { + $parts = static::splitMime($message, $boundary); + if (! $parts) { + return; + } + $result = []; + $headers = null; // "Declare" variable before the first usage "for reading" + $body = null; // "Declare" variable before the first usage "for reading" + foreach ($parts as $part) { + static::splitMessage($part, $headers, $body, $EOL); + $result[] = [ + 'header' => $headers, + 'body' => $body, + ]; + } + return $result; + } + + /** + * split a message in header and body part, if no header or an + * invalid header is found $headers is empty + * + * The charset of the returned headers depend on your iconv settings. + * + * @param string|Headers $message raw message with header and optional content + * @param Headers $headers output param, headers container + * @param string $body output param, content of message + * @param string $EOL EOL string; defaults to {@link Laminas\Mime\Mime::LINEEND} + * @param bool $strict enable strict mode for parsing message + * @return null + */ + public static function splitMessage($message, &$headers, &$body, $EOL = Mime::LINEEND, $strict = false) + { + if ($message instanceof Headers) { + $message = $message->toString(); + } + // check for valid header at first line + $firstlinePos = strpos($message, "\n"); + $firstline = $firstlinePos === false ? $message : substr($message, 0, $firstlinePos); + if (! preg_match('%^[^\s]+[^:]*:%', $firstline)) { + $headers = new Headers(); + // TODO: we're ignoring \r for now - is this function fast enough and is it safe to assume noone needs \r? + $body = str_replace(["\r", "\n"], ['', $EOL], $message); + return; + } + + // see @Laminas-372, pops the first line off a message if it doesn't contain a header + if (! $strict) { + $parts = explode(':', $firstline, 2); + if (count($parts) != 2) { + $message = substr($message, strpos($message, $EOL) + 1); + } + } + + // @todo splitMime removes "\r" sequences, which breaks valid mime + // messages as returned by many mail servers + $headersEOL = $EOL; + + // find an empty line between headers and body + // default is set new line + // @todo Maybe this is too much "magic"; we should be more strict here + if (strpos($message, $EOL . $EOL)) { + list($headers, $body) = explode($EOL . $EOL, $message, 2); + // next is the standard new line + } elseif ($EOL != "\r\n" && strpos($message, "\r\n\r\n")) { + list($headers, $body) = explode("\r\n\r\n", $message, 2); + $headersEOL = "\r\n"; // Headers::fromString will fail with incorrect EOL + // next is the other "standard" new line + } elseif ($EOL != "\n" && strpos($message, "\n\n")) { + list($headers, $body) = explode("\n\n", $message, 2); + $headersEOL = "\n"; + // at last resort find anything that looks like a new line + } else { + ErrorHandler::start(E_NOTICE | E_WARNING); + list($headers, $body) = preg_split("%([\r\n]+)\\1%U", $message, 2); + ErrorHandler::stop(); + } + + $headers = Headers::fromString($headers, $headersEOL); + } + + /** + * split a content type in its different parts + * + * @param string $type content-type + * @param string $wantedPart the wanted part, else an array with all parts is returned + * @return string|array wanted part or all parts as array('type' => content-type, partname => value) + */ + public static function splitContentType($type, $wantedPart = null) + { + return static::splitHeaderField($type, $wantedPart, 'type'); + } + + /** + * split a header field like content type in its different parts + * + * @param string $field header field + * @param string $wantedPart the wanted part, else an array with all parts is returned + * @param string $firstName key name for the first part + * @return string|array wanted part or all parts as array($firstName => firstPart, partname => value) + * @throws Exception\RuntimeException + */ + public static function splitHeaderField($field, $wantedPart = null, $firstName = '0') + { + $wantedPart = strtolower($wantedPart); + $firstName = strtolower($firstName); + + // special case - a bit optimized + if ($firstName === $wantedPart) { + $field = strtok($field, ';'); + return $field[0] == '"' ? substr($field, 1, -1) : $field; + } + + $field = $firstName . '=' . $field; + if (! preg_match_all('%([^=\s]+)\s*=\s*("[^"]+"|[^;]+)(;\s*|$)%', $field, $matches)) { + throw new Exception\RuntimeException('not a valid header field'); + } + + if ($wantedPart) { + foreach ($matches[1] as $key => $name) { + if (strcasecmp($name, $wantedPart)) { + continue; + } + if ($matches[2][$key][0] != '"') { + return $matches[2][$key]; + } + return substr($matches[2][$key], 1, -1); + } + return; + } + + $split = []; + foreach ($matches[1] as $key => $name) { + $name = strtolower($name); + if ($matches[2][$key][0] == '"') { + $split[$name] = substr($matches[2][$key], 1, -1); + } else { + $split[$name] = $matches[2][$key]; + } + } + + return $split; + } + + /** + * decode a quoted printable encoded string + * + * The charset of the returned string depends on your iconv settings. + * + * @param string $string encoded string + * @return string decoded string + */ + public static function decodeQuotedPrintable($string) + { + return iconv_mime_decode($string, ICONV_MIME_DECODE_CONTINUE_ON_ERROR, 'UTF-8'); + } +} diff --git a/lib/laminas/laminas-mime/src/Exception/ExceptionInterface.php b/lib/laminas/laminas-mime/src/Exception/ExceptionInterface.php new file mode 100644 index 000000000..5217cb08e --- /dev/null +++ b/lib/laminas/laminas-mime/src/Exception/ExceptionInterface.php @@ -0,0 +1,13 @@ +parts; + } + + /** + * Sets the given array of Laminas\Mime\Part as the array for the message + * + * @param array $parts + * @return self + */ + public function setParts($parts) + { + $this->parts = $parts; + return $this; + } + + /** + * Append a new Laminas\Mime\Part to the current message + * + * @param \Laminas\Mime\Part $part + * @throws Exception\InvalidArgumentException + * @return self + */ + public function addPart(Part $part) + { + foreach ($this->getParts() as $key => $row) { + if ($part == $row) { + throw new Exception\InvalidArgumentException(sprintf( + 'Provided part %s already defined.', + $part->getId() + )); + } + } + + $this->parts[] = $part; + return $this; + } + + /** + * Check if message needs to be sent as multipart + * MIME message or if it has only one part. + * + * @return bool + */ + public function isMultiPart() + { + return (count($this->parts) > 1); + } + + /** + * Set Laminas\Mime\Mime object for the message + * + * This can be used to set the boundary specifically or to use a subclass of + * Laminas\Mime for generating the boundary. + * + * @param \Laminas\Mime\Mime $mime + * @return self + */ + public function setMime(Mime $mime) + { + $this->mime = $mime; + return $this; + } + + /** + * Returns the Laminas\Mime\Mime object in use by the message + * + * If the object was not present, it is created and returned. Can be used to + * determine the boundary used in this message. + * + * @return \Laminas\Mime\Mime + */ + public function getMime() + { + if ($this->mime === null) { + $this->mime = new Mime(); + } + + return $this->mime; + } + + /** + * Generate MIME-compliant message from the current configuration + * + * This can be a multipart message if more than one MIME part was added. If + * only one part is present, the content of this part is returned. If no + * part had been added, an empty string is returned. + * + * Parts are separated by the mime boundary as defined in Laminas\Mime\Mime. If + * {@link setMime()} has been called before this method, the Laminas\Mime\Mime + * object set by this call will be used. Otherwise, a new Laminas\Mime\Mime object + * is generated and used. + * + * @param string $EOL EOL string; defaults to {@link Laminas\Mime\Mime::LINEEND} + * @return string + */ + public function generateMessage($EOL = Mime::LINEEND) + { + if (! $this->isMultiPart()) { + if (empty($this->parts)) { + return ''; + } + $part = current($this->parts); + $body = $part->getContent($EOL); + } else { + $mime = $this->getMime(); + + $boundaryLine = $mime->boundaryLine($EOL); + $body = 'This is a message in Mime Format. If you see this, ' + . "your mail reader does not support this format." . $EOL; + + foreach (array_keys($this->parts) as $p) { + $body .= $boundaryLine + . $this->getPartHeaders($p, $EOL) + . $EOL + . $this->getPartContent($p, $EOL); + } + + $body .= $mime->mimeEnd($EOL); + } + + return trim($body); + } + + /** + * Get the headers of a given part as an array + * + * @param int $partnum + * @return array + */ + public function getPartHeadersArray($partnum) + { + return $this->parts[$partnum]->getHeadersArray(); + } + + /** + * Get the headers of a given part as a string + * + * @param int $partnum + * @param string $EOL + * @return string + */ + public function getPartHeaders($partnum, $EOL = Mime::LINEEND) + { + return $this->parts[$partnum]->getHeaders($EOL); + } + + /** + * Get the (encoded) content of a given part as a string + * + * @param int $partnum + * @param string $EOL + * @return string + */ + public function getPartContent($partnum, $EOL = Mime::LINEEND) + { + return $this->parts[$partnum]->getContent($EOL); + } + + /** + * Explode MIME multipart string into separate parts + * + * Parts consist of the header and the body of each MIME part. + * + * @param string $body + * @param string $boundary + * @throws Exception\RuntimeException + * @return array + */ + // @codingStandardsIgnoreStart + protected static function _disassembleMime($body, $boundary) + { + // @codingStandardsIgnoreEnd + $start = 0; + $res = []; + // find every mime part limiter and cut out the + // string before it. + // the part before the first boundary string is discarded: + $p = strpos($body, '--' . $boundary."\n", $start); + if ($p === false) { + // no parts found! + return []; + } + + // position after first boundary line + $start = $p + 3 + strlen($boundary); + + while (($p = strpos($body, '--' . $boundary . "\n", $start)) !== false) { + $res[] = substr($body, $start, $p - $start); + $start = $p + 3 + strlen($boundary); + } + + // no more parts, find end boundary + $p = strpos($body, '--' . $boundary . '--', $start); + if ($p === false) { + throw new Exception\RuntimeException('Not a valid Mime Message: End Missing'); + } + + // the remaining part also needs to be parsed: + $res[] = substr($body, $start, $p - $start); + return $res; + } + + /** + * Decodes a MIME encoded string and returns a Laminas\Mime\Message object with + * all the MIME parts set according to the given string + * + * @param string $message + * @param string $boundary Multipart boundary; if omitted, $message will be + * treated as a single part. + * @param string $EOL EOL string; defaults to {@link Laminas\Mime\Mime::LINEEND} + * @throws Exception\RuntimeException + * @return Message + */ + public static function createFromMessage($message, $boundary = null, $EOL = Mime::LINEEND) + { + if ($boundary) { + $parts = Decode::splitMessageStruct($message, $boundary, $EOL); + } else { + Decode::splitMessage($message, $headers, $body, $EOL); + $parts = [[ + 'header' => $headers, + 'body' => $body, + ]]; + } + + $res = new static(); + foreach ($parts as $part) { + // now we build a new MimePart for the current Message Part: + $properties = []; + foreach ($part['header'] as $header) { + /** @var \Laminas\Mail\Header\HeaderInterface $header */ + /** + * @todo check for characterset and filename + */ + + $fieldName = $header->getFieldName(); + $fieldValue = $header->getFieldValue(); + switch (strtolower($fieldName)) { + case 'content-type': + $properties['type'] = $fieldValue; + break; + case 'content-transfer-encoding': + $properties['encoding'] = $fieldValue; + break; + case 'content-id': + $properties['id'] = trim($fieldValue, '<>'); + break; + case 'content-disposition': + $properties['disposition'] = $fieldValue; + break; + case 'content-description': + $properties['description'] = $fieldValue; + break; + case 'content-location': + $properties['location'] = $fieldValue; + break; + case 'content-language': + $properties['language'] = $fieldValue; + break; + default: + // Ignore unknown header + break; + } + } + + $body = $part['body']; + + if (isset($properties['encoding'])) { + switch ($properties['encoding']) { + case 'quoted-printable': + $body = quoted_printable_decode($body); + break; + case 'base64': + $body = base64_decode($body); + break; + } + } + + $newPart = new Part($body); + foreach ($properties as $key => $value) { + $newPart->$key = $value; + } + $res->addPart($newPart); + } + + return $res; + } +} diff --git a/lib/laminas/laminas-mime/src/Mime.php b/lib/laminas/laminas-mime/src/Mime.php new file mode 100644 index 000000000..20004023f --- /dev/null +++ b/lib/laminas/laminas-mime/src/Mime.php @@ -0,0 +1,398 @@ +[\x21\x23-\x26\x2a\x2b\x2d\x5e\5f\60\x7b-\x7ea-zA-Z0-9]+)\?(?P[\x21\x23-\x26\x2a\x2b\x2d\x5e\5f\60\x7b-\x7ea-zA-Z0-9]+)\?(?P[\x21-\x3e\x40-\x7e]+)#'; + // @codingStandardsIgnoreEnd + + protected $boundary; + protected static $makeUnique = 0; + + // lookup-Tables for QuotedPrintable + public static $qpKeys = [ + "\x00","\x01","\x02","\x03","\x04","\x05","\x06","\x07", + "\x08","\x09","\x0A","\x0B","\x0C","\x0D","\x0E","\x0F", + "\x10","\x11","\x12","\x13","\x14","\x15","\x16","\x17", + "\x18","\x19","\x1A","\x1B","\x1C","\x1D","\x1E","\x1F", + "\x7F","\x80","\x81","\x82","\x83","\x84","\x85","\x86", + "\x87","\x88","\x89","\x8A","\x8B","\x8C","\x8D","\x8E", + "\x8F","\x90","\x91","\x92","\x93","\x94","\x95","\x96", + "\x97","\x98","\x99","\x9A","\x9B","\x9C","\x9D","\x9E", + "\x9F","\xA0","\xA1","\xA2","\xA3","\xA4","\xA5","\xA6", + "\xA7","\xA8","\xA9","\xAA","\xAB","\xAC","\xAD","\xAE", + "\xAF","\xB0","\xB1","\xB2","\xB3","\xB4","\xB5","\xB6", + "\xB7","\xB8","\xB9","\xBA","\xBB","\xBC","\xBD","\xBE", + "\xBF","\xC0","\xC1","\xC2","\xC3","\xC4","\xC5","\xC6", + "\xC7","\xC8","\xC9","\xCA","\xCB","\xCC","\xCD","\xCE", + "\xCF","\xD0","\xD1","\xD2","\xD3","\xD4","\xD5","\xD6", + "\xD7","\xD8","\xD9","\xDA","\xDB","\xDC","\xDD","\xDE", + "\xDF","\xE0","\xE1","\xE2","\xE3","\xE4","\xE5","\xE6", + "\xE7","\xE8","\xE9","\xEA","\xEB","\xEC","\xED","\xEE", + "\xEF","\xF0","\xF1","\xF2","\xF3","\xF4","\xF5","\xF6", + "\xF7","\xF8","\xF9","\xFA","\xFB","\xFC","\xFD","\xFE", + "\xFF" + ]; + + public static $qpReplaceValues = [ + "=00","=01","=02","=03","=04","=05","=06","=07", + "=08","=09","=0A","=0B","=0C","=0D","=0E","=0F", + "=10","=11","=12","=13","=14","=15","=16","=17", + "=18","=19","=1A","=1B","=1C","=1D","=1E","=1F", + "=7F","=80","=81","=82","=83","=84","=85","=86", + "=87","=88","=89","=8A","=8B","=8C","=8D","=8E", + "=8F","=90","=91","=92","=93","=94","=95","=96", + "=97","=98","=99","=9A","=9B","=9C","=9D","=9E", + "=9F","=A0","=A1","=A2","=A3","=A4","=A5","=A6", + "=A7","=A8","=A9","=AA","=AB","=AC","=AD","=AE", + "=AF","=B0","=B1","=B2","=B3","=B4","=B5","=B6", + "=B7","=B8","=B9","=BA","=BB","=BC","=BD","=BE", + "=BF","=C0","=C1","=C2","=C3","=C4","=C5","=C6", + "=C7","=C8","=C9","=CA","=CB","=CC","=CD","=CE", + "=CF","=D0","=D1","=D2","=D3","=D4","=D5","=D6", + "=D7","=D8","=D9","=DA","=DB","=DC","=DD","=DE", + "=DF","=E0","=E1","=E2","=E3","=E4","=E5","=E6", + "=E7","=E8","=E9","=EA","=EB","=EC","=ED","=EE", + "=EF","=F0","=F1","=F2","=F3","=F4","=F5","=F6", + "=F7","=F8","=F9","=FA","=FB","=FC","=FD","=FE", + "=FF" + ]; + // @codingStandardsIgnoreStart + public static $qpKeysString = + "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1A\x1B\x1C\x1D\x1E\x1F\x7F\x80\x81\x82\x83\x84\x85\x86\x87\x88\x89\x8A\x8B\x8C\x8D\x8E\x8F\x90\x91\x92\x93\x94\x95\x96\x97\x98\x99\x9A\x9B\x9C\x9D\x9E\x9F\xA0\xA1\xA2\xA3\xA4\xA5\xA6\xA7\xA8\xA9\xAA\xAB\xAC\xAD\xAE\xAF\xB0\xB1\xB2\xB3\xB4\xB5\xB6\xB7\xB8\xB9\xBA\xBB\xBC\xBD\xBE\xBF\xC0\xC1\xC2\xC3\xC4\xC5\xC6\xC7\xC8\xC9\xCA\xCB\xCC\xCD\xCE\xCF\xD0\xD1\xD2\xD3\xD4\xD5\xD6\xD7\xD8\xD9\xDA\xDB\xDC\xDD\xDE\xDF\xE0\xE1\xE2\xE3\xE4\xE5\xE6\xE7\xE8\xE9\xEA\xEB\xEC\xED\xEE\xEF\xF0\xF1\xF2\xF3\xF4\xF5\xF6\xF7\xF8\xF9\xFA\xFB\xFC\xFD\xFE\xFF"; + // @codingStandardsIgnoreEnd + + /** + * Check if the given string is "printable" + * + * Checks that a string contains no unprintable characters. If this returns + * false, encode the string for secure delivery. + * + * @param string $str + * @return bool + */ + public static function isPrintable($str) + { + return (strcspn($str, static::$qpKeysString) == strlen($str)); + } + + /** + * Encode a given string with the QUOTED_PRINTABLE mechanism and wrap the lines. + * + * @param string $str + * @param int $lineLength Defaults to {@link LINELENGTH} + * @param string $lineEnd Defaults to {@link LINEEND} + * @return string + */ + public static function encodeQuotedPrintable( + $str, + $lineLength = self::LINELENGTH, + $lineEnd = self::LINEEND + ) { + $out = ''; + $str = self::_encodeQuotedPrintable($str); + + // Split encoded text into separate lines + $initialPtr = 0; + $strLength = strlen($str); + while ($initialPtr < $strLength) { + $continueAt = $strLength - $initialPtr; + + if ($continueAt > $lineLength) { + $continueAt = $lineLength; + } + + $chunk = substr($str, $initialPtr, $continueAt); + + // Ensure we are not splitting across an encoded character + $endingMarkerPos = strrpos($chunk, '='); + if ($endingMarkerPos !== false && $endingMarkerPos >= strlen($chunk) - 2) { + $chunk = substr($chunk, 0, $endingMarkerPos); + $continueAt = $endingMarkerPos; + } + + if (ord($chunk[0]) == 0x2E) { // 0x2E is a dot + $chunk = '=2E' . substr($chunk, 1); + } + + // copied from swiftmailer https://git.io/vAXU1 + switch (ord(substr($chunk, strlen($chunk) - 1))) { + case 0x09: // Horizontal Tab + $chunk = substr_replace($chunk, '=09', strlen($chunk) - 1, 1); + break; + case 0x20: // Space + $chunk = substr_replace($chunk, '=20', strlen($chunk) - 1, 1); + break; + } + + // Add string and continue + $out .= $chunk . '=' . $lineEnd; + $initialPtr += $continueAt; + } + + $out = rtrim($out, $lineEnd); + $out = rtrim($out, '='); + return $out; + } + + /** + * Converts a string into quoted printable format. + * + * @param string $str + * @return string + */ + // @codingStandardsIgnoreStart + private static function _encodeQuotedPrintable($str) + { + // @codingStandardsIgnoreEnd + $str = str_replace('=', '=3D', $str); + $str = str_replace(static::$qpKeys, static::$qpReplaceValues, $str); + $str = rtrim($str); + return $str; + } + + /** + * Encode a given string with the QUOTED_PRINTABLE mechanism for Mail Headers. + * + * Mail headers depend on an extended quoted printable algorithm otherwise + * a range of bugs can occur. + * + * @param string $str + * @param string $charset + * @param int $lineLength Defaults to {@link LINELENGTH} + * @param string $lineEnd Defaults to {@link LINEEND} + * @return string + */ + public static function encodeQuotedPrintableHeader( + $str, + $charset, + $lineLength = self::LINELENGTH, + $lineEnd = self::LINEEND + ) { + // Reduce line-length by the length of the required delimiter, charsets and encoding + $prefix = sprintf('=?%s?Q?', $charset); + $lineLength = $lineLength - strlen($prefix) - 3; + + $str = self::_encodeQuotedPrintable($str); + + // Mail-Header required chars have to be encoded also: + $str = str_replace(['?', ',', ' ', '_'], ['=3F', '=2C', '=20', '=5F'], $str); + + // initialize first line, we need it anyways + $lines = [0 => '']; + + // Split encoded text into separate lines + $tmp = ''; + while (strlen($str) > 0) { + $currentLine = max(count($lines) - 1, 0); + $token = static::getNextQuotedPrintableToken($str); + $substr = substr($str, strlen($token)); + $str = (false === $substr) ? '' : $substr; + + $tmp .= $token; + if ($token === '=20') { + // only if we have a single char token or space, we can append the + // tempstring it to the current line or start a new line if necessary. + $lineLimitReached = (strlen($lines[$currentLine] . $tmp) > $lineLength); + $noCurrentLine = ($lines[$currentLine] === ''); + if ($noCurrentLine && $lineLimitReached) { + $lines[$currentLine] = $tmp; + $lines[$currentLine + 1] = ''; + } elseif ($lineLimitReached) { + $lines[$currentLine + 1] = $tmp; + } else { + $lines[$currentLine] .= $tmp; + } + $tmp = ''; + } + // don't forget to append the rest to the last line + if (strlen($str) === 0) { + $lines[$currentLine] .= $tmp; + } + } + + // assemble the lines together by pre- and appending delimiters, charset, encoding. + for ($i = 0, $count = count($lines); $i < $count; $i++) { + $lines[$i] = " " . $prefix . $lines[$i] . "?="; + } + $str = trim(implode($lineEnd, $lines)); + return $str; + } + + /** + * Retrieves the first token from a quoted printable string. + * + * @param string $str + * @return string + */ + private static function getNextQuotedPrintableToken($str) + { + if (0 === strpos($str, '=')) { + $token = substr($str, 0, 3); + } else { + $token = substr($str, 0, 1); + } + return $token; + } + + /** + * Encode a given string in mail header compatible base64 encoding. + * + * @param string $str + * @param string $charset + * @param int $lineLength Defaults to {@link LINELENGTH} + * @param string $lineEnd Defaults to {@link LINEEND} + * @return string + */ + public static function encodeBase64Header( + $str, + $charset, + $lineLength = self::LINELENGTH, + $lineEnd = self::LINEEND + ) { + $prefix = '=?' . $charset . '?B?'; + $suffix = '?='; + $remainingLength = $lineLength - strlen($prefix) - strlen($suffix); + + $encodedValue = static::encodeBase64($str, $remainingLength, $lineEnd); + $encodedValue = str_replace($lineEnd, $suffix . $lineEnd . ' ' . $prefix, $encodedValue); + $encodedValue = $prefix . $encodedValue . $suffix; + return $encodedValue; + } + + /** + * Encode a given string in base64 encoding and break lines + * according to the maximum linelength. + * + * @param string $str + * @param int $lineLength Defaults to {@link LINELENGTH} + * @param string $lineEnd Defaults to {@link LINEEND} + * @return string + */ + public static function encodeBase64( + $str, + $lineLength = self::LINELENGTH, + $lineEnd = self::LINEEND + ) { + $lineLength = $lineLength - ($lineLength % 4); + return rtrim(chunk_split(base64_encode($str), $lineLength, $lineEnd)); + } + + /** + * Constructor + * + * @param null|string $boundary + * @access public + */ + public function __construct($boundary = null) + { + // This string needs to be somewhat unique + if ($boundary === null) { + $this->boundary = '=_' . md5(microtime(1) . static::$makeUnique++); + } else { + $this->boundary = $boundary; + } + } + + /** + * Encode the given string with the given encoding. + * + * @param string $str + * @param string $encoding + * @param string $EOL EOL string; defaults to {@link LINEEND} + * @return string + */ + public static function encode($str, $encoding, $EOL = self::LINEEND) + { + switch ($encoding) { + case self::ENCODING_BASE64: + return static::encodeBase64($str, self::LINELENGTH, $EOL); + + case self::ENCODING_QUOTEDPRINTABLE: + return static::encodeQuotedPrintable($str, self::LINELENGTH, $EOL); + + default: + /** + * @todo 7Bit and 8Bit is currently handled the same way. + */ + return $str; + } + } + + /** + * Return a MIME boundary + * + * @access public + * @return string + */ + public function boundary() + { + return $this->boundary; + } + + /** + * Return a MIME boundary line + * + * @param string $EOL Defaults to {@link LINEEND} + * @access public + * @return string + */ + public function boundaryLine($EOL = self::LINEEND) + { + return $EOL . '--' . $this->boundary . $EOL; + } + + /** + * Return MIME ending + * + * @param string $EOL Defaults to {@link LINEEND} + * @access public + * @return string + */ + public function mimeEnd($EOL = self::LINEEND) + { + return $EOL . '--' . $this->boundary . '--' . $EOL; + } + + /** + * Detect MIME charset + * + * Extract parts according to https://tools.ietf.org/html/rfc2047#section-2 + * + * @param string $str + * @return string + */ + public static function mimeDetectCharset($str) + { + if (preg_match(self::CHARSET_REGEX, $str, $matches)) { + return strtoupper($matches['charset']); + } + + return 'ASCII'; + } +} diff --git a/lib/laminas/laminas-mime/src/Part.php b/lib/laminas/laminas-mime/src/Part.php new file mode 100644 index 000000000..1760e016c --- /dev/null +++ b/lib/laminas/laminas-mime/src/Part.php @@ -0,0 +1,483 @@ +setContent($content); + } + + /** + * @todo error checking for setting $type + * @todo error checking for setting $encoding + */ + + /** + * Set type + * @param string $type + * @return self + */ + public function setType($type = Mime::TYPE_OCTETSTREAM) + { + $this->type = $type; + return $this; + } + + /** + * Get type + * @return string + */ + public function getType() + { + return $this->type; + } + + /** + * Set encoding + * @param string $encoding + * @return self + */ + public function setEncoding($encoding = Mime::ENCODING_8BIT) + { + $this->encoding = $encoding; + return $this; + } + + /** + * Get encoding + * @return string + */ + public function getEncoding() + { + return $this->encoding; + } + + /** + * Set id + * @param string $id + * @return self + */ + public function setId($id) + { + $this->id = $id; + return $this; + } + + /** + * Get id + * @return string + */ + public function getId() + { + return $this->id; + } + + /** + * Set disposition + * @param string $disposition + * @return self + */ + public function setDisposition($disposition) + { + $this->disposition = $disposition; + return $this; + } + + /** + * Get disposition + * @return string + */ + public function getDisposition() + { + return $this->disposition; + } + + /** + * Set description + * @param string $description + * @return self + */ + public function setDescription($description) + { + $this->description = $description; + return $this; + } + + /** + * Get description + * @return string + */ + public function getDescription() + { + return $this->description; + } + + /** + * Set filename + * @param string $fileName + * @return self + */ + public function setFileName($fileName) + { + $this->filename = $fileName; + return $this; + } + + /** + * Get filename + * @return string + */ + public function getFileName() + { + return $this->filename; + } + + /** + * Set charset + * @param string $type + * @return self + */ + public function setCharset($charset) + { + $this->charset = $charset; + return $this; + } + + /** + * Get charset + * @return string + */ + public function getCharset() + { + return $this->charset; + } + + /** + * Set boundary + * @param string $boundary + * @return self + */ + public function setBoundary($boundary) + { + $this->boundary = $boundary; + return $this; + } + + /** + * Get boundary + * @return string + */ + public function getBoundary() + { + return $this->boundary; + } + + /** + * Set location + * @param string $location + * @return self + */ + public function setLocation($location) + { + $this->location = $location; + return $this; + } + + /** + * Get location + * @return string + */ + public function getLocation() + { + return $this->location; + } + + /** + * Set language + * @param string $language + * @return self + */ + public function setLanguage($language) + { + $this->language = $language; + return $this; + } + + /** + * Get language + * @return string + */ + public function getLanguage() + { + return $this->language; + } + + /** + * Set content + * @param mixed $content String or Stream containing the content + * @throws Exception\InvalidArgumentException + * @return self + */ + public function setContent($content) + { + if (! is_string($content) && ! is_resource($content)) { + throw new Exception\InvalidArgumentException(sprintf( + 'Content must be string or resource; received "%s"', + is_object($content) ? get_class($content) : gettype($content) + )); + } + $this->content = $content; + if (is_resource($content)) { + $this->isStream = true; + } + + return $this; + } + + /** + * Set isStream + * @param bool $isStream + * @return self + */ + public function setIsStream($isStream = false) + { + $this->isStream = (bool) $isStream; + return $this; + } + + /** + * Get isStream + * @return bool + */ + public function getIsStream() + { + return $this->isStream; + } + + /** + * Set filters + * @param array $filters + * @return self + */ + public function setFilters($filters = []) + { + $this->filters = $filters; + return $this; + } + + /** + * Get Filters + * @return array + */ + public function getFilters() + { + return $this->filters; + } + + /** + * check if this part can be read as a stream. + * if true, getEncodedStream can be called, otherwise + * only getContent can be used to fetch the encoded + * content of the part + * + * @return bool + */ + public function isStream() + { + return $this->isStream; + } + + /** + * if this was created with a stream, return a filtered stream for + * reading the content. very useful for large file attachments. + * + * @param string $EOL + * @return resource + * @throws Exception\RuntimeException if not a stream or unable to append filter + */ + public function getEncodedStream($EOL = Mime::LINEEND) + { + if (! $this->isStream) { + throw new Exception\RuntimeException('Attempt to get a stream from a string part'); + } + + //stream_filter_remove(); // ??? is that right? + switch ($this->encoding) { + case Mime::ENCODING_QUOTEDPRINTABLE: + if (array_key_exists(Mime::ENCODING_QUOTEDPRINTABLE, $this->filters)) { + stream_filter_remove($this->filters[Mime::ENCODING_QUOTEDPRINTABLE]); + } + $filter = stream_filter_append( + $this->content, + 'convert.quoted-printable-encode', + STREAM_FILTER_READ, + [ + 'line-length' => 76, + 'line-break-chars' => $EOL + ] + ); + $this->filters[Mime::ENCODING_QUOTEDPRINTABLE] = $filter; + if (! is_resource($filter)) { + throw new Exception\RuntimeException('Failed to append quoted-printable filter'); + } + break; + case Mime::ENCODING_BASE64: + if (array_key_exists(Mime::ENCODING_BASE64, $this->filters)) { + stream_filter_remove($this->filters[Mime::ENCODING_BASE64]); + } + $filter = stream_filter_append( + $this->content, + 'convert.base64-encode', + STREAM_FILTER_READ, + [ + 'line-length' => 76, + 'line-break-chars' => $EOL + ] + ); + $this->filters[Mime::ENCODING_BASE64] = $filter; + if (! is_resource($filter)) { + throw new Exception\RuntimeException('Failed to append base64 filter'); + } + break; + default: + } + return $this->content; + } + + /** + * Get the Content of the current Mime Part in the given encoding. + * + * @param string $EOL + * @return string + */ + public function getContent($EOL = Mime::LINEEND) + { + if ($this->isStream) { + $encodedStream = $this->getEncodedStream($EOL); + $encodedStreamContents = stream_get_contents($encodedStream); + $streamMetaData = stream_get_meta_data($encodedStream); + + if (isset($streamMetaData['seekable']) && $streamMetaData['seekable']) { + rewind($encodedStream); + } + + return $encodedStreamContents; + } + return Mime::encode($this->content, $this->encoding, $EOL); + } + + /** + * Get the RAW unencoded content from this part + * @return string + */ + public function getRawContent() + { + if ($this->isStream) { + return stream_get_contents($this->content); + } + return $this->content; + } + + /** + * Create and return the array of headers for this MIME part + * + * @access public + * @param string $EOL + * @return array + */ + public function getHeadersArray($EOL = Mime::LINEEND) + { + $headers = []; + + $contentType = $this->type; + if ($this->charset) { + $contentType .= '; charset=' . $this->charset; + } + + if ($this->boundary) { + $contentType .= ';' . $EOL + . " boundary=\"" . $this->boundary . '"'; + } + + $headers[] = ['Content-Type', $contentType]; + + if ($this->encoding) { + $headers[] = ['Content-Transfer-Encoding', $this->encoding]; + } + + if ($this->id) { + $headers[] = ['Content-ID', '<' . $this->id . '>']; + } + + if ($this->disposition) { + $disposition = $this->disposition; + if ($this->filename) { + $disposition .= '; filename="' . $this->filename . '"'; + } + $headers[] = ['Content-Disposition', $disposition]; + } + + if ($this->description) { + $headers[] = ['Content-Description', $this->description]; + } + + if ($this->location) { + $headers[] = ['Content-Location', $this->location]; + } + + if ($this->language) { + $headers[] = ['Content-Language', $this->language]; + } + + return $headers; + } + + /** + * Return the headers for this part as a string + * + * @param string $EOL + * @return String + */ + public function getHeaders($EOL = Mime::LINEEND) + { + $res = ''; + foreach ($this->getHeadersArray($EOL) as $header) { + $res .= $header[0] . ': ' . $header[1] . $EOL; + } + + return $res; + } +} diff --git a/lib/laminas/laminas-stdlib/CHANGELOG.md b/lib/laminas/laminas-stdlib/CHANGELOG.md new file mode 100644 index 000000000..57b79833f --- /dev/null +++ b/lib/laminas/laminas-stdlib/CHANGELOG.md @@ -0,0 +1,385 @@ +# Changelog + +All notable changes to this project will be documented in this file, in reverse chronological order by release. + +## 3.2.1 - 2018-08-28 + +### Added + +- Nothing. + +### Changed + +- Nothing. + +### Deprecated + +- Nothing. + +### Removed + +- Nothing. + +### Fixed + +- [zendframework/zend-stdlib#92](https://github.com/zendframework/zend-stdlib/pull/92) fixes serialization of `SplPriorityQueue` by ensuring its `$serial` + property is also serialized. + +- [zendframework/zend-stdlib#91](https://github.com/zendframework/zend-stdlib/pull/91) fixes behavior in the `ArrayObject` implementation that was not + compatible with PHP 7.3. + +## 3.2.0 - 2018-04-30 + +### Added + +- [zendframework/zend-stdlib#87](https://github.com/zendframework/zend-stdlib/pull/87) adds support for PHP 7.2. + +### Changed + +- Nothing. + +### Deprecated + +- Nothing. + +### Removed + +- [zendframework/zend-stdlib#87](https://github.com/zendframework/zend-stdlib/pull/87) removes support for HHVM. + +### Fixed + +- Nothing. + +## 3.1.1 - 2018-04-12 + +### Added + +- Nothing. + +### Changed + +- [zendframework/zend-stdlib#67](https://github.com/zendframework/zend-stdlib/pull/67) changes the typehint of the `$content` property + of the `Message` class to indicate it is a string. All known implementations + already assumed this. + +### Deprecated + +- Nothing. + +### Removed + +- Nothing. + +### Fixed + +- [zendframework/zend-stdlib#60](https://github.com/zendframework/zend-stdlib/pull/60) fixes an issue whereby calling `remove()` would + incorrectly re-calculate the maximum priority stored in the queue. + +- [zendframework/zend-stdlib#60](https://github.com/zendframework/zend-stdlib/pull/60) fixes an infinite loop condition that can occur when + inserting an item at 0 priority. + +## 3.1.0 - 2016-09-13 + +### Added + +- [zendframework/zend-stdlib#63](https://github.com/zendframework/zend-stdlib/pull/63) adds a new + `Laminas\Stdlib\ConsoleHelper` class, providing minimal support for writing + output to `STDOUT` and `STDERR`, with optional colorization, when the console + supports that feature. + +### Deprecated + +- [zendframework/zend-stdlib#38](https://github.com/zendframework/zend-stdlib/pull/38) deprecates + `Laminas\Stdlib\JsonSerializable`, as all supported version of PHP now support + it. + +### Removed + +- Nothing. + +### Fixed + +- Nothing. + +## 3.0.1 - 2016-04-12 + +### Added + +- Nothing. + +### Deprecated + +- Nothing. + +### Removed + +- Nothing. + +### Fixed + +- [zendframework/zend-stdlib#59](https://github.com/zendframework/zend-stdlib/pull/59) fixes a notice + when defining the `Laminas\Json\Json::GLOB_BRACE` constant on systems using + non-gcc glob implementations. + +## 3.0.0 - 2016-02-03 + +### Added + +- [zendframework/zend-stdlib#51](https://github.com/zendframework/zend-stdlib/pull/51) adds PHP 7 as a + supported PHP version. +- [zendframework/zend-stdlib#51](https://github.com/zendframework/zend-stdlib/pull/51) adds a migration + document from v2 to v3. Hint: if you use hydrators, you need to be using + laminas-hydrator instead! +- [zendframework/zend-stdlib#51](https://github.com/zendframework/zend-stdlib/pull/51) adds automated + documentation builds to gh-pages. + +### Deprecated + +- Nothing. + +### Removed + +- [zendframework/zend-stdlib#33](https://github.com/zendframework/zend-stdlib/pull/33) - removed + deprecated classes + - *All Hydrator classes* see zendframework/zend-stdlib#22. + - `Laminas\Stdlib\CallbackHandler` see zendframework/zend-stdlib#35 +- [zendframework/zend-stdlib#37](https://github.com/zendframework/zend-stdlib/pull/37) - removed + deprecated classes and polyfills: + - `Laminas\Stdlib\DateTime`; this had been deprecated since 2.5, and only + existed as a polyfill for the `createFromISO8601()` support, now standard + in all PHP versions we support. + - `Laminas\Stdlib\Exception\InvalidCallbackException`, which was unused since zendframework/zend-stdlib#33. + - `Laminas\Stdlib\Guard\GuardUtils`, which duplicated `Laminas\Stdlib\Guard\AllGuardsTrait` + to allow usage with pre-PHP 5.4 versions. + - `src/compatibility/autoload.php`, which has been dprecated since 2.5. +- [zendframework/zend-stdlib#37](https://github.com/zendframework/zend-stdlib/pull/37) - removed + unneeded dependencies: + - laminas-config (used only in testing ArrayUtils, and the test was redundant) + - laminas-serializer (no longer used) +- [zendframework/zend-stdlib#51](https://github.com/zendframework/zend-stdlib/pull/51) removes the + documentation for hydrators, as those are part of the laminas-hydrator + component. + +### Fixed + +- Nothing. + +## 2.7.4 - 2015-10-15 + +### Added + +- Nothing. + +### Deprecated + +- [zendframework/zend-stdlib#35](https://github.com/zendframework/zend-stdlib/pull/35) deprecates + `Laminas\Stdlib\CallbackHandler`, as the one component that used it, + laminas-eventmanager, will no longer depend on it starting in v3. + +### Removed + +- Nothing. + +### Fixed + +- Nothing. + +## 2.7.3 - 2015-09-24 + +### Added + +- Nothing. + +### Deprecated + +- Nothing. + +### Removed + +- Nothing. + +### Fixed + +- [zendframework/zend-stdlib#27](https://github.com/zendframework/zend-stdlib/pull/27) fixes a race + condition in the `FastPriorityQueue::remove()` logic that occurs when removing + items iteratively from the same priority of a queue. + +## 2.7.2 - 2015-09-23 + +### Added + +- Nothing. + +### Deprecated + +- Nothing. + +### Removed + +- Nothing. + +### Fixed + +- [zendframework/zend-stdlib#26](https://github.com/zendframework/zend-stdlib/pull/26) fixes a subtle + inheritance issue with deprecation in the hydrators, and updates the + `HydratorInterface` to also extend the laminas-hydrator `HydratorInterface` to + ensure LSP is preserved. + +## 2.7.1 - 2015-09-22 + +### Added + +- Nothing. + +### Deprecated + +- Nothing. + +### Removed + +- Nothing. + +### Fixed + +- [zendframework/zend-stdlib#24](https://github.com/zendframework/zend-stdlib/pull/24) fixes an import in + `FastPriorityQueue` to alias `SplPriorityQueue` in order to disambiguate with + the local override present in the component. + +## 2.7.0 - 2015-09-22 + +### Added + +- [zendframework/zend-stdlib#19](https://github.com/zendframework/zend-stdlib/pull/19) adds a new + `FastPriorityQueue` implementation. It follows the same signature as + `SplPriorityQueue`, but uses a performance-optimized algorithm: + + - inserts are 2x faster than `SplPriorityQueue` and 3x faster than the + `Laminas\Stdlib\PriorityQueue` implementation. + - extracts are 4x faster than `SplPriorityQueue` and 4-5x faster than the + `Laminas\Stdlib\PriorityQueue` implementation. + + The intention is to use this as a drop-in replacement in the + `laminas-eventmanager` component to provide performance benefits. + +### Deprecated + +- [zendframework/zend-stdlib#20](https://github.com/zendframework/zend-stdlib/pull/20) deprecates *all + hydrator* classes, in favor of the new [laminas-hydrator](https://github.com/laminas/laminas-hydrator) + component. All classes were updated to extend their laminas-hydrator equivalents, + and marked as `@deprecated`, indicating the equivalent class from the other + repository. + + Users *should* immediately start changing their code to use the laminas-hydrator + equivalents; in most cases, this can be as easy as removing the `Stdlib` + namespace from import statements or hydrator configuration. Hydrators will be + removed entirely from laminas-stdlib in v3.0, and all future updates to hydrators + will occur in the laminas-hydrator library. + + Changes with backwards compatibility implications: + + - Users implementing `Laminas\Stdlib\Hydrator\HydratorAwareInterface` will need to + update their `setHydrator()` implementation to typehint on + `Laminas\Hydrator\HydratorInterface`. This can be done by changing the import + statement for that interface as follows: + + ```php + // Replace this: + use Laminas\Stdlib\Hydrator\HydratorInterface; + // with this: + use Laminas\Hydrator\HydratorInterface; + ``` + + If you are not using imports, change the typehint within the signature itself: + + ```php + // Replace this: + public function setHydrator(\Laminas\Stdlib\Hydrator\HydratorInterface $hydrator) + // with this: + public function setHydrator(\Laminas\Hydrator\HydratorInterface $hydrator) + ``` + + If you are using `Laminas\Stdlib\Hydrator\HydratorAwareTrait`, no changes are + necessary, unless you override that method. + + - If you were catching hydrator-generated exceptions, these were previously in + the `Laminas\Stdlib\Exception` namespace. You will need to update your code to + catch exceptions in the `Laminas\Hydrator\Exception` namespace. + + - Users who *do* migrate to laminas-hydrator may end up in a situation where + their code will not work with existing libraries that are still type-hinting + on the laminas-stdlib interfaces. We will be attempting to address that ASAP, + but the deprecation within laminas-stdlib is necessary as a first step. + + In the meantime, you can write hydrators targeting laminas-stdlib still in + order to guarantee compatibility. + +### Removed + +- Nothing. + +### Fixed + +- Nothing. + +## 2.6.0 - 2015-07-21 + +### Added + +- [zendframework/zend-stdlib#13](https://github.com/zendframework/zend-stdlib/pull/13) adds + `Laminas\Stdlib\Hydrator\Iterator`, which provides mechanisms for hydrating + objects when iterating a traversable. This allows creating generic collection + resultsets; the original idea was pulled from + [PhlyMongo](https://github.com/phly/PhlyMongo), where it was used to hydrate + collections retrieved from MongoDB. + +### Deprecated + +- Nothing. + +### Removed + +- Nothing. + +### Fixed + +- Nothing. + +## 2.5.2 - 2015-07-21 + +### Added + +- Nothing. + +### Deprecated + +- Nothing. + +### Removed + +- Nothing. + +### Fixed + +- [zendframework/zend-stdlib#9](https://github.com/zendframework/zend-stdlib/pull/9) fixes an issue with + count incrementation during insert in PriorityList, ensuring that incrementation only + occurs when the item inserted was not previously present in the list. + +## 2.4.4 - 2015-07-21 + +### Added + +- Nothing. + +### Deprecated + +- Nothing. + +### Removed + +- Nothing. + +### Fixed + +- [zendframework/zend-stdlib#9](https://github.com/zendframework/zend-stdlib/pull/9) fixes an issue with + count incrementation during insert in PriorityList, ensuring that incrementation only + occurs when the item inserted was not previously present in the list. diff --git a/lib/laminas/laminas-stdlib/COPYRIGHT.md b/lib/laminas/laminas-stdlib/COPYRIGHT.md new file mode 100644 index 000000000..c4fc4fee1 --- /dev/null +++ b/lib/laminas/laminas-stdlib/COPYRIGHT.md @@ -0,0 +1,2 @@ +Copyright (c) 2019, Laminas Foundation. +All rights reserved. (https://getlaminas.org/) diff --git a/lib/laminas/laminas-stdlib/LICENSE.md b/lib/laminas/laminas-stdlib/LICENSE.md new file mode 100644 index 000000000..09f53edc1 --- /dev/null +++ b/lib/laminas/laminas-stdlib/LICENSE.md @@ -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. diff --git a/lib/laminas/laminas-stdlib/README.md b/lib/laminas/laminas-stdlib/README.md new file mode 100644 index 000000000..103bb939e --- /dev/null +++ b/lib/laminas/laminas-stdlib/README.md @@ -0,0 +1,29 @@ +# laminas-stdlib + +[![Build Status](https://travis-ci.org/laminas/laminas-stdlib.svg?branch=master)](https://travis-ci.org/laminas/laminas-stdlib) +[![Coverage Status](https://coveralls.io/repos/github/laminas/laminas-stdlib/badge.svg?branch=master)](https://coveralls.io/github/laminas/laminas-stdlib?branch=master) + +`Laminas\Stdlib` is a set of components that implements general purpose utility +class for different scopes like: + +- array utilities functions; +- general messaging systems; +- string wrappers; +- etc. + +--- + +- File issues at https://github.com/laminas/laminas-stdlib/issues +- Documentation is at https://docs.laminas.dev/laminas-stdlib/ + +## Benchmarks + +We provide scripts for benchmarking laminas-stdlib using the +[PHPBench](https://github.com/phpbench/phpbench) framework; these can be +found in the `benchmark/` directory. + +To execute the benchmarks you can run the following command: + +```bash +$ vendor/bin/phpbench run --report=aggregate +``` diff --git a/lib/laminas/laminas-stdlib/composer.json b/lib/laminas/laminas-stdlib/composer.json new file mode 100644 index 000000000..b3745908e --- /dev/null +++ b/lib/laminas/laminas-stdlib/composer.json @@ -0,0 +1,60 @@ +{ + "name": "laminas/laminas-stdlib", + "description": "SPL extensions, array utilities, error handlers, and more", + "license": "BSD-3-Clause", + "keywords": [ + "laminas", + "stdlib" + ], + "homepage": "https://laminas.dev", + "support": { + "docs": "https://docs.laminas.dev/laminas-stdlib/", + "issues": "https://github.com/laminas/laminas-stdlib/issues", + "source": "https://github.com/laminas/laminas-stdlib", + "rss": "https://github.com/laminas/laminas-stdlib/releases.atom", + "chat": "https://laminas.dev/chat", + "forum": "https://discourse.laminas.dev" + }, + "config": { + "sort-packages": true + }, + "extra": { + "branch-alias": { + "dev-master": "3.2.x-dev", + "dev-develop": "3.3.x-dev" + } + }, + "require": { + "php": "^5.6 || ^7.0", + "laminas/laminas-zendframework-bridge": "^1.0" + }, + "require-dev": { + "laminas/laminas-coding-standard": "~1.0.0", + "phpbench/phpbench": "^0.13", + "phpunit/phpunit": "^5.7.27 || ^6.5.8 || ^7.1.2" + }, + "autoload": { + "psr-4": { + "Laminas\\Stdlib\\": "src/" + } + }, + "autoload-dev": { + "psr-4": { + "LaminasTest\\Stdlib\\": "test/", + "LaminasBench\\Stdlib\\": "benchmark/" + } + }, + "scripts": { + "check": [ + "@cs-check", + "@test" + ], + "cs-check": "phpcs", + "cs-fix": "phpcbf", + "test": "phpunit --colors=always", + "test-coverage": "phpunit --colors=always --coverage-clover clover.xml" + }, + "replace": { + "zendframework/zend-stdlib": "self.version" + } +} diff --git a/lib/laminas/laminas-stdlib/src/AbstractOptions.php b/lib/laminas/laminas-stdlib/src/AbstractOptions.php new file mode 100644 index 000000000..c2b113e84 --- /dev/null +++ b/lib/laminas/laminas-stdlib/src/AbstractOptions.php @@ -0,0 +1,177 @@ +setFromArray($options); + } + } + + /** + * Set one or more configuration properties + * + * @param array|Traversable|AbstractOptions $options + * @throws Exception\InvalidArgumentException + * @return AbstractOptions Provides fluent interface + */ + public function setFromArray($options) + { + if ($options instanceof self) { + $options = $options->toArray(); + } + + if (! is_array($options) && ! $options instanceof Traversable) { + throw new Exception\InvalidArgumentException( + sprintf( + 'Parameter provided to %s must be an %s, %s or %s', + __METHOD__, + 'array', + 'Traversable', + 'Laminas\Stdlib\AbstractOptions' + ) + ); + } + + foreach ($options as $key => $value) { + $this->__set($key, $value); + } + + return $this; + } + + /** + * Cast to array + * + * @return array + */ + public function toArray() + { + $array = []; + $transform = function ($letters) { + $letter = array_shift($letters); + return '_' . strtolower($letter); + }; + foreach ($this as $key => $value) { + if ($key === '__strictMode__') { + continue; + } + $normalizedKey = preg_replace_callback('/([A-Z])/', $transform, $key); + $array[$normalizedKey] = $value; + } + return $array; + } + + /** + * Set a configuration property + * + * @see ParameterObject::__set() + * @param string $key + * @param mixed $value + * @throws Exception\BadMethodCallException + * @return void + */ + public function __set($key, $value) + { + $setter = 'set' . str_replace('_', '', $key); + + if (is_callable([$this, $setter])) { + $this->{$setter}($value); + + return; + } + + if ($this->__strictMode__) { + throw new Exception\BadMethodCallException(sprintf( + 'The option "%s" does not have a callable "%s" ("%s") setter method which must be defined', + $key, + 'set' . str_replace(' ', '', ucwords(str_replace('_', ' ', $key))), + $setter + )); + } + } + + /** + * Get a configuration property + * + * @see ParameterObject::__get() + * @param string $key + * @throws Exception\BadMethodCallException + * @return mixed + */ + public function __get($key) + { + $getter = 'get' . str_replace('_', '', $key); + + if (is_callable([$this, $getter])) { + return $this->{$getter}(); + } + + throw new Exception\BadMethodCallException(sprintf( + 'The option "%s" does not have a callable "%s" getter method which must be defined', + $key, + 'get' . str_replace(' ', '', ucwords(str_replace('_', ' ', $key))) + )); + } + + /** + * Test if a configuration property is null + * @see ParameterObject::__isset() + * @param string $key + * @return bool + */ + public function __isset($key) + { + $getter = 'get' . str_replace('_', '', $key); + + return method_exists($this, $getter) && null !== $this->__get($key); + } + + /** + * Set a configuration property to NULL + * + * @see ParameterObject::__unset() + * @param string $key + * @throws Exception\InvalidArgumentException + * @return void + */ + public function __unset($key) + { + try { + $this->__set($key, null); + } catch (Exception\BadMethodCallException $e) { + throw new Exception\InvalidArgumentException( + 'The class property $' . $key . ' cannot be unset as' + . ' NULL is an invalid value for it', + 0, + $e + ); + } + } +} diff --git a/lib/laminas/laminas-stdlib/src/ArrayObject.php b/lib/laminas/laminas-stdlib/src/ArrayObject.php new file mode 100644 index 000000000..9bbb07411 --- /dev/null +++ b/lib/laminas/laminas-stdlib/src/ArrayObject.php @@ -0,0 +1,433 @@ +setFlags($flags); + $this->storage = $input; + $this->setIteratorClass($iteratorClass); + $this->protectedProperties = array_keys(get_object_vars($this)); + } + + /** + * Returns whether the requested key exists + * + * @param mixed $key + * @return bool + */ + public function __isset($key) + { + if ($this->flag == self::ARRAY_AS_PROPS) { + return $this->offsetExists($key); + } + if (in_array($key, $this->protectedProperties)) { + throw new Exception\InvalidArgumentException('$key is a protected property, use a different key'); + } + + return isset($this->$key); + } + + /** + * Sets the value at the specified key to value + * + * @param mixed $key + * @param mixed $value + * @return void + */ + public function __set($key, $value) + { + if ($this->flag == self::ARRAY_AS_PROPS) { + return $this->offsetSet($key, $value); + } + if (in_array($key, $this->protectedProperties)) { + throw new Exception\InvalidArgumentException('$key is a protected property, use a different key'); + } + $this->$key = $value; + } + + /** + * Unsets the value at the specified key + * + * @param mixed $key + * @return void + */ + public function __unset($key) + { + if ($this->flag == self::ARRAY_AS_PROPS) { + return $this->offsetUnset($key); + } + if (in_array($key, $this->protectedProperties)) { + throw new Exception\InvalidArgumentException('$key is a protected property, use a different key'); + } + unset($this->$key); + } + + /** + * Returns the value at the specified key by reference + * + * @param mixed $key + * @return mixed + */ + public function &__get($key) + { + $ret = null; + if ($this->flag == self::ARRAY_AS_PROPS) { + $ret =& $this->offsetGet($key); + + return $ret; + } + if (in_array($key, $this->protectedProperties)) { + throw new Exception\InvalidArgumentException('$key is a protected property, use a different key'); + } + + return $this->$key; + } + + /** + * Appends the value + * + * @param mixed $value + * @return void + */ + public function append($value) + { + $this->storage[] = $value; + } + + /** + * Sort the entries by value + * + * @return void + */ + public function asort() + { + asort($this->storage); + } + + /** + * Get the number of public properties in the ArrayObject + * + * @return int + */ + public function count() + { + return count($this->storage); + } + + /** + * Exchange the array for another one. + * + * @param array|ArrayObject $data + * @return array + */ + public function exchangeArray($data) + { + if (! is_array($data) && ! is_object($data)) { + throw new Exception\InvalidArgumentException( + 'Passed variable is not an array or object, using empty array instead' + ); + } + + if (is_object($data) && ($data instanceof self || $data instanceof \ArrayObject)) { + $data = $data->getArrayCopy(); + } + if (! is_array($data)) { + $data = (array) $data; + } + + $storage = $this->storage; + + $this->storage = $data; + + return $storage; + } + + /** + * Creates a copy of the ArrayObject. + * + * @return array + */ + public function getArrayCopy() + { + return $this->storage; + } + + /** + * Gets the behavior flags. + * + * @return int + */ + public function getFlags() + { + return $this->flag; + } + + /** + * Create a new iterator from an ArrayObject instance + * + * @return \Iterator + */ + public function getIterator() + { + $class = $this->iteratorClass; + + return new $class($this->storage); + } + + /** + * Gets the iterator classname for the ArrayObject. + * + * @return string + */ + public function getIteratorClass() + { + return $this->iteratorClass; + } + + /** + * Sort the entries by key + * + * @return void + */ + public function ksort() + { + ksort($this->storage); + } + + /** + * Sort an array using a case insensitive "natural order" algorithm + * + * @return void + */ + public function natcasesort() + { + natcasesort($this->storage); + } + + /** + * Sort entries using a "natural order" algorithm + * + * @return void + */ + public function natsort() + { + natsort($this->storage); + } + + /** + * Returns whether the requested key exists + * + * @param mixed $key + * @return bool + */ + public function offsetExists($key) + { + return isset($this->storage[$key]); + } + + /** + * Returns the value at the specified key + * + * @param mixed $key + * @return mixed + */ + public function &offsetGet($key) + { + $ret = null; + if (! $this->offsetExists($key)) { + return $ret; + } + $ret =& $this->storage[$key]; + + return $ret; + } + + /** + * Sets the value at the specified key to value + * + * @param mixed $key + * @param mixed $value + * @return void + */ + public function offsetSet($key, $value) + { + $this->storage[$key] = $value; + } + + /** + * Unsets the value at the specified key + * + * @param mixed $key + * @return void + */ + public function offsetUnset($key) + { + if ($this->offsetExists($key)) { + unset($this->storage[$key]); + } + } + + /** + * Serialize an ArrayObject + * + * @return string + */ + public function serialize() + { + return serialize(get_object_vars($this)); + } + + /** + * Sets the behavior flags + * + * @param int $flags + * @return void + */ + public function setFlags($flags) + { + $this->flag = $flags; + } + + /** + * Sets the iterator classname for the ArrayObject + * + * @param string $class + * @return void + */ + public function setIteratorClass($class) + { + if (class_exists($class)) { + $this->iteratorClass = $class; + + return ; + } + + if (strpos($class, '\\') === 0) { + $class = '\\' . $class; + if (class_exists($class)) { + $this->iteratorClass = $class; + + return ; + } + } + + throw new Exception\InvalidArgumentException('The iterator class does not exist'); + } + + /** + * Sort the entries with a user-defined comparison function and maintain key association + * + * @param callable $function + * @return void + */ + public function uasort($function) + { + if (is_callable($function)) { + uasort($this->storage, $function); + } + } + + /** + * Sort the entries by keys using a user-defined comparison function + * + * @param callable $function + * @return void + */ + public function uksort($function) + { + if (is_callable($function)) { + uksort($this->storage, $function); + } + } + + /** + * Unserialize an ArrayObject + * + * @param string $data + * @return void + */ + public function unserialize($data) + { + $ar = unserialize($data); + $this->protectedProperties = array_keys(get_object_vars($this)); + + $this->setFlags($ar['flag']); + $this->exchangeArray($ar['storage']); + $this->setIteratorClass($ar['iteratorClass']); + + foreach ($ar as $k => $v) { + switch ($k) { + case 'flag': + $this->setFlags($v); + break; + case 'storage': + $this->exchangeArray($v); + break; + case 'iteratorClass': + $this->setIteratorClass($v); + break; + case 'protectedProperties': + break; + default: + $this->__set($k, $v); + } + } + } +} diff --git a/lib/laminas/laminas-stdlib/src/ArraySerializableInterface.php b/lib/laminas/laminas-stdlib/src/ArraySerializableInterface.php new file mode 100644 index 000000000..d0d95eef1 --- /dev/null +++ b/lib/laminas/laminas-stdlib/src/ArraySerializableInterface.php @@ -0,0 +1,27 @@ +getArrayCopy(); + return new ArrayIterator(array_reverse($array)); + } +} diff --git a/lib/laminas/laminas-stdlib/src/ArrayUtils.php b/lib/laminas/laminas-stdlib/src/ArrayUtils.php new file mode 100644 index 000000000..13eb25d0d --- /dev/null +++ b/lib/laminas/laminas-stdlib/src/ArrayUtils.php @@ -0,0 +1,313 @@ + 0; + } + + /** + * Test whether an array contains one or more integer keys + * + * @param mixed $value + * @param bool $allowEmpty Should an empty array() return true + * @return bool + */ + public static function hasIntegerKeys($value, $allowEmpty = false) + { + if (! is_array($value)) { + return false; + } + + if (! $value) { + return $allowEmpty; + } + + return count(array_filter(array_keys($value), 'is_int')) > 0; + } + + /** + * Test whether an array contains one or more numeric keys. + * + * A numeric key can be one of the following: + * - an integer 1, + * - a string with a number '20' + * - a string with negative number: '-1000' + * - a float: 2.2120, -78.150999 + * - a string with float: '4000.99999', '-10.10' + * + * @param mixed $value + * @param bool $allowEmpty Should an empty array() return true + * @return bool + */ + public static function hasNumericKeys($value, $allowEmpty = false) + { + if (! is_array($value)) { + return false; + } + + if (! $value) { + return $allowEmpty; + } + + return count(array_filter(array_keys($value), 'is_numeric')) > 0; + } + + /** + * Test whether an array is a list + * + * A list is a collection of values assigned to continuous integer keys + * starting at 0 and ending at count() - 1. + * + * For example: + * + * $list = array('a', 'b', 'c', 'd'); + * $list = array( + * 0 => 'foo', + * 1 => 'bar', + * 2 => array('foo' => 'baz'), + * ); + * + * + * @param mixed $value + * @param bool $allowEmpty Is an empty list a valid list? + * @return bool + */ + public static function isList($value, $allowEmpty = false) + { + if (! is_array($value)) { + return false; + } + + if (! $value) { + return $allowEmpty; + } + + return (array_values($value) === $value); + } + + /** + * Test whether an array is a hash table. + * + * An array is a hash table if: + * + * 1. Contains one or more non-integer keys, or + * 2. Integer keys are non-continuous or misaligned (not starting with 0) + * + * For example: + * + * $hash = array( + * 'foo' => 15, + * 'bar' => false, + * ); + * $hash = array( + * 1995 => 'Birth of PHP', + * 2009 => 'PHP 5.3.0', + * 2012 => 'PHP 5.4.0', + * ); + * $hash = array( + * 'formElement, + * 'options' => array( 'debug' => true ), + * ); + * + * + * @param mixed $value + * @param bool $allowEmpty Is an empty array() a valid hash table? + * @return bool + */ + public static function isHashTable($value, $allowEmpty = false) + { + if (! is_array($value)) { + return false; + } + + if (! $value) { + return $allowEmpty; + } + + return (array_values($value) !== $value); + } + + /** + * Checks if a value exists in an array. + * + * Due to "foo" == 0 === TRUE with in_array when strict = false, an option + * has been added to prevent this. When $strict = 0/false, the most secure + * non-strict check is implemented. if $strict = -1, the default in_array + * non-strict behaviour is used. + * + * @param mixed $needle + * @param array $haystack + * @param int|bool $strict + * @return bool + */ + public static function inArray($needle, array $haystack, $strict = false) + { + if (! $strict) { + if (is_int($needle) || is_float($needle)) { + $needle = (string) $needle; + } + if (is_string($needle)) { + foreach ($haystack as &$h) { + if (is_int($h) || is_float($h)) { + $h = (string) $h; + } + } + } + } + return in_array($needle, $haystack, $strict); + } + + /** + * Convert an iterator to an array. + * + * Converts an iterator to an array. The $recursive flag, on by default, + * hints whether or not you want to do so recursively. + * + * @param array|Traversable $iterator The array or Traversable object to convert + * @param bool $recursive Recursively check all nested structures + * @throws Exception\InvalidArgumentException if $iterator is not an array or a Traversable object + * @return array + */ + public static function iteratorToArray($iterator, $recursive = true) + { + if (! is_array($iterator) && ! $iterator instanceof Traversable) { + throw new Exception\InvalidArgumentException(__METHOD__ . ' expects an array or Traversable object'); + } + + if (! $recursive) { + if (is_array($iterator)) { + return $iterator; + } + + return iterator_to_array($iterator); + } + + if (method_exists($iterator, 'toArray')) { + return $iterator->toArray(); + } + + $array = []; + foreach ($iterator as $key => $value) { + if (is_scalar($value)) { + $array[$key] = $value; + continue; + } + + if ($value instanceof Traversable) { + $array[$key] = static::iteratorToArray($value, $recursive); + continue; + } + + if (is_array($value)) { + $array[$key] = static::iteratorToArray($value, $recursive); + continue; + } + + $array[$key] = $value; + } + + return $array; + } + + /** + * Merge two arrays together. + * + * If an integer key exists in both arrays and preserveNumericKeys is false, the value + * from the second array will be appended to the first array. If both values are arrays, they + * are merged together, else the value of the second array overwrites the one of the first array. + * + * @param array $a + * @param array $b + * @param bool $preserveNumericKeys + * @return array + */ + public static function merge(array $a, array $b, $preserveNumericKeys = false) + { + foreach ($b as $key => $value) { + if ($value instanceof MergeReplaceKeyInterface) { + $a[$key] = $value->getData(); + } elseif (isset($a[$key]) || array_key_exists($key, $a)) { + if ($value instanceof MergeRemoveKey) { + unset($a[$key]); + } elseif (! $preserveNumericKeys && is_int($key)) { + $a[] = $value; + } elseif (is_array($value) && is_array($a[$key])) { + $a[$key] = static::merge($a[$key], $value, $preserveNumericKeys); + } else { + $a[$key] = $value; + } + } else { + if (! $value instanceof MergeRemoveKey) { + $a[$key] = $value; + } + } + } + + return $a; + } + + /** + * @deprecated Since 3.2.0; use the native array_filter methods + * + * @param array $data + * @param callable $callback + * @param null|int $flag + * @return array + * @throws Exception\InvalidArgumentException + */ + public static function filter(array $data, $callback, $flag = null) + { + if (! is_callable($callback)) { + throw new Exception\InvalidArgumentException(sprintf( + 'Second parameter of %s must be callable', + __METHOD__ + )); + } + + return array_filter($data, $callback, $flag); + } +} diff --git a/lib/laminas/laminas-stdlib/src/ArrayUtils/MergeRemoveKey.php b/lib/laminas/laminas-stdlib/src/ArrayUtils/MergeRemoveKey.php new file mode 100644 index 000000000..8c9d56e69 --- /dev/null +++ b/lib/laminas/laminas-stdlib/src/ArrayUtils/MergeRemoveKey.php @@ -0,0 +1,13 @@ +data = $data; + } + + /** + * {@inheritDoc} + */ + public function getData() + { + return $this->data; + } +} diff --git a/lib/laminas/laminas-stdlib/src/ArrayUtils/MergeReplaceKeyInterface.php b/lib/laminas/laminas-stdlib/src/ArrayUtils/MergeReplaceKeyInterface.php new file mode 100644 index 000000000..54c244382 --- /dev/null +++ b/lib/laminas/laminas-stdlib/src/ArrayUtils/MergeReplaceKeyInterface.php @@ -0,0 +1,20 @@ +message`, + * `message`) + * - Write output to a specified stream, optionally with colorization. + * - Write a line of output to a specified stream, optionally with + * colorization, using the system EOL sequence.. + * - Write an error message to STDERR. + * + * Colorization will only occur when expected sequences are discovered, and + * then, only if the console terminal allows it. + * + * Essentially, provides the bare minimum to allow you to provide messages to + * the current console. + */ +class ConsoleHelper +{ + const COLOR_GREEN = "\033[32m"; + const COLOR_RED = "\033[31m"; + const COLOR_RESET = "\033[0m"; + + const HIGHLIGHT_INFO = 'info'; + const HIGHLIGHT_ERROR = 'error'; + + private $highlightMap = [ + self::HIGHLIGHT_INFO => self::COLOR_GREEN, + self::HIGHLIGHT_ERROR => self::COLOR_RED, + ]; + + /** + * @var string Exists only for testing. + */ + private $eol = PHP_EOL; + + /** + * @var resource Exists only for testing. + */ + private $stderr = STDERR; + + /** + * @var bool + */ + private $supportsColor; + + /** + * @param resource $resource + */ + public function __construct($resource = STDOUT) + { + $this->supportsColor = $this->detectColorCapabilities($resource); + } + + /** + * Colorize a string for use with the terminal. + * + * Takes strings formatted as `string` and formats them per the + * $highlightMap; if color support is disabled, simply removes the formatting + * tags. + * + * @param string $string + * @return string + */ + public function colorize($string) + { + $reset = $this->supportsColor ? self::COLOR_RESET : ''; + foreach ($this->highlightMap as $key => $color) { + $pattern = sprintf('#<%s>(.*?)#s', $key, $key); + $color = $this->supportsColor ? $color : ''; + $string = preg_replace($pattern, $color . '$1' . $reset, $string); + } + return $string; + } + + /** + * @param string $string + * @param bool $colorize Whether or not to colorize the string + * @param resource $resource Defaults to STDOUT + * @return void + */ + public function write($string, $colorize = true, $resource = STDOUT) + { + if ($colorize) { + $string = $this->colorize($string); + } + + $string = $this->formatNewlines($string); + + fwrite($resource, $string); + } + + /** + * @param string $string + * @param bool $colorize Whether or not to colorize the line + * @param resource $resource Defaults to STDOUT + * @return void + */ + public function writeLine($string, $colorize = true, $resource = STDOUT) + { + $this->write($string . $this->eol, $colorize, $resource); + } + + /** + * Emit an error message. + * + * Wraps the message in ``, and passes it to `writeLine()`, + * using STDERR as the resource; emits an additional empty line when done, + * also to STDERR. + * + * @param string $message + * @return void + */ + public function writeErrorMessage($message) + { + $this->writeLine(sprintf('%s', $message), true, $this->stderr); + $this->writeLine('', false, $this->stderr); + } + + /** + * @param resource $resource + * @return bool + */ + private function detectColorCapabilities($resource = STDOUT) + { + if ('\\' === DIRECTORY_SEPARATOR) { + // Windows + return false !== getenv('ANSICON') + || 'ON' === getenv('ConEmuANSI') + || 'xterm' === getenv('TERM'); + } + + return function_exists('posix_isatty') && posix_isatty($resource); + } + + /** + * Ensure newlines are appropriate for the current terminal. + * + * @param string + * @return string + */ + private function formatNewlines($string) + { + $string = str_replace($this->eol, "\0PHP_EOL\0", $string); + $string = preg_replace("/(\r\n|\n|\r)/", $this->eol, $string); + return str_replace("\0PHP_EOL\0", $this->eol, $string); + } +} diff --git a/lib/laminas/laminas-stdlib/src/DispatchableInterface.php b/lib/laminas/laminas-stdlib/src/DispatchableInterface.php new file mode 100644 index 000000000..62b813af2 --- /dev/null +++ b/lib/laminas/laminas-stdlib/src/DispatchableInterface.php @@ -0,0 +1,21 @@ +values[$priority][] = $value; + if (! isset($this->priorities[$priority])) { + $this->priorities[$priority] = $priority; + $this->maxPriority = $this->maxPriority === null ? $priority : max($priority, $this->maxPriority); + } + ++$this->count; + } + + /** + * Extract an element in the queue according to the priority and the + * order of insertion + * + * @return mixed + */ + public function extract() + { + if (! $this->valid()) { + return false; + } + $value = $this->current(); + $this->nextAndRemove(); + return $value; + } + + /** + * Remove an item from the queue + * + * This is different than {@link extract()}; its purpose is to dequeue an + * item. + * + * Note: this removes the first item matching the provided item found. If + * the same item has been added multiple times, it will not remove other + * instances. + * + * @param mixed $datum + * @return bool False if the item was not found, true otherwise. + */ + public function remove($datum) + { + $currentIndex = $this->index; + $currentSubIndex = $this->subIndex; + $currentPriority = $this->maxPriority; + + $this->rewind(); + while ($this->valid()) { + if (current($this->values[$this->maxPriority]) === $datum) { + $index = key($this->values[$this->maxPriority]); + unset($this->values[$this->maxPriority][$index]); + + // The `next()` method advances the internal array pointer, so we need to use the `reset()` function, + // otherwise we would lose all elements before the place the pointer points. + reset($this->values[$this->maxPriority]); + + $this->index = $currentIndex; + $this->subIndex = $currentSubIndex; + + // If the array is empty we need to destroy the unnecessary priority, + // otherwise we would end up with an incorrect value of `$this->count` + // {@see \Laminas\Stdlib\FastPriorityQueue::nextAndRemove()}. + if (empty($this->values[$this->maxPriority])) { + unset($this->values[$this->maxPriority]); + unset($this->priorities[$this->maxPriority]); + if ($this->maxPriority === $currentPriority) { + $this->subIndex = 0; + } + } + + $this->maxPriority = empty($this->priorities) ? null : max($this->priorities); + --$this->count; + return true; + } + $this->next(); + } + return false; + } + + /** + * Get the total number of elements in the queue + * + * @return integer + */ + public function count() + { + return $this->count; + } + + /** + * Get the current element in the queue + * + * @return mixed + */ + public function current() + { + switch ($this->extractFlag) { + case self::EXTR_DATA: + return current($this->values[$this->maxPriority]); + case self::EXTR_PRIORITY: + return $this->maxPriority; + case self::EXTR_BOTH: + return [ + 'data' => current($this->values[$this->maxPriority]), + 'priority' => $this->maxPriority + ]; + } + } + + /** + * Get the index of the current element in the queue + * + * @return integer + */ + public function key() + { + return $this->index; + } + + /** + * Set the iterator pointer to the next element in the queue + * removing the previous element + */ + protected function nextAndRemove() + { + $key = key($this->values[$this->maxPriority]); + + if (false === next($this->values[$this->maxPriority])) { + unset($this->priorities[$this->maxPriority]); + unset($this->values[$this->maxPriority]); + $this->maxPriority = empty($this->priorities) ? null : max($this->priorities); + $this->subIndex = -1; + } else { + unset($this->values[$this->maxPriority][$key]); + } + ++$this->index; + ++$this->subIndex; + --$this->count; + } + + /** + * Set the iterator pointer to the next element in the queue + * without removing the previous element + */ + public function next() + { + if (false === next($this->values[$this->maxPriority])) { + unset($this->subPriorities[$this->maxPriority]); + reset($this->values[$this->maxPriority]); + $this->maxPriority = empty($this->subPriorities) ? null : max($this->subPriorities); + $this->subIndex = -1; + } + ++$this->index; + ++$this->subIndex; + } + + /** + * Check if the current iterator is valid + * + * @return boolean + */ + public function valid() + { + return isset($this->values[$this->maxPriority]); + } + + /** + * Rewind the current iterator + */ + public function rewind() + { + $this->subPriorities = $this->priorities; + $this->maxPriority = empty($this->priorities) ? 0 : max($this->priorities); + $this->index = 0; + $this->subIndex = 0; + } + + /** + * Serialize to an array + * + * Array will be priority => data pairs + * + * @return array + */ + public function toArray() + { + $array = []; + foreach (clone $this as $item) { + $array[] = $item; + } + return $array; + } + + /** + * Serialize + * + * @return string + */ + public function serialize() + { + $clone = clone $this; + $clone->setExtractFlags(self::EXTR_BOTH); + + $data = []; + foreach ($clone as $item) { + $data[] = $item; + } + + return serialize($data); + } + + /** + * Deserialize + * + * @param string $data + * @return void + */ + public function unserialize($data) + { + foreach (unserialize($data) as $item) { + $this->insert($item['data'], $item['priority']); + } + } + + /** + * Set the extract flag + * + * @param integer $flag + */ + public function setExtractFlags($flag) + { + switch ($flag) { + case self::EXTR_DATA: + case self::EXTR_PRIORITY: + case self::EXTR_BOTH: + $this->extractFlag = $flag; + break; + default: + throw new Exception\InvalidArgumentException("The extract flag specified is not valid"); + } + } + + /** + * Check if the queue is empty + * + * @return boolean + */ + public function isEmpty() + { + return empty($this->values); + } + + /** + * Does the queue contain the given datum? + * + * @param mixed $datum + * @return bool + */ + public function contains($datum) + { + foreach ($this->values as $values) { + if (in_array($datum, $values)) { + return true; + } + } + return false; + } + + /** + * Does the queue have an item with the given priority? + * + * @param int $priority + * @return bool + */ + public function hasPriority($priority) + { + return isset($this->values[$priority]); + } +} diff --git a/lib/laminas/laminas-stdlib/src/Glob.php b/lib/laminas/laminas-stdlib/src/Glob.php new file mode 100644 index 000000000..f25d0b9d5 --- /dev/null +++ b/lib/laminas/laminas-stdlib/src/Glob.php @@ -0,0 +1,201 @@ + GLOB_MARK, + self::GLOB_NOSORT => GLOB_NOSORT, + self::GLOB_NOCHECK => GLOB_NOCHECK, + self::GLOB_NOESCAPE => GLOB_NOESCAPE, + self::GLOB_BRACE => defined('GLOB_BRACE') ? GLOB_BRACE : 0, + self::GLOB_ONLYDIR => GLOB_ONLYDIR, + self::GLOB_ERR => GLOB_ERR, + ]; + + $globFlags = 0; + + foreach ($flagMap as $internalFlag => $globFlag) { + if ($flags & $internalFlag) { + $globFlags |= $globFlag; + } + } + } else { + $globFlags = 0; + } + + ErrorHandler::start(); + $res = glob($pattern, $globFlags); + $err = ErrorHandler::stop(); + if ($res === false) { + throw new Exception\RuntimeException("glob('{$pattern}', {$globFlags}) failed", 0, $err); + } + return $res; + } + + /** + * Expand braces manually, then use the system glob. + * + * @param string $pattern + * @param int $flags + * @return array + * @throws Exception\RuntimeException + */ + protected static function fallbackGlob($pattern, $flags) + { + if (! $flags & self::GLOB_BRACE) { + return static::systemGlob($pattern, $flags); + } + + $flags &= ~self::GLOB_BRACE; + $length = strlen($pattern); + $paths = []; + + if ($flags & self::GLOB_NOESCAPE) { + $begin = strpos($pattern, '{'); + } else { + $begin = 0; + + while (true) { + if ($begin === $length) { + $begin = false; + break; + } elseif ($pattern[$begin] === '\\' && ($begin + 1) < $length) { + $begin++; + } elseif ($pattern[$begin] === '{') { + break; + } + + $begin++; + } + } + + if ($begin === false) { + return static::systemGlob($pattern, $flags); + } + + $next = static::nextBraceSub($pattern, $begin + 1, $flags); + + if ($next === null) { + return static::systemGlob($pattern, $flags); + } + + $rest = $next; + + while ($pattern[$rest] !== '}') { + $rest = static::nextBraceSub($pattern, $rest + 1, $flags); + + if ($rest === null) { + return static::systemGlob($pattern, $flags); + } + } + + $p = $begin + 1; + + while (true) { + $subPattern = substr($pattern, 0, $begin) + . substr($pattern, $p, $next - $p) + . substr($pattern, $rest + 1); + + $result = static::fallbackGlob($subPattern, $flags | self::GLOB_BRACE); + + if ($result) { + $paths = array_merge($paths, $result); + } + + if ($pattern[$next] === '}') { + break; + } + + $p = $next + 1; + $next = static::nextBraceSub($pattern, $p, $flags); + } + + return array_unique($paths); + } + + /** + * Find the end of the sub-pattern in a brace expression. + * + * @param string $pattern + * @param int $begin + * @param int $flags + * @return int|null + */ + protected static function nextBraceSub($pattern, $begin, $flags) + { + $length = strlen($pattern); + $depth = 0; + $current = $begin; + + while ($current < $length) { + if (! $flags & self::GLOB_NOESCAPE && $pattern[$current] === '\\') { + if (++$current === $length) { + break; + } + + $current++; + } else { + if (($pattern[$current] === '}' && $depth-- === 0) || ($pattern[$current] === ',' && $depth === 0)) { + break; + } elseif ($pattern[$current++] === '{') { + $depth++; + } + } + } + + return ($current < $length ? $current : null); + } +} diff --git a/lib/laminas/laminas-stdlib/src/Guard/AllGuardsTrait.php b/lib/laminas/laminas-stdlib/src/Guard/AllGuardsTrait.php new file mode 100644 index 000000000..e701c176b --- /dev/null +++ b/lib/laminas/laminas-stdlib/src/Guard/AllGuardsTrait.php @@ -0,0 +1,19 @@ +metadata[$spec] = $value; + return $this; + } + if (! is_array($spec) && ! $spec instanceof Traversable) { + throw new Exception\InvalidArgumentException(sprintf( + 'Expected a string, array, or Traversable argument in first position; received "%s"', + (is_object($spec) ? get_class($spec) : gettype($spec)) + )); + } + foreach ($spec as $key => $value) { + $this->metadata[$key] = $value; + } + return $this; + } + + /** + * Retrieve all metadata or a single metadatum as specified by key + * + * @param null|string|int $key + * @param null|mixed $default + * @throws Exception\InvalidArgumentException + * @return mixed + */ + public function getMetadata($key = null, $default = null) + { + if (null === $key) { + return $this->metadata; + } + + if (! is_scalar($key)) { + throw new Exception\InvalidArgumentException('Non-scalar argument provided for key'); + } + + if (array_key_exists($key, $this->metadata)) { + return $this->metadata[$key]; + } + + return $default; + } + + /** + * Set message content + * + * @param mixed $value + * @return Message + */ + public function setContent($value) + { + $this->content = $value; + return $this; + } + + /** + * Get message content + * + * @return mixed + */ + public function getContent() + { + return $this->content; + } + + /** + * @return string + */ + public function toString() + { + $request = ''; + foreach ($this->getMetadata() as $key => $value) { + $request .= sprintf( + "%s: %s\r\n", + (string) $key, + (string) $value + ); + } + $request .= "\r\n" . $this->getContent(); + return $request; + } +} diff --git a/lib/laminas/laminas-stdlib/src/MessageInterface.php b/lib/laminas/laminas-stdlib/src/MessageInterface.php new file mode 100644 index 000000000..76f089a02 --- /dev/null +++ b/lib/laminas/laminas-stdlib/src/MessageInterface.php @@ -0,0 +1,43 @@ +exchangeArray($values); + } + + /** + * Populate from query string + * + * @param string $string + * @return void + */ + public function fromString($string) + { + $array = []; + parse_str($string, $array); + $this->fromArray($array); + } + + /** + * Serialize to native PHP array + * + * @return array + */ + public function toArray() + { + return $this->getArrayCopy(); + } + + /** + * Serialize to query string + * + * @return string + */ + public function toString() + { + return http_build_query($this->toArray()); + } + + /** + * Retrieve by key + * + * Returns null if the key does not exist. + * + * @param string $name + * @return mixed + */ + public function offsetGet($name) + { + if ($this->offsetExists($name)) { + return parent::offsetGet($name); + } + return; + } + + /** + * @param string $name + * @param mixed $default optional default value + * @return mixed + */ + public function get($name, $default = null) + { + if ($this->offsetExists($name)) { + return parent::offsetGet($name); + } + return $default; + } + + /** + * @param string $name + * @param mixed $value + * @return Parameters + */ + public function set($name, $value) + { + $this[$name] = $value; + return $this; + } +} diff --git a/lib/laminas/laminas-stdlib/src/ParametersInterface.php b/lib/laminas/laminas-stdlib/src/ParametersInterface.php new file mode 100644 index 000000000..0c62df3a5 --- /dev/null +++ b/lib/laminas/laminas-stdlib/src/ParametersInterface.php @@ -0,0 +1,85 @@ +items[$name])) { + $this->count++; + } + + $this->sorted = false; + + $this->items[$name] = [ + 'data' => $value, + 'priority' => (int) $priority, + 'serial' => $this->serial++, + ]; + } + + /** + * @param string $name + * @param int $priority + * + * @return $this + * + * @throws \Exception + */ + public function setPriority($name, $priority) + { + if (! isset($this->items[$name])) { + throw new \Exception("item $name not found"); + } + + $this->items[$name]['priority'] = (int) $priority; + $this->sorted = false; + + return $this; + } + + /** + * Remove a item. + * + * @param string $name + * @return void + */ + public function remove($name) + { + if (isset($this->items[$name])) { + $this->count--; + } + + unset($this->items[$name]); + } + + /** + * Remove all items. + * + * @return void + */ + public function clear() + { + $this->items = []; + $this->serial = 0; + $this->count = 0; + $this->sorted = false; + } + + /** + * Get a item. + * + * @param string $name + * @return mixed + */ + public function get($name) + { + if (! isset($this->items[$name])) { + return; + } + + return $this->items[$name]['data']; + } + + /** + * Sort all items. + * + * @return void + */ + protected function sort() + { + if (! $this->sorted) { + uasort($this->items, [$this, 'compare']); + $this->sorted = true; + } + } + + /** + * Compare the priority of two items. + * + * @param array $item1, + * @param array $item2 + * @return int + */ + protected function compare(array $item1, array $item2) + { + return ($item1['priority'] === $item2['priority']) + ? ($item1['serial'] > $item2['serial'] ? -1 : 1) * $this->isLIFO + : ($item1['priority'] > $item2['priority'] ? -1 : 1); + } + + /** + * Get/Set serial order mode + * + * @param bool|null $flag + * + * @return bool + */ + public function isLIFO($flag = null) + { + if ($flag !== null) { + $isLifo = $flag === true ? 1 : -1; + + if ($isLifo !== $this->isLIFO) { + $this->isLIFO = $isLifo; + $this->sorted = false; + } + } + + return 1 === $this->isLIFO; + } + + /** + * {@inheritDoc} + */ + public function rewind() + { + $this->sort(); + reset($this->items); + } + + /** + * {@inheritDoc} + */ + public function current() + { + $this->sorted || $this->sort(); + $node = current($this->items); + + return $node ? $node['data'] : false; + } + + /** + * {@inheritDoc} + */ + public function key() + { + $this->sorted || $this->sort(); + return key($this->items); + } + + /** + * {@inheritDoc} + */ + public function next() + { + $node = next($this->items); + + return $node ? $node['data'] : false; + } + + /** + * {@inheritDoc} + */ + public function valid() + { + return current($this->items) !== false; + } + + /** + * @return self + */ + public function getIterator() + { + return clone $this; + } + + /** + * {@inheritDoc} + */ + public function count() + { + return $this->count; + } + + /** + * Return list as array + * + * @param int $flag + * + * @return array + */ + public function toArray($flag = self::EXTR_DATA) + { + $this->sort(); + + if ($flag == self::EXTR_BOTH) { + return $this->items; + } + + return array_map( + function ($item) use ($flag) { + return ($flag == PriorityList::EXTR_PRIORITY) ? $item['priority'] : $item['data']; + }, + $this->items + ); + } +} diff --git a/lib/laminas/laminas-stdlib/src/PriorityQueue.php b/lib/laminas/laminas-stdlib/src/PriorityQueue.php new file mode 100644 index 000000000..ab4b1b65a --- /dev/null +++ b/lib/laminas/laminas-stdlib/src/PriorityQueue.php @@ -0,0 +1,300 @@ +items[] = [ + 'data' => $data, + 'priority' => $priority, + ]; + $this->getQueue()->insert($data, $priority); + return $this; + } + + /** + * Remove an item from the queue + * + * This is different than {@link extract()}; its purpose is to dequeue an + * item. + * + * This operation is potentially expensive, as it requires + * re-initialization and re-population of the inner queue. + * + * Note: this removes the first item matching the provided item found. If + * the same item has been added multiple times, it will not remove other + * instances. + * + * @param mixed $datum + * @return bool False if the item was not found, true otherwise. + */ + public function remove($datum) + { + $found = false; + foreach ($this->items as $key => $item) { + if ($item['data'] === $datum) { + $found = true; + break; + } + } + if ($found) { + unset($this->items[$key]); + $this->queue = null; + + if (! $this->isEmpty()) { + $queue = $this->getQueue(); + foreach ($this->items as $item) { + $queue->insert($item['data'], $item['priority']); + } + } + return true; + } + return false; + } + + /** + * Is the queue empty? + * + * @return bool + */ + public function isEmpty() + { + return (0 === $this->count()); + } + + /** + * How many items are in the queue? + * + * @return int + */ + public function count() + { + return count($this->items); + } + + /** + * Peek at the top node in the queue, based on priority. + * + * @return mixed + */ + public function top() + { + return $this->getIterator()->top(); + } + + /** + * Extract a node from the inner queue and sift up + * + * @return mixed + */ + public function extract() + { + return $this->getQueue()->extract(); + } + + /** + * Retrieve the inner iterator + * + * SplPriorityQueue acts as a heap, which typically implies that as items + * are iterated, they are also removed. This does not work for situations + * where the queue may be iterated multiple times. As such, this class + * aggregates the values, and also injects an SplPriorityQueue. This method + * retrieves the inner queue object, and clones it for purposes of + * iteration. + * + * @return SplPriorityQueue + */ + public function getIterator() + { + $queue = $this->getQueue(); + return clone $queue; + } + + /** + * Serialize the data structure + * + * @return string + */ + public function serialize() + { + return serialize($this->items); + } + + /** + * Unserialize a string into a PriorityQueue object + * + * Serialization format is compatible with {@link Laminas\Stdlib\SplPriorityQueue} + * + * @param string $data + * @return void + */ + public function unserialize($data) + { + foreach (unserialize($data) as $item) { + $this->insert($item['data'], $item['priority']); + } + } + + /** + * Serialize to an array + * + * By default, returns only the item data, and in the order registered (not + * sorted). You may provide one of the EXTR_* flags as an argument, allowing + * the ability to return priorities or both data and priority. + * + * @param int $flag + * @return array + */ + public function toArray($flag = self::EXTR_DATA) + { + switch ($flag) { + case self::EXTR_BOTH: + return $this->items; + case self::EXTR_PRIORITY: + return array_map(function ($item) { + return $item['priority']; + }, $this->items); + case self::EXTR_DATA: + default: + return array_map(function ($item) { + return $item['data']; + }, $this->items); + } + } + + /** + * Specify the internal queue class + * + * Please see {@link getIterator()} for details on the necessity of an + * internal queue class. The class provided should extend SplPriorityQueue. + * + * @param string $class + * @return PriorityQueue + */ + public function setInternalQueueClass($class) + { + $this->queueClass = (string) $class; + return $this; + } + + /** + * Does the queue contain the given datum? + * + * @param mixed $datum + * @return bool + */ + public function contains($datum) + { + foreach ($this->items as $item) { + if ($item['data'] === $datum) { + return true; + } + } + return false; + } + + /** + * Does the queue have an item with the given priority? + * + * @param int $priority + * @return bool + */ + public function hasPriority($priority) + { + foreach ($this->items as $item) { + if ($item['priority'] === $priority) { + return true; + } + } + return false; + } + + /** + * Get the inner priority queue instance + * + * @throws Exception\DomainException + * @return SplPriorityQueue + */ + protected function getQueue() + { + if (null === $this->queue) { + $this->queue = new $this->queueClass(); + if (! $this->queue instanceof \SplPriorityQueue) { + throw new Exception\DomainException(sprintf( + 'PriorityQueue expects an internal queue of type SplPriorityQueue; received "%s"', + get_class($this->queue) + )); + } + } + return $this->queue; + } + + /** + * Add support for deep cloning + * + * @return void + */ + public function __clone() + { + if (null !== $this->queue) { + $this->queue = clone $this->queue; + } + } +} diff --git a/lib/laminas/laminas-stdlib/src/Request.php b/lib/laminas/laminas-stdlib/src/Request.php new file mode 100644 index 000000000..a593a480f --- /dev/null +++ b/lib/laminas/laminas-stdlib/src/Request.php @@ -0,0 +1,14 @@ +serial--]; + } + parent::insert($datum, $priority); + } + + /** + * Serialize to an array + * + * Array will be priority => data pairs + * + * @return array + */ + public function toArray() + { + $array = []; + foreach (clone $this as $item) { + $array[] = $item; + } + return $array; + } + + /** + * Serialize + * + * @return string + */ + public function serialize() + { + $clone = clone $this; + $clone->setExtractFlags(self::EXTR_BOTH); + + $data = []; + foreach ($clone as $item) { + $data[] = $item; + } + + return serialize($data); + } + + /** + * Deserialize + * + * @param string $data + * @return void + */ + public function unserialize($data) + { + $this->serial = PHP_INT_MAX; + foreach (unserialize($data) as $item) { + $this->serial--; + $this->insert($item['data'], $item['priority']); + } + } +} diff --git a/lib/laminas/laminas-stdlib/src/SplQueue.php b/lib/laminas/laminas-stdlib/src/SplQueue.php new file mode 100644 index 000000000..9eb2abb7f --- /dev/null +++ b/lib/laminas/laminas-stdlib/src/SplQueue.php @@ -0,0 +1,54 @@ +toArray()); + } + + /** + * Unserialize + * + * @param string $data + * @return void + */ + public function unserialize($data) + { + foreach (unserialize($data) as $item) { + $this->push($item); + } + } +} diff --git a/lib/laminas/laminas-stdlib/src/SplStack.php b/lib/laminas/laminas-stdlib/src/SplStack.php new file mode 100644 index 000000000..404203dd4 --- /dev/null +++ b/lib/laminas/laminas-stdlib/src/SplStack.php @@ -0,0 +1,54 @@ +toArray()); + } + + /** + * Unserialize + * + * @param string $data + * @return void + */ + public function unserialize($data) + { + foreach (unserialize($data) as $item) { + $this->unshift($item); + } + } +} diff --git a/lib/laminas/laminas-stdlib/src/StringUtils.php b/lib/laminas/laminas-stdlib/src/StringUtils.php new file mode 100644 index 000000000..a52218c31 --- /dev/null +++ b/lib/laminas/laminas-stdlib/src/StringUtils.php @@ -0,0 +1,186 @@ +setEncoding($encoding, $convertEncoding); + return $wrapper; + } + } + + throw new Exception\RuntimeException( + 'No wrapper found supporting "' . $encoding . '"' + . (($convertEncoding !== null) ? ' and "' . $convertEncoding . '"' : '') + ); + } + + /** + * Get a list of all known single-byte character encodings + * + * @return string[] + */ + public static function getSingleByteEncodings() + { + return static::$singleByteEncodings; + } + + /** + * Check if a given encoding is a known single-byte character encoding + * + * @param string $encoding + * @return bool + */ + public static function isSingleByteEncoding($encoding) + { + return in_array(strtoupper($encoding), static::$singleByteEncodings); + } + + /** + * Check if a given string is valid UTF-8 encoded + * + * @param string $str + * @return bool + */ + public static function isValidUtf8($str) + { + return is_string($str) && ($str === '' || preg_match('/^./su', $str) == 1); + } + + /** + * Is PCRE compiled with Unicode support? + * + * @return bool + */ + public static function hasPcreUnicodeSupport() + { + if (static::$hasPcreUnicodeSupport === null) { + ErrorHandler::start(); + static::$hasPcreUnicodeSupport = defined('PREG_BAD_UTF8_OFFSET_ERROR') && preg_match('/\pL/u', 'a') == 1; + ErrorHandler::stop(); + } + return static::$hasPcreUnicodeSupport; + } +} diff --git a/lib/laminas/laminas-stdlib/src/StringWrapper/AbstractStringWrapper.php b/lib/laminas/laminas-stdlib/src/StringWrapper/AbstractStringWrapper.php new file mode 100644 index 000000000..a3125f065 --- /dev/null +++ b/lib/laminas/laminas-stdlib/src/StringWrapper/AbstractStringWrapper.php @@ -0,0 +1,268 @@ +convertEncoding = $convertEncodingUpper; + } else { + $this->convertEncoding = null; + } + $this->encoding = $encodingUpper; + + return $this; + } + + /** + * Get the defined character encoding to work with + * + * @return string + * @throws Exception\LogicException If no encoding was defined + */ + public function getEncoding() + { + return $this->encoding; + } + + /** + * Get the defined character encoding to convert to + * + * @return string|null + */ + public function getConvertEncoding() + { + return $this->convertEncoding; + } + + /** + * Convert a string from defined character encoding to the defined convert encoding + * + * @param string $str + * @param bool $reverse + * @return string|false + */ + public function convert($str, $reverse = false) + { + $encoding = $this->getEncoding(); + $convertEncoding = $this->getConvertEncoding(); + if ($convertEncoding === null) { + throw new Exception\LogicException( + 'No convert encoding defined' + ); + } + + if ($encoding === $convertEncoding) { + return $str; + } + + $from = $reverse ? $convertEncoding : $encoding; + $to = $reverse ? $encoding : $convertEncoding; + throw new Exception\RuntimeException(sprintf( + 'Converting from "%s" to "%s" isn\'t supported by this string wrapper', + $from, + $to + )); + } + + /** + * Wraps a string to a given number of characters + * + * @param string $string + * @param int $width + * @param string $break + * @param bool $cut + * @return string|false + */ + public function wordWrap($string, $width = 75, $break = "\n", $cut = false) + { + $string = (string) $string; + if ($string === '') { + return ''; + } + + $break = (string) $break; + if ($break === '') { + throw new Exception\InvalidArgumentException('Break string cannot be empty'); + } + + $width = (int) $width; + if ($width === 0 && $cut) { + throw new Exception\InvalidArgumentException('Cannot force cut when width is zero'); + } + + if (StringUtils::isSingleByteEncoding($this->getEncoding())) { + return wordwrap($string, $width, $break, $cut); + } + + $stringWidth = $this->strlen($string); + $breakWidth = $this->strlen($break); + + $result = ''; + $lastStart = $lastSpace = 0; + + for ($current = 0; $current < $stringWidth; $current++) { + $char = $this->substr($string, $current, 1); + + $possibleBreak = $char; + if ($breakWidth !== 1) { + $possibleBreak = $this->substr($string, $current, $breakWidth); + } + + if ($possibleBreak === $break) { + $result .= $this->substr($string, $lastStart, $current - $lastStart + $breakWidth); + $current += $breakWidth - 1; + $lastStart = $lastSpace = $current + 1; + continue; + } + + if ($char === ' ') { + if ($current - $lastStart >= $width) { + $result .= $this->substr($string, $lastStart, $current - $lastStart) . $break; + $lastStart = $current + 1; + } + + $lastSpace = $current; + continue; + } + + if ($current - $lastStart >= $width && $cut && $lastStart >= $lastSpace) { + $result .= $this->substr($string, $lastStart, $current - $lastStart) . $break; + $lastStart = $lastSpace = $current; + continue; + } + + if ($current - $lastStart >= $width && $lastStart < $lastSpace) { + $result .= $this->substr($string, $lastStart, $lastSpace - $lastStart) . $break; + $lastStart = $lastSpace = $lastSpace + 1; + continue; + } + } + + if ($lastStart !== $current) { + $result .= $this->substr($string, $lastStart, $current - $lastStart); + } + + return $result; + } + + /** + * Pad a string to a certain length with another string + * + * @param string $input + * @param int $padLength + * @param string $padString + * @param int $padType + * @return string + */ + public function strPad($input, $padLength, $padString = ' ', $padType = STR_PAD_RIGHT) + { + if (StringUtils::isSingleByteEncoding($this->getEncoding())) { + return str_pad($input, $padLength, $padString, $padType); + } + + $lengthOfPadding = $padLength - $this->strlen($input); + if ($lengthOfPadding <= 0) { + return $input; + } + + $padStringLength = $this->strlen($padString); + if ($padStringLength === 0) { + return $input; + } + + $repeatCount = floor($lengthOfPadding / $padStringLength); + + if ($padType === STR_PAD_BOTH) { + $repeatCountLeft = $repeatCountRight = ($repeatCount - $repeatCount % 2) / 2; + + $lastStringLength = $lengthOfPadding - 2 * $repeatCountLeft * $padStringLength; + $lastStringLeftLength = $lastStringRightLength = floor($lastStringLength / 2); + $lastStringRightLength += $lastStringLength % 2; + + $lastStringLeft = $this->substr($padString, 0, $lastStringLeftLength); + $lastStringRight = $this->substr($padString, 0, $lastStringRightLength); + + return str_repeat($padString, $repeatCountLeft) . $lastStringLeft + . $input + . str_repeat($padString, $repeatCountRight) . $lastStringRight; + } + + $lastString = $this->substr($padString, 0, $lengthOfPadding % $padStringLength); + + if ($padType === STR_PAD_LEFT) { + return str_repeat($padString, $repeatCount) . $lastString . $input; + } + + return $input . str_repeat($padString, $repeatCount) . $lastString; + } +} diff --git a/lib/laminas/laminas-stdlib/src/StringWrapper/Iconv.php b/lib/laminas/laminas-stdlib/src/StringWrapper/Iconv.php new file mode 100644 index 000000000..126b04854 --- /dev/null +++ b/lib/laminas/laminas-stdlib/src/StringWrapper/Iconv.php @@ -0,0 +1,288 @@ +getEncoding()); + } + + /** + * Returns the portion of string specified by the start and length parameters + * + * @param string $str + * @param int $offset + * @param int|null $length + * @return string|false + */ + public function substr($str, $offset = 0, $length = null) + { + return iconv_substr($str, $offset, $length, $this->getEncoding()); + } + + /** + * Find the position of the first occurrence of a substring in a string + * + * @param string $haystack + * @param string $needle + * @param int $offset + * @return int|false + */ + public function strpos($haystack, $needle, $offset = 0) + { + return iconv_strpos($haystack, $needle, $offset, $this->getEncoding()); + } + + /** + * Convert a string from defined encoding to the defined convert encoding + * + * @param string $str + * @param bool $reverse + * @return string|false + */ + public function convert($str, $reverse = false) + { + $encoding = $this->getEncoding(); + $convertEncoding = $this->getConvertEncoding(); + if ($convertEncoding === null) { + throw new Exception\LogicException( + 'No convert encoding defined' + ); + } + + if ($encoding === $convertEncoding) { + return $str; + } + + $fromEncoding = $reverse ? $convertEncoding : $encoding; + $toEncoding = $reverse ? $encoding : $convertEncoding; + + // automatically add "//IGNORE" to not stop converting on invalid characters + // invalid characters triggers a notice anyway + return iconv($fromEncoding, $toEncoding . '//IGNORE', $str); + } +} diff --git a/lib/laminas/laminas-stdlib/src/StringWrapper/Intl.php b/lib/laminas/laminas-stdlib/src/StringWrapper/Intl.php new file mode 100644 index 000000000..217bd4fc3 --- /dev/null +++ b/lib/laminas/laminas-stdlib/src/StringWrapper/Intl.php @@ -0,0 +1,87 @@ +getEncoding()); + } + + /** + * Returns the portion of string specified by the start and length parameters + * + * @param string $str + * @param int $offset + * @param int|null $length + * @return string|false + */ + public function substr($str, $offset = 0, $length = null) + { + return mb_substr($str, $offset, $length, $this->getEncoding()); + } + + /** + * Find the position of the first occurrence of a substring in a string + * + * @param string $haystack + * @param string $needle + * @param int $offset + * @return int|false + */ + public function strpos($haystack, $needle, $offset = 0) + { + return mb_strpos($haystack, $needle, $offset, $this->getEncoding()); + } + + /** + * Convert a string from defined encoding to the defined convert encoding + * + * @param string $str + * @param bool $reverse + * @return string|false + */ + public function convert($str, $reverse = false) + { + $encoding = $this->getEncoding(); + $convertEncoding = $this->getConvertEncoding(); + + if ($convertEncoding === null) { + throw new Exception\LogicException( + 'No convert encoding defined' + ); + } + + if ($encoding === $convertEncoding) { + return $str; + } + + $fromEncoding = $reverse ? $convertEncoding : $encoding; + $toEncoding = $reverse ? $encoding : $convertEncoding; + return mb_convert_encoding($str, $toEncoding, $fromEncoding); + } +} diff --git a/lib/laminas/laminas-stdlib/src/StringWrapper/Native.php b/lib/laminas/laminas-stdlib/src/StringWrapper/Native.php new file mode 100644 index 000000000..0c3734666 --- /dev/null +++ b/lib/laminas/laminas-stdlib/src/StringWrapper/Native.php @@ -0,0 +1,133 @@ +convertEncoding = $encodingUpper; + } + + if ($convertEncoding !== null) { + if ($encodingUpper !== strtoupper($convertEncoding)) { + throw new Exception\InvalidArgumentException( + 'Wrapper doesn\'t support to convert between character encodings' + ); + } + + $this->convertEncoding = $encodingUpper; + } else { + $this->convertEncoding = null; + } + $this->encoding = $encodingUpper; + + return $this; + } + + /** + * Returns the length of the given string + * + * @param string $str + * @return int|false + */ + public function strlen($str) + { + return strlen($str); + } + + /** + * Returns the portion of string specified by the start and length parameters + * + * @param string $str + * @param int $offset + * @param int|null $length + * @return string|false + */ + public function substr($str, $offset = 0, $length = null) + { + return substr($str, $offset, $length); + } + + /** + * Find the position of the first occurrence of a substring in a string + * + * @param string $haystack + * @param string $needle + * @param int $offset + * @return int|false + */ + public function strpos($haystack, $needle, $offset = 0) + { + return strpos($haystack, $needle, $offset); + } +} diff --git a/lib/laminas/laminas-stdlib/src/StringWrapper/StringWrapperInterface.php b/lib/laminas/laminas-stdlib/src/StringWrapper/StringWrapperInterface.php new file mode 100644 index 000000000..5c10365be --- /dev/null +++ b/lib/laminas/laminas-stdlib/src/StringWrapper/StringWrapperInterface.php @@ -0,0 +1,110 @@ +getBody(), "\n")); +$validatorVersion = getVersionFromString('IanaVersion', file_get_contents(LAMINAS_HOSTNAME_VALIDATOR_FILE)); + +if ($checkOnly && $ianaVersion > $validatorVersion) { + printf( + 'TLDs must be updated, please run `php bin/update_hostname_validator.php` and push your changes%s', + PHP_EOL + ); + exit(1); +} + +if ($checkOnly) { + printf('TLDs are up-to-date%s', PHP_EOL); + exit(0); +} + +foreach (file(LAMINAS_HOSTNAME_VALIDATOR_FILE) as $line) { + // Replace old version number with new one + if (preg_match('/\*\s+IanaVersion\s+\d+/', $line, $matches)) { + $newFileContent[] = sprintf(" * IanaVersion %s\n", $ianaVersion); + continue; + } + + if ($insertDone === $insertFinish) { + // Outside of $validTlds definition; keep line as-is + $newFileContent[] = $line; + } + + if ($insertFinish) { + continue; + } + + if ($insertDone) { + // Detect where the $validTlds declaration ends + if (preg_match('/^\s+\];\s*$/', $line)) { + $newFileContent[] = $line; + $insertFinish = true; + } + + continue; + } + + // Detect where the $validTlds declaration begins + if (preg_match('/^\s+protected\s+\$validTlds\s+=\s+\[\s*$/', $line)) { + $newFileContent = array_merge($newFileContent, getNewValidTlds($response->getBody())); + $insertDone = true; + } +} + +if (! $insertDone) { + printf('Error: cannot find line with "protected $validTlds"%s', PHP_EOL); + exit(1); +} + +if (!$insertFinish) { + printf('Error: cannot find end of $validTlds declaration%s', PHP_EOL); + exit(1); +} + +if (false === @file_put_contents(LAMINAS_HOSTNAME_VALIDATOR_FILE, $newFileContent)) { + printf('Error: cannot write info file "%s"%s', LAMINAS_HOSTNAME_VALIDATOR_FILE, PHP_EOL); + exit(1); +} + +printf('Validator TLD file updated.%s', PHP_EOL); +exit(0); + +/** + * Get Official TLDs + * + * @return \Laminas\Http\Response + * @throws Exception + */ +function getOfficialTLDs() +{ + $client = new Client(); + $client->setOptions([ + 'adapter' => 'Laminas\Http\Client\Adapter\Curl', + ]); + $client->setUri(IANA_URL); + $client->setMethod('GET'); + + $response = $client->send(); + if (! $response->isSuccess()) { + throw new \Exception(sprintf("Error: cannot get '%s'%s", IANA_URL, PHP_EOL)); + } + return $response; +} + +/** + * Extract the first match of a string like + * "Version 2015072300" from the given string + * + * @param string $prefix + * @param string $string + * @return string + * @throws Exception + */ +function getVersionFromString($prefix, $string) +{ + $matches = []; + if (! preg_match(sprintf('/%s\s+((\d+)?)/', $prefix), $string, $matches)) { + throw new Exception('Error: cannot get last update date'); + } + + return $matches[1]; +} + +/** + * Extract new Valid TLDs from a string containing one per line. + * + * @param string $string + * @return array + */ +function getNewValidTlds($string) +{ + $decodePunycode = getPunycodeDecoder(); + + // Get new TLDs from the list previously fetched + $newValidTlds = []; + foreach (preg_grep('/^[^#]/', preg_split("#\r?\n#", $string)) as $line) { + $newValidTlds []= sprintf( + "%s'%s',\n", + str_repeat(' ', 8), + $decodePunycode(strtolower($line)) + ); + } + + return $newValidTlds; +} + +/** + * Retrieve and return a punycode decoder. + * + * TLDs are puny encoded. + * + * We need a decodePunycode function to translate TLDs to UTF-8: + * + * - use idn_to_utf8 if available + * - otherwise, use Hostname::decodePunycode() + * + * @return callable + */ +function getPunycodeDecoder() +{ + if (function_exists('idn_to_utf8')) { + return function ($domain) { + return idn_to_utf8($domain, 0, INTL_IDNA_VARIANT_UTS46); + }; + } + + $hostnameValidator = new Hostname(); + $reflection = new ReflectionClass(get_class($hostnameValidator)); + $decodePunyCode = $reflection->getMethod('decodePunycode'); + $decodePunyCode->setAccessible(true); + + return function ($encode) use ($hostnameValidator, $decodePunyCode) { + if (strpos($encode, 'xn--') === 0) { + return $decodePunyCode->invokeArgs($hostnameValidator, [substr($encode, 4)]); + } + return $encode; + }; +} diff --git a/lib/laminas/laminas-validator/composer.json b/lib/laminas/laminas-validator/composer.json new file mode 100644 index 000000000..aa9b72c3d --- /dev/null +++ b/lib/laminas/laminas-validator/composer.json @@ -0,0 +1,84 @@ +{ + "name": "laminas/laminas-validator", + "description": "Validation classes for a wide range of domains, and the ability to chain validators to create complex validation criteria", + "license": "BSD-3-Clause", + "keywords": [ + "laminas", + "validator" + ], + "homepage": "https://laminas.dev", + "support": { + "docs": "https://docs.laminas.dev/laminas-validator/", + "issues": "https://github.com/laminas/laminas-validator/issues", + "source": "https://github.com/laminas/laminas-validator", + "rss": "https://github.com/laminas/laminas-validator/releases.atom", + "chat": "https://laminas.dev/chat", + "forum": "https://discourse.laminas.dev" + }, + "config": { + "sort-packages": true + }, + "extra": { + "laminas": { + "component": "Laminas\\Validator", + "config-provider": "Laminas\\Validator\\ConfigProvider" + } + }, + "require": { + "php": "^7.1", + "container-interop/container-interop": "^1.1", + "laminas/laminas-stdlib": "^3.2.1", + "laminas/laminas-zendframework-bridge": "^1.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" + }, + "autoload": { + "psr-4": { + "Laminas\\Validator\\": "src/" + } + }, + "autoload-dev": { + "psr-4": { + "LaminasTest\\Validator\\": "test/" + } + }, + "scripts": { + "check": [ + "@cs-check", + "@test" + ], + "cs-check": "phpcs", + "cs-fix": "phpcbf", + "test": "phpunit --colors=always", + "test-coverage": "phpunit --colors=always --coverage-clover clover.xml" + }, + "replace": { + "zendframework/zend-validator": "^2.13.0" + } +} diff --git a/lib/laminas/laminas-validator/src/AbstractValidator.php b/lib/laminas/laminas-validator/src/AbstractValidator.php new file mode 100644 index 000000000..28578036e --- /dev/null +++ b/lib/laminas/laminas-validator/src/AbstractValidator.php @@ -0,0 +1,573 @@ + [], // Array of validation failure messages + 'messageTemplates' => [], // Array of validation failure message templates + 'messageVariables' => [], // Array of additional variables available for validation failure messages + 'translator' => null, // Translation object to used -> Translator\TranslatorInterface + 'translatorTextDomain' => null, // Translation text domain + 'translatorEnabled' => true, // Is translation enabled? + 'valueObscured' => false, // Flag indicating whether or not value should be obfuscated + // in error messages + ]; + + /** + * Abstract constructor for all validators + * A validator should accept following parameters: + * - nothing f.e. Validator() + * - one or multiple scalar values f.e. Validator($first, $second, $third) + * - an array f.e. Validator(array($first => 'first', $second => 'second', $third => 'third')) + * - an instance of Traversable f.e. Validator($config_instance) + * + * @param array|Traversable $options + */ + public function __construct($options = null) + { + // The abstract constructor allows no scalar values + if ($options instanceof Traversable) { + $options = ArrayUtils::iteratorToArray($options); + } + + if (isset($this->messageTemplates)) { + $this->abstractOptions['messageTemplates'] = $this->messageTemplates; + } + + if (isset($this->messageVariables)) { + $this->abstractOptions['messageVariables'] = $this->messageVariables; + } + + if (is_array($options)) { + $this->setOptions($options); + } + } + + /** + * Returns an option + * + * @param string $option Option to be returned + * @return mixed Returned option + * @throws Exception\InvalidArgumentException + */ + public function getOption($option) + { + if (array_key_exists($option, $this->abstractOptions)) { + return $this->abstractOptions[$option]; + } + + if (isset($this->options) && array_key_exists($option, $this->options)) { + return $this->options[$option]; + } + + throw new Exception\InvalidArgumentException("Invalid option '$option'"); + } + + /** + * Returns all available options + * + * @return array Array with all available options + */ + public function getOptions() + { + $result = $this->abstractOptions; + if (isset($this->options)) { + $result += $this->options; + } + return $result; + } + + /** + * Sets one or multiple options + * + * @param array|Traversable $options Options to set + * @throws Exception\InvalidArgumentException If $options is not an array or Traversable + * @return $this Provides fluid interface + */ + public function setOptions($options = []) + { + if (! is_array($options) && ! $options instanceof Traversable) { + throw new Exception\InvalidArgumentException(__METHOD__ . ' expects an array or Traversable'); + } + + foreach ($options as $name => $option) { + $fname = 'set' . ucfirst($name); + $fname2 = 'is' . ucfirst($name); + if (($name !== 'setOptions') && method_exists($this, $name)) { + $this->{$name}($option); + } elseif (($fname !== 'setOptions') && method_exists($this, $fname)) { + $this->{$fname}($option); + } elseif (method_exists($this, $fname2)) { + $this->{$fname2}($option); + } elseif (isset($this->options)) { + $this->options[$name] = $option; + } else { + $this->abstractOptions[$name] = $option; + } + } + + return $this; + } + + /** + * Returns array of validation failure messages + * + * @return array + */ + public function getMessages() + { + return array_unique($this->abstractOptions['messages'], SORT_REGULAR); + } + + /** + * Invoke as command + * + * @param mixed $value + * @return bool + */ + public function __invoke($value) + { + return $this->isValid($value); + } + + /** + * Returns an array of the names of variables that are used in constructing validation failure messages + * + * @return array + */ + public function getMessageVariables() + { + return array_keys($this->abstractOptions['messageVariables']); + } + + /** + * Returns the message templates from the validator + * + * @return array + */ + public function getMessageTemplates() + { + return $this->abstractOptions['messageTemplates']; + } + + /** + * Sets the validation failure message template for a particular key + * + * @param string $messageString + * @param string $messageKey OPTIONAL + * @return $this Provides a fluent interface + * @throws Exception\InvalidArgumentException + */ + public function setMessage($messageString, $messageKey = null) + { + if ($messageKey === null) { + $keys = array_keys($this->abstractOptions['messageTemplates']); + foreach ($keys as $key) { + $this->setMessage($messageString, $key); + } + return $this; + } + + if (! isset($this->abstractOptions['messageTemplates'][$messageKey])) { + throw new Exception\InvalidArgumentException("No message template exists for key '$messageKey'"); + } + + $this->abstractOptions['messageTemplates'][$messageKey] = $messageString; + return $this; + } + + /** + * Sets validation failure message templates given as an array, where the array keys are the message keys, + * and the array values are the message template strings. + * + * @param array $messages + * @return $this + */ + public function setMessages(array $messages) + { + foreach ($messages as $key => $message) { + $this->setMessage($message, $key); + } + return $this; + } + + /** + * Magic function returns the value of the requested property, if and only if it is the value or a + * message variable. + * + * @param string $property + * @return mixed + * @throws Exception\InvalidArgumentException + */ + public function __get($property) + { + if ($property == 'value') { + return $this->value; + } + + if (array_key_exists($property, $this->abstractOptions['messageVariables'])) { + $result = $this->abstractOptions['messageVariables'][$property]; + if (is_array($result)) { + return $this->{key($result)}[current($result)]; + } + return $this->{$result}; + } + + if (isset($this->messageVariables) && array_key_exists($property, $this->messageVariables)) { + $result = $this->{$this->messageVariables[$property]}; + if (is_array($result)) { + return $this->{key($result)}[current($result)]; + } + return $this->{$result}; + } + + throw new Exception\InvalidArgumentException("No property exists by the name '$property'"); + } + + /** + * Constructs and returns a validation failure message with the given message key and value. + * + * Returns null if and only if $messageKey does not correspond to an existing template. + * + * If a translator is available and a translation exists for $messageKey, + * the translation will be used. + * + * @param string $messageKey + * @param string|array|object $value + * @return string + */ + protected function createMessage($messageKey, $value) + { + if (! isset($this->abstractOptions['messageTemplates'][$messageKey])) { + return; + } + + $message = $this->abstractOptions['messageTemplates'][$messageKey]; + + $message = $this->translateMessage($messageKey, $message); + + if (is_object($value) && + ! in_array('__toString', get_class_methods($value)) + ) { + $value = get_class($value) . ' object'; + } elseif (is_array($value)) { + $value = var_export($value, 1); + } else { + $value = (string) $value; + } + + if ($this->isValueObscured()) { + $value = str_repeat('*', strlen($value)); + } + + $message = str_replace('%value%', (string) $value, $message); + foreach ($this->abstractOptions['messageVariables'] as $ident => $property) { + if (is_array($property)) { + $value = $this->{key($property)}[current($property)]; + if (is_array($value)) { + $value = '[' . implode(', ', $value) . ']'; + } + } else { + $value = $this->$property; + } + $message = str_replace("%$ident%", (string) $value, $message); + } + + $length = self::getMessageLength(); + if (($length > -1) && (strlen($message) > $length)) { + $message = substr($message, 0, $length - 3) . '...'; + } + + return $message; + } + + /** + * @param string $messageKey + * @param string $value OPTIONAL + * @return void + */ + protected function error($messageKey, $value = null) + { + if ($messageKey === null) { + $keys = array_keys($this->abstractOptions['messageTemplates']); + $messageKey = current($keys); + } + + if ($value === null) { + $value = $this->value; + } + + $this->abstractOptions['messages'][$messageKey] = $this->createMessage($messageKey, $value); + } + + /** + * Returns the validation value + * + * @return mixed Value to be validated + */ + protected function getValue() + { + return $this->value; + } + + /** + * Sets the value to be validated and clears the messages and errors arrays + * + * @param mixed $value + * @return void + */ + protected function setValue($value) + { + $this->value = $value; + $this->abstractOptions['messages'] = []; + } + + /** + * Set flag indicating whether or not value should be obfuscated in messages + * + * @param bool $flag + * @return $this + */ + public function setValueObscured($flag) + { + $this->abstractOptions['valueObscured'] = (bool) $flag; + return $this; + } + + /** + * Retrieve flag indicating whether or not value should be obfuscated in + * messages + * + * @return bool + */ + public function isValueObscured() + { + return $this->abstractOptions['valueObscured']; + } + + /** + * Set translation object + * + * @param Translator\TranslatorInterface|null $translator + * @param string $textDomain (optional) + * @return $this + * @throws Exception\InvalidArgumentException + */ + public function setTranslator(Translator\TranslatorInterface $translator = null, $textDomain = null) + { + $this->abstractOptions['translator'] = $translator; + if (null !== $textDomain) { + $this->setTranslatorTextDomain($textDomain); + } + return $this; + } + + /** + * Return translation object + * + * @return Translator\TranslatorInterface|null + */ + public function getTranslator() + { + if (! $this->isTranslatorEnabled()) { + return; + } + + if (null === $this->abstractOptions['translator']) { + $this->abstractOptions['translator'] = self::getDefaultTranslator(); + } + + return $this->abstractOptions['translator']; + } + + /** + * Does this validator have its own specific translator? + * + * @return bool + */ + public function hasTranslator() + { + return (bool) $this->abstractOptions['translator']; + } + + /** + * Set translation text domain + * + * @param string $textDomain + * @return $this + */ + public function setTranslatorTextDomain($textDomain = 'default') + { + $this->abstractOptions['translatorTextDomain'] = $textDomain; + return $this; + } + + /** + * Return the translation text domain + * + * @return string + */ + public function getTranslatorTextDomain() + { + if (null === $this->abstractOptions['translatorTextDomain']) { + $this->abstractOptions['translatorTextDomain'] = + self::getDefaultTranslatorTextDomain(); + } + return $this->abstractOptions['translatorTextDomain']; + } + + /** + * Set default translation object for all validate objects + * + * @param Translator\TranslatorInterface|null $translator + * @param string $textDomain (optional) + * @return void + * @throws Exception\InvalidArgumentException + */ + public static function setDefaultTranslator(Translator\TranslatorInterface $translator = null, $textDomain = null) + { + static::$defaultTranslator = $translator; + if (null !== $textDomain) { + self::setDefaultTranslatorTextDomain($textDomain); + } + } + + /** + * Get default translation object for all validate objects + * + * @return Translator\TranslatorInterface|null + */ + public static function getDefaultTranslator() + { + return static::$defaultTranslator; + } + + /** + * Is there a default translation object set? + * + * @return bool + */ + public static function hasDefaultTranslator() + { + return (bool) static::$defaultTranslator; + } + + /** + * Set default translation text domain for all validate objects + * + * @param string $textDomain + * @return void + */ + public static function setDefaultTranslatorTextDomain($textDomain = 'default') + { + static::$defaultTranslatorTextDomain = $textDomain; + } + + /** + * Get default translation text domain for all validate objects + * + * @return string + */ + public static function getDefaultTranslatorTextDomain() + { + return static::$defaultTranslatorTextDomain; + } + + /** + * Indicate whether or not translation should be enabled + * + * @param bool $flag + * @return $this + */ + public function setTranslatorEnabled($flag = true) + { + $this->abstractOptions['translatorEnabled'] = (bool) $flag; + return $this; + } + + /** + * Is translation enabled? + * + * @return bool + */ + public function isTranslatorEnabled() + { + return $this->abstractOptions['translatorEnabled']; + } + + /** + * Returns the maximum allowed message length + * + * @return int + */ + public static function getMessageLength() + { + return static::$messageLength; + } + + /** + * Sets the maximum allowed message length + * + * @param int $length + */ + public static function setMessageLength($length = -1) + { + static::$messageLength = $length; + } + + /** + * Translate a validation message + * + * @param string $messageKey + * @param string $message + * @return string + */ + protected function translateMessage($messageKey, $message) + { + $translator = $this->getTranslator(); + if (! $translator) { + return $message; + } + + return $translator->translate($message, $this->getTranslatorTextDomain()); + } +} diff --git a/lib/laminas/laminas-validator/src/Barcode.php b/lib/laminas/laminas-validator/src/Barcode.php new file mode 100644 index 000000000..8a3ec759b --- /dev/null +++ b/lib/laminas/laminas-validator/src/Barcode.php @@ -0,0 +1,190 @@ + 'The input failed checksum validation', + self::INVALID_CHARS => 'The input contains invalid characters', + self::INVALID_LENGTH => 'The input should have a length of %length% characters', + self::INVALID => 'Invalid type given. String expected', + ]; + + /** + * Additional variables available for validation failure messages + * + * @var array + */ + protected $messageVariables = [ + 'length' => ['options' => 'length'], + ]; + + protected $options = [ + 'adapter' => null, // Barcode adapter Laminas\Validator\Barcode\AbstractAdapter + 'options' => null, // Options for this adapter + 'length' => null, + 'useChecksum' => null, + ]; + + /** + * Constructor for barcodes + * + * @param array|string $options Options to use + */ + public function __construct($options = null) + { + if ($options === null) { + $options = []; + } + + if (is_array($options)) { + if (array_key_exists('options', $options)) { + $options['options'] = ['options' => $options['options']]; + } + } elseif ($options instanceof Traversable) { + if (property_exists($options, 'options')) { + $options['options'] = ['options' => $options['options']]; + } + } else { + $options = ['adapter' => $options]; + } + + parent::__construct($options); + } + + /** + * Returns the set adapter + * + * @return Barcode\AbstractAdapter + */ + public function getAdapter() + { + if (! $this->options['adapter'] instanceof Barcode\AdapterInterface) { + $this->setAdapter('Ean13'); + } + + return $this->options['adapter']; + } + + /** + * Sets a new barcode adapter + * + * @param string|Barcode\AbstractAdapter $adapter Barcode adapter to use + * @param array $options Options for this adapter + * @return $this + * @throws Exception\InvalidArgumentException + */ + public function setAdapter($adapter, $options = null) + { + if (is_string($adapter)) { + $adapter = ucfirst(strtolower($adapter)); + $adapter = 'Laminas\\Validator\\Barcode\\' . $adapter; + + if (! class_exists($adapter)) { + throw new Exception\InvalidArgumentException('Barcode adapter matching "' . $adapter . '" not found'); + } + + $adapter = new $adapter($options); + } + + if (! $adapter instanceof Barcode\AdapterInterface) { + throw new Exception\InvalidArgumentException( + sprintf( + 'Adapter %s does not implement Laminas\\Validator\\Barcode\\AdapterInterface', + is_object($adapter) ? get_class($adapter) : gettype($adapter) + ) + ); + } + + $this->options['adapter'] = $adapter; + + return $this; + } + + /** + * Returns the checksum option + * + * @return string + */ + public function getChecksum() + { + return $this->getAdapter()->getChecksum(); + } + + /** + * Sets if checksum should be validated, if no value is given the actual setting is returned + * + * @param bool $checksum + * @return bool + */ + public function useChecksum($checksum = null) + { + return $this->getAdapter()->useChecksum($checksum); + } + + /** + * Defined by Laminas\Validator\ValidatorInterface + * + * Returns true if and only if $value contains a valid barcode + * + * @param string $value + * @return bool + */ + public function isValid($value) + { + if (! is_string($value)) { + $this->error(self::INVALID); + return false; + } + + $this->setValue($value); + $adapter = $this->getAdapter(); + $this->options['length'] = $adapter->getLength(); + $result = $adapter->hasValidLength($value); + if (! $result) { + if (is_array($this->options['length'])) { + $temp = $this->options['length']; + $this->options['length'] = ''; + foreach ($temp as $length) { + $this->options['length'] .= '/'; + $this->options['length'] .= $length; + } + + $this->options['length'] = substr($this->options['length'], 1); + } + + $this->error(self::INVALID_LENGTH); + return false; + } + + $result = $adapter->hasValidCharacters($value); + if (! $result) { + $this->error(self::INVALID_CHARS); + return false; + } + + if ($this->useChecksum(null)) { + $result = $adapter->hasValidChecksum($value); + if (! $result) { + $this->error(self::FAILED); + return false; + } + } + + return true; + } +} diff --git a/lib/laminas/laminas-validator/src/Barcode/AbstractAdapter.php b/lib/laminas/laminas-validator/src/Barcode/AbstractAdapter.php new file mode 100644 index 000000000..fc24e6242 --- /dev/null +++ b/lib/laminas/laminas-validator/src/Barcode/AbstractAdapter.php @@ -0,0 +1,309 @@ + null, // Allowed barcode lengths, integer, array, string + 'characters' => null, // Allowed barcode characters + 'checksum' => null, // Callback to checksum function + 'useChecksum' => true, // Is a checksum value included?, boolean + ]; + + /** + * Checks the length of a barcode + * + * @param string $value The barcode to check for proper length + * @return bool + */ + public function hasValidLength($value) + { + if (! is_string($value)) { + return false; + } + + $fixum = strlen($value); + $found = false; + $length = $this->getLength(); + if (is_array($length)) { + foreach ($length as $value) { + if ($fixum == $value) { + $found = true; + } + + if ($value == -1) { + $found = true; + } + } + } elseif ($fixum == $length) { + $found = true; + } elseif ($length == -1) { + $found = true; + } elseif ($length == 'even') { + $count = $fixum % 2; + $found = 0 == $count; + } elseif ($length == 'odd') { + $count = $fixum % 2; + $found = 1 == $count; + } + + return $found; + } + + /** + * Checks for allowed characters within the barcode + * + * @param string $value The barcode to check for allowed characters + * @return bool + */ + public function hasValidCharacters($value) + { + if (! is_string($value)) { + return false; + } + + $characters = $this->getCharacters(); + if ($characters == 128) { + for ($x = 0; $x < 128; ++$x) { + $value = str_replace(chr($x), '', $value); + } + } else { + $chars = str_split($characters); + foreach ($chars as $char) { + $value = str_replace($char, '', $value); + } + } + + if (strlen($value) > 0) { + return false; + } + + return true; + } + + /** + * Validates the checksum + * + * @param string $value The barcode to check the checksum for + * @return bool + */ + public function hasValidChecksum($value) + { + $checksum = $this->getChecksum(); + if (! empty($checksum)) { + if (method_exists($this, $checksum)) { + return $this->$checksum($value); + } + } + + return false; + } + + /** + * Returns the allowed barcode length + * + * @return int|array + */ + public function getLength() + { + return $this->options['length']; + } + + /** + * Returns the allowed characters + * + * @return int|string|array + */ + public function getCharacters() + { + return $this->options['characters']; + } + + /** + * Returns the checksum function name + * + */ + public function getChecksum() + { + return $this->options['checksum']; + } + + /** + * Sets the checksum validation method + * + * @param callable $checksum Checksum method to call + * @return $this + */ + protected function setChecksum($checksum) + { + $this->options['checksum'] = $checksum; + return $this; + } + + /** + * Sets the checksum validation, if no value is given, the actual setting is returned + * + * @param bool $check + * @return AbstractAdapter|bool + */ + public function useChecksum($check = null) + { + if ($check === null) { + return $this->options['useChecksum']; + } + + $this->options['useChecksum'] = (bool) $check; + return $this; + } + + /** + * Sets the length of this barcode + * + * @param int|array $length + * @return $this + */ + protected function setLength($length) + { + $this->options['length'] = $length; + return $this; + } + + /** + * Sets the allowed characters of this barcode + * + * @param int $characters + * @return $this + */ + protected function setCharacters($characters) + { + $this->options['characters'] = $characters; + return $this; + } + + /** + * Validates the checksum (Modulo 10) + * GTIN implementation factor 3 + * + * @param string $value The barcode to validate + * @return bool + */ + protected function gtin($value) + { + $barcode = substr($value, 0, -1); + $sum = 0; + $length = strlen($barcode) - 1; + + for ($i = 0; $i <= $length; $i++) { + if (($i % 2) === 0) { + $sum += $barcode[$length - $i] * 3; + } else { + $sum += $barcode[$length - $i]; + } + } + + $calc = $sum % 10; + $checksum = $calc === 0 ? 0 : 10 - $calc; + if ($value[$length + 1] != $checksum) { + return false; + } + + return true; + } + + /** + * Validates the checksum (Modulo 10) + * IDENTCODE implementation factors 9 and 4 + * + * @param string $value The barcode to validate + * @return bool + */ + protected function identcode($value) + { + $barcode = substr($value, 0, -1); + $sum = 0; + $length = strlen($value) - 2; + + for ($i = 0; $i <= $length; $i++) { + if (($i % 2) === 0) { + $sum += $barcode[$length - $i] * 4; + } else { + $sum += $barcode[$length - $i] * 9; + } + } + + $calc = $sum % 10; + $checksum = $calc === 0 ? 0 : 10 - $calc; + if ($value[$length + 1] != $checksum) { + return false; + } + + return true; + } + + /** + * Validates the checksum (Modulo 10) + * CODE25 implementation factor 3 + * + * @param string $value The barcode to validate + * @return bool + */ + protected function code25($value) + { + $barcode = substr($value, 0, -1); + $sum = 0; + $length = strlen($barcode) - 1; + + for ($i = 0; $i <= $length; $i++) { + if (($i % 2) === 0) { + $sum += $barcode[$i] * 3; + } else { + $sum += $barcode[$i]; + } + } + + $calc = $sum % 10; + $checksum = $calc === 0 ? 0 : 10 - $calc; + if ($value[$length + 1] != $checksum) { + return false; + } + + return true; + } + + /** + * Validates the checksum () + * POSTNET implementation + * + * @param string $value The barcode to validate + * @return bool + */ + protected function postnet($value) + { + $checksum = substr($value, -1, 1); + $values = str_split(substr($value, 0, -1)); + + $check = 0; + foreach ($values as $row) { + $check += $row; + } + + $check %= 10; + $check = 10 - $check; + if ($check == $checksum) { + return true; + } + + return false; + } +} diff --git a/lib/laminas/laminas-validator/src/Barcode/AdapterInterface.php b/lib/laminas/laminas-validator/src/Barcode/AdapterInterface.php new file mode 100644 index 000000000..c9f7afe17 --- /dev/null +++ b/lib/laminas/laminas-validator/src/Barcode/AdapterInterface.php @@ -0,0 +1,65 @@ +setLength(-1); + $this->setCharacters('0123456789-$:/.+ABCDTN*E'); + $this->useChecksum(false); + } + + /** + * Checks for allowed characters + * @see Laminas\Validator\Barcode.AbstractAdapter::checkChars() + */ + public function hasValidCharacters($value) + { + if (strpbrk($value, 'ABCD')) { + $first = $value[0]; + if (! strpbrk($first, 'ABCD')) { + // Missing start char + return false; + } + + $last = substr($value, -1, 1); + if (! strpbrk($last, 'ABCD')) { + // Missing stop char + return false; + } + + $value = substr($value, 1, -1); + } elseif (strpbrk($value, 'TN*E')) { + $first = $value[0]; + if (! strpbrk($first, 'TN*E')) { + // Missing start char + return false; + } + + $last = substr($value, -1, 1); + if (! strpbrk($last, 'TN*E')) { + // Missing stop char + return false; + } + + $value = substr($value, 1, -1); + } + + $chars = $this->getCharacters(); + $this->setCharacters('0123456789-$:/.+'); + $result = parent::hasValidCharacters($value); + $this->setCharacters($chars); + return $result; + } +} diff --git a/lib/laminas/laminas-validator/src/Barcode/Code128.php b/lib/laminas/laminas-validator/src/Barcode/Code128.php new file mode 100644 index 000000000..400846ddf --- /dev/null +++ b/lib/laminas/laminas-validator/src/Barcode/Code128.php @@ -0,0 +1,447 @@ +setLength(-1); + $this->setCharacters([ + 'A' => [ + 0 => ' ', 1 => '!', 2 => '"', 3 => '#', 4 => '$', 5 => '%', 6 => '&', 7 => "'", + 8 => '(', 9 => ')', 10 => '*', 11 => '+', 12 => ',', 13 => '-', 14 => '.', 15 => '/', + 16 => '0', 17 => '1', 18 => '2', 19 => '3', 20 => '4', 21 => '5', 22 => '6', 23 => '7', + 24 => '8', 25 => '9', 26 => ':', 27 => ';', 28 => '<', 29 => '=', 30 => '>', 31 => '?', + 32 => '@', 33 => 'A', 34 => 'B', 35 => 'C', 36 => 'D', 37 => 'E', 38 => 'F', 39 => 'G', + 40 => 'H', 41 => 'I', 42 => 'J', 43 => 'K', 44 => 'L', 45 => 'M', 46 => 'N', 47 => 'O', + 48 => 'P', 49 => 'Q', 50 => 'R', 51 => 'S', 52 => 'T', 53 => 'U', 54 => 'V', 55 => 'W', + 56 => 'X', 57 => 'Y', 58 => 'Z', 59 => '[', 60 => '\\', 61 => ']', 62 => '^', 63 => '_', + 64 => 0x00, 65 => 0x01, 66 => 0x02, 67 => 0x03, 68 => 0x04, 69 => 0x05, 70 => 0x06, 71 => 0x07, + 72 => 0x08, 73 => 0x09, 74 => 0x0A, 75 => 0x0B, 76 => 0x0C, 77 => 0x0D, 78 => 0x0E, 79 => 0x0F, + 80 => 0x10, 81 => 0x11, 82 => 0x12, 83 => 0x13, 84 => 0x14, 85 => 0x15, 86 => 0x16, 87 => 0x17, + 88 => 0x18, 89 => 0x19, 90 => 0x1A, 91 => 0x1B, 92 => 0x1C, 93 => 0x1D, 94 => 0x1E, 95 => 0x1F, + 96 => 'Ç', 97 => 'ü', 98 => 'é', 99 => 'â', 100 => 'ä', 101 => 'à', 102 => 'å', 103 => '‡', + 104 => 'ˆ', 105 => '‰', 106 => 'Š'], + 'B' => [ + 0 => ' ', 1 => '!', 2 => '"', 3 => '#', 4 => '$', 5 => '%', 6 => '&', 7 => "'", + 8 => '(', 9 => ')', 10 => '*', 11 => '+', 12 => ',', 13 => '-', 14 => '.', 15 => '/', + 16 => '0', 17 => '1', 18 => '2', 19 => '3', 20 => '4', 21 => '5', 22 => '6', 23 => '7', + 24 => '8', 25 => '9', 26 => ':', 27 => ';', 28 => '<', 29 => '=', 30 => '>', 31 => '?', + 32 => '@', 33 => 'A', 34 => 'B', 35 => 'C', 36 => 'D', 37 => 'E', 38 => 'F', 39 => 'G', + 40 => 'H', 41 => 'I', 42 => 'J', 43 => 'K', 44 => 'L', 45 => 'M', 46 => 'N', 47 => 'O', + 48 => 'P', 49 => 'Q', 50 => 'R', 51 => 'S', 52 => 'T', 53 => 'U', 54 => 'V', 55 => 'W', + 56 => 'X', 57 => 'Y', 58 => 'Z', 59 => '[', 60 => '\\', 61 => ']', 62 => '^', 63 => '_', + 64 => '`', 65 => 'a', 66 => 'b', 67 => 'c', 68 => 'd', 69 => 'e', 70 => 'f', 71 => 'g', + 72 => 'h', 73 => 'i', 74 => 'j', 75 => 'k', 76 => 'l', 77 => 'm', 78 => 'n', 79 => 'o', + 80 => 'p', 81 => 'q', 82 => 'r', 83 => 's', 84 => 't', 85 => 'u', 86 => 'v', 87 => 'w', + 88 => 'x', 89 => 'y', 90 => 'z', 91 => '{', 92 => '|', 93 => '}', 94 => '~', 95 => 0x7F, + 96 => 'Ç', 97 => 'ü', 98 => 'é', 99 => 'â', 100 => 'ä', 101 => 'à', 102 => 'å', 103 => '‡', + 104 => 'ˆ', 105 => '‰', 106 => 'Š'], + 'C' => [ + 0 => '00', 1 => '01', 2 => '02', 3 => '03', 4 => '04', 5 => '05', 6 => '06', 7 => '07', + 8 => '08', 9 => '09', 10 => '10', 11 => '11', 12 => '12', 13 => '13', 14 => '14', 15 => '15', + 16 => '16', 17 => '17', 18 => '18', 19 => '19', 20 => '20', 21 => '21', 22 => '22', 23 => '23', + 24 => '24', 25 => '25', 26 => '26', 27 => '27', 28 => '28', 29 => '29', 30 => '30', 31 => '31', + 32 => '32', 33 => '33', 34 => '34', 35 => '35', 36 => '36', 37 => '37', 38 => '38', 39 => '39', + 40 => '40', 41 => '41', 42 => '42', 43 => '43', 44 => '44', 45 => '45', 46 => '46', 47 => '47', + 48 => '48', 49 => '49', 50 => '50', 51 => '51', 52 => '52', 53 => '53', 54 => '54', 55 => '55', + 56 => '56', 57 => '57', 58 => '58', 59 => '59', 60 => '60', 61 => '61', 62 => '62', 63 => '63', + 64 => '64', 65 => '65', 66 => '66', 67 => '67', 68 => '68', 69 => '69', 70 => '70', 71 => '71', + 72 => '72', 73 => '73', 74 => '74', 75 => '75', 76 => '76', 77 => '77', 78 => '78', 79 => '79', + 80 => '80', 81 => '81', 82 => '82', 83 => '83', 84 => '84', 85 => '85', 86 => '86', 87 => '87', + 88 => '88', 89 => '89', 90 => '90', 91 => '91', 92 => '92', 93 => '93', 94 => '94', 95 => '95', + 96 => '96', 97 => '97', 98 => '98', 99 => '99', 100 => 'ä', 101 => 'à', 102 => 'å', 103 => '‡', + 104 => 'ˆ', 105 => '‰', 106 => 'Š'] + ]); + $this->setChecksum('code128'); + } + + public function setUtf8StringWrapper(StringWrapperInterface $utf8StringWrapper) + { + if (! $utf8StringWrapper->isSupported('UTF-8')) { + throw new Exception\InvalidArgumentException( + 'The string wrapper needs to support UTF-8 character encoding' + ); + } + $this->utf8StringWrapper = $utf8StringWrapper; + } + + /** + * Get the string wrapper supporting UTF-8 character encoding + * + * @return StringWrapperInterface + */ + public function getUtf8StringWrapper() + { + if (! $this->utf8StringWrapper) { + $this->utf8StringWrapper = StringUtils::getWrapper('UTF-8'); + } + return $this->utf8StringWrapper; + } + + /** + * Checks for allowed characters within the barcode + * + * @param string $value The barcode to check for allowed characters + * @return bool + */ + public function hasValidCharacters($value) + { + if (! is_string($value)) { + return false; + } + + // get used string wrapper for UTF-8 character encoding + $strWrapper = $this->getUtf8StringWrapper(); + + // detect starting charset + $set = $this->getCodingSet($value); + $read = $set; + if ($set != '') { + $value = $strWrapper->substr($value, 1, null); + } + + // process barcode + while ($value != '') { + $char = $strWrapper->substr($value, 0, 1); + + switch ($char) { + // Function definition + case 'Ç': + case 'ü': + case 'å': + break; + + // Switch 1 char between A and B + case 'é': + if ($set == 'A') { + $read = 'B'; + } elseif ($set == 'B') { + $read = 'A'; + } + break; + + // Switch to C + case 'â': + $set = 'C'; + $read = 'C'; + break; + + // Switch to B + case 'ä': + $set = 'B'; + $read = 'B'; + break; + + // Switch to A + case 'à': + $set = 'A'; + $read = 'A'; + break; + + // Doubled start character + case '‡': + case 'ˆ': + case '‰': + return false; + + // Chars after the stop character + case 'Š': + break 2; + + default: + // Does the char exist within the charset to read? + if ($this->ord128($char, $read) == -1) { + return false; + } + + break; + } + + $value = $strWrapper->substr($value, 1, null); + $read = $set; + } + + if (($value != '') && ($strWrapper->strlen($value) != 1)) { + return false; + } + + return true; + } + + /** + * Validates the checksum () + * + * @param string $value The barcode to validate + * @return bool + */ + protected function code128($value) + { + $sum = 0; + $pos = 1; + $set = $this->getCodingSet($value); + $read = $set; + $usecheck = $this->useChecksum(null); + $strWrapper = $this->getUtf8StringWrapper(); + $char = $strWrapper->substr($value, 0, 1); + if ($char == '‡') { + $sum = 103; + } elseif ($char == 'ˆ') { + $sum = 104; + } elseif ($char == '‰') { + $sum = 105; + } elseif ($usecheck == true) { + // no start value, unable to detect a proper checksum + return false; + } + + $value = $strWrapper->substr($value, 1, null); + while ($strWrapper->strpos($value, 'Š') || ($value != '')) { + $char = $strWrapper->substr($value, 0, 1); + if ($read == 'C') { + $char = $strWrapper->substr($value, 0, 2); + } + + switch ($char) { + // Function definition + case 'Ç': + case 'ü': + case 'å': + $sum += $pos * $this->ord128($char, $set); + break; + + case 'é': + $sum += $pos * $this->ord128($char, $set); + if ($set == 'A') { + $read = 'B'; + } elseif ($set == 'B') { + $read = 'A'; + } + break; + + // Switch to C + case 'â': + $sum += $pos * $this->ord128($char, $set); + $set = 'C'; + $read = 'C'; + break; + + // Switch to B + case 'ä': + $sum += $pos * $this->ord128($char, $set); + $set = 'B'; + $read = 'B'; + break; + + // Switch to A + case 'à': + $sum += $pos * $this->ord128($char, $set); + $set = 'A'; + $read = 'A'; + break; + + case '‡': + case 'ˆ': + case '‰': + return false; + break; + + default: + // Does the char exist within the charset to read? + if ($this->ord128($char, $read) == -1) { + return false; + } + + $sum += $pos * $this->ord128($char, $set); + break; + } + + $value = $strWrapper->substr($value, 1); + ++$pos; + if (($strWrapper->strpos($value, 'Š') == 1) && ($strWrapper->strlen($value) == 2)) { + // break by stop and checksum char + break; + } + $read = $set; + } + + if (($strWrapper->strpos($value, 'Š') != 1) || ($strWrapper->strlen($value) != 2)) { + // return false if checksum is not readable and true if no startvalue is detected + return ! $usecheck; + } + + $mod = $sum % 103; + if ($strWrapper->substr($value, 0, 1) == $this->chr128($mod, $set)) { + return true; + } + + return false; + } + + /** + * Returns the coding set for a barcode + * + * @param string $value Barcode + * @return string + */ + protected function getCodingSet($value) + { + $value = $this->getUtf8StringWrapper()->substr($value, 0, 1); + switch ($value) { + case '‡': + return 'A'; + break; + case 'ˆ': + return 'B'; + break; + case '‰': + return 'C'; + break; + } + + return ''; + } + + /** + * Internal method to return the code128 integer from an ascii value + * + * Table A + * ASCII CODE128 + * 32 to 95 == 0 to 63 + * 0 to 31 == 64 to 95 + * 128 to 138 == 96 to 106 + * + * Table B + * ASCII CODE128 + * 32 to 138 == 0 to 106 + * + * Table C + * ASCII CODE128 + * "00" to "99" == 0 to 99 + * 132 to 138 == 100 to 106 + * + * @param string $value + * @param string $set + * @return int + */ + protected function ord128($value, $set) + { + $ord = ord($value); + if ($set == 'A') { + if ($ord < 32) { + return $ord + 64; + } elseif ($ord < 96) { + return $ord - 32; + } elseif ($ord > 138) { + return -1; + } else { + return $ord - 32; + } + } elseif ($set == 'B') { + if ($ord < 32) { + return -1; + } elseif ($ord <= 138) { + return $ord - 32; + } else { + return -1; + } + } elseif ($set == 'C') { + $val = (int) $value; + if (($val >= 0) && ($val <= 99)) { + return $val; + } elseif (($ord >= 132) && ($ord <= 138)) { + return $ord - 32; + } else { + return -1; + } + } else { + if ($ord < 32) { + return $ord + 64; + } elseif ($ord <= 138) { + return $ord - 32; + } else { + return -1; + } + } + } + + /** + * Internal Method to return the ascii value from a code128 integer + * + * Table A + * ASCII CODE128 + * 32 to 95 == 0 to 63 + * 0 to 31 == 64 to 95 + * 128 to 138 == 96 to 106 + * + * Table B + * ASCII CODE128 + * 32 to 138 == 0 to 106 + * + * Table C + * ASCII CODE128 + * "00" to "99" == 0 to 99 + * 132 to 138 == 100 to 106 + * + * @param int $value + * @param string $set + * @return string + */ + protected function chr128($value, $set) + { + if ($set == 'A') { + if ($value < 64) { + return chr($value + 32); + } elseif ($value < 96) { + return chr($value - 64); + } elseif ($value > 106) { + return -1; + } else { + return chr($value + 32); + } + } elseif ($set == 'B') { + if ($value > 106) { + return -1; + } else { + return chr($value + 32); + } + } elseif ($set == 'C') { + if (($value >= 0) && ($value <= 9)) { + return '0' . (string) $value; + } elseif ($value <= 99) { + return (string) $value; + } elseif ($value <= 106) { + return chr($value + 32); + } else { + return -1; + } + } else { + if ($value <= 106) { + return $value + 32; + } else { + return -1; + } + } + } +} diff --git a/lib/laminas/laminas-validator/src/Barcode/Code25.php b/lib/laminas/laminas-validator/src/Barcode/Code25.php new file mode 100644 index 000000000..f98f32238 --- /dev/null +++ b/lib/laminas/laminas-validator/src/Barcode/Code25.php @@ -0,0 +1,23 @@ +setLength(-1); + $this->setCharacters('0123456789'); + $this->setChecksum('code25'); + $this->useChecksum(false); + } +} diff --git a/lib/laminas/laminas-validator/src/Barcode/Code25interleaved.php b/lib/laminas/laminas-validator/src/Barcode/Code25interleaved.php new file mode 100644 index 000000000..5675b225f --- /dev/null +++ b/lib/laminas/laminas-validator/src/Barcode/Code25interleaved.php @@ -0,0 +1,25 @@ +setLength('even'); + $this->setCharacters('0123456789'); + $this->setChecksum('code25'); + $this->useChecksum(false); + } +} diff --git a/lib/laminas/laminas-validator/src/Barcode/Code39.php b/lib/laminas/laminas-validator/src/Barcode/Code39.php new file mode 100644 index 000000000..dc583678b --- /dev/null +++ b/lib/laminas/laminas-validator/src/Barcode/Code39.php @@ -0,0 +1,59 @@ + 0, '1' => 1, '2' => 2, '3' => 3, '4' => 4, '5' => 5, '6' => 6, + '7' => 7, '8' => 8, '9' => 9, 'A' => 10, 'B' => 11, 'C' => 12, 'D' => 13, + 'E' => 14, 'F' => 15, 'G' => 16, 'H' => 17, 'I' => 18, 'J' => 19, 'K' => 20, + 'L' => 21, 'M' => 22, 'N' => 23, 'O' => 24, 'P' => 25, 'Q' => 26, 'R' => 27, + 'S' => 28, 'T' => 29, 'U' => 30, 'V' => 31, 'W' => 32, 'X' => 33, 'Y' => 34, + 'Z' => 35, '-' => 36, '.' => 37, ' ' => 38, '$' => 39, '/' => 40, '+' => 41, + '%' => 42, + ]; + + /** + * Constructor for this barcode adapter + */ + public function __construct() + { + $this->setLength(-1); + $this->setCharacters('0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ -.$/+%'); + $this->setChecksum('code39'); + $this->useChecksum(false); + } + + /** + * Validates the checksum (Modulo 43) + * + * @param string $value The barcode to validate + * @return bool + */ + protected function code39($value) + { + $checksum = substr($value, -1, 1); + $value = str_split(substr($value, 0, -1)); + $count = 0; + foreach ($value as $char) { + $count += $this->check[$char]; + } + + $mod = $count % 43; + if ($mod == $this->check[$checksum]) { + return true; + } + + return false; + } +} diff --git a/lib/laminas/laminas-validator/src/Barcode/Code39ext.php b/lib/laminas/laminas-validator/src/Barcode/Code39ext.php new file mode 100644 index 000000000..142b85f81 --- /dev/null +++ b/lib/laminas/laminas-validator/src/Barcode/Code39ext.php @@ -0,0 +1,22 @@ +setLength(-1); + $this->setCharacters(128); + $this->useChecksum(false); + } +} diff --git a/lib/laminas/laminas-validator/src/Barcode/Code93.php b/lib/laminas/laminas-validator/src/Barcode/Code93.php new file mode 100644 index 000000000..fb9a65bc6 --- /dev/null +++ b/lib/laminas/laminas-validator/src/Barcode/Code93.php @@ -0,0 +1,79 @@ + 0, '1' => 1, '2' => 2, '3' => 3, '4' => 4, '5' => 5, '6' => 6, + '7' => 7, '8' => 8, '9' => 9, 'A' => 10, 'B' => 11, 'C' => 12, 'D' => 13, + 'E' => 14, 'F' => 15, 'G' => 16, 'H' => 17, 'I' => 18, 'J' => 19, 'K' => 20, + 'L' => 21, 'M' => 22, 'N' => 23, 'O' => 24, 'P' => 25, 'Q' => 26, 'R' => 27, + 'S' => 28, 'T' => 29, 'U' => 30, 'V' => 31, 'W' => 32, 'X' => 33, 'Y' => 34, + 'Z' => 35, '-' => 36, '.' => 37, ' ' => 38, '$' => 39, '/' => 40, '+' => 41, + '%' => 42, '!' => 43, '"' => 44, '§' => 45, '&' => 46, + ]; + + /** + * Constructor for this barcode adapter + */ + public function __construct() + { + $this->setLength(-1); + $this->setCharacters('0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ -.$/+%'); + $this->setChecksum('code93'); + $this->useChecksum(false); + } + + /** + * Validates the checksum (Modulo CK) + * + * @param string $value The barcode to validate + * @return bool + */ + protected function code93($value) + { + $checksum = substr($value, -2, 2); + $value = str_split(substr($value, 0, -2)); + $count = 0; + $length = count($value) % 20; + foreach ($value as $char) { + if ($length == 0) { + $length = 20; + } + + $count += $this->check[$char] * $length; + --$length; + } + + $check = array_search($count % 47, $this->check); + $value[] = $check; + $count = 0; + $length = count($value) % 15; + foreach ($value as $char) { + if ($length == 0) { + $length = 15; + } + + $count += $this->check[$char] * $length; + --$length; + } + $check .= array_search($count % 47, $this->check); + + if ($check == $checksum) { + return true; + } + + return false; + } +} diff --git a/lib/laminas/laminas-validator/src/Barcode/Code93ext.php b/lib/laminas/laminas-validator/src/Barcode/Code93ext.php new file mode 100644 index 000000000..f6c7aedd9 --- /dev/null +++ b/lib/laminas/laminas-validator/src/Barcode/Code93ext.php @@ -0,0 +1,22 @@ +setLength(-1); + $this->setCharacters(128); + $this->useChecksum(false); + } +} diff --git a/lib/laminas/laminas-validator/src/Barcode/Ean12.php b/lib/laminas/laminas-validator/src/Barcode/Ean12.php new file mode 100644 index 000000000..a9251f2f3 --- /dev/null +++ b/lib/laminas/laminas-validator/src/Barcode/Ean12.php @@ -0,0 +1,22 @@ +setLength(12); + $this->setCharacters('0123456789'); + $this->setChecksum('gtin'); + } +} diff --git a/lib/laminas/laminas-validator/src/Barcode/Ean13.php b/lib/laminas/laminas-validator/src/Barcode/Ean13.php new file mode 100644 index 000000000..51c7447ca --- /dev/null +++ b/lib/laminas/laminas-validator/src/Barcode/Ean13.php @@ -0,0 +1,22 @@ +setLength(13); + $this->setCharacters('0123456789'); + $this->setChecksum('gtin'); + } +} diff --git a/lib/laminas/laminas-validator/src/Barcode/Ean14.php b/lib/laminas/laminas-validator/src/Barcode/Ean14.php new file mode 100644 index 000000000..dc0c9e9a2 --- /dev/null +++ b/lib/laminas/laminas-validator/src/Barcode/Ean14.php @@ -0,0 +1,22 @@ +setLength(14); + $this->setCharacters('0123456789'); + $this->setChecksum('gtin'); + } +} diff --git a/lib/laminas/laminas-validator/src/Barcode/Ean18.php b/lib/laminas/laminas-validator/src/Barcode/Ean18.php new file mode 100644 index 000000000..516a47731 --- /dev/null +++ b/lib/laminas/laminas-validator/src/Barcode/Ean18.php @@ -0,0 +1,22 @@ +setLength(18); + $this->setCharacters('0123456789'); + $this->setChecksum('gtin'); + } +} diff --git a/lib/laminas/laminas-validator/src/Barcode/Ean2.php b/lib/laminas/laminas-validator/src/Barcode/Ean2.php new file mode 100644 index 000000000..6222b5818 --- /dev/null +++ b/lib/laminas/laminas-validator/src/Barcode/Ean2.php @@ -0,0 +1,22 @@ +setLength(2); + $this->setCharacters('0123456789'); + $this->useChecksum(false); + } +} diff --git a/lib/laminas/laminas-validator/src/Barcode/Ean5.php b/lib/laminas/laminas-validator/src/Barcode/Ean5.php new file mode 100644 index 000000000..b48153aed --- /dev/null +++ b/lib/laminas/laminas-validator/src/Barcode/Ean5.php @@ -0,0 +1,24 @@ +setLength(5); + $this->setCharacters('0123456789'); + $this->useChecksum(false); + } +} diff --git a/lib/laminas/laminas-validator/src/Barcode/Ean8.php b/lib/laminas/laminas-validator/src/Barcode/Ean8.php new file mode 100644 index 000000000..e7ba27f1b --- /dev/null +++ b/lib/laminas/laminas-validator/src/Barcode/Ean8.php @@ -0,0 +1,39 @@ +setLength([7, 8]); + $this->setCharacters('0123456789'); + $this->setChecksum('gtin'); + } + + /** + * Overrides parent checkLength + * + * @param string $value Value + * @return bool + */ + public function hasValidLength($value) + { + if (strlen($value) == 7) { + $this->useChecksum(false); + } else { + $this->useChecksum(true); + } + + return parent::hasValidLength($value); + } +} diff --git a/lib/laminas/laminas-validator/src/Barcode/Gtin12.php b/lib/laminas/laminas-validator/src/Barcode/Gtin12.php new file mode 100644 index 000000000..a65dbec3b --- /dev/null +++ b/lib/laminas/laminas-validator/src/Barcode/Gtin12.php @@ -0,0 +1,22 @@ +setLength(12); + $this->setCharacters('0123456789'); + $this->setChecksum('gtin'); + } +} diff --git a/lib/laminas/laminas-validator/src/Barcode/Gtin13.php b/lib/laminas/laminas-validator/src/Barcode/Gtin13.php new file mode 100644 index 000000000..315e20f3b --- /dev/null +++ b/lib/laminas/laminas-validator/src/Barcode/Gtin13.php @@ -0,0 +1,22 @@ +setLength(13); + $this->setCharacters('0123456789'); + $this->setChecksum('gtin'); + } +} diff --git a/lib/laminas/laminas-validator/src/Barcode/Gtin14.php b/lib/laminas/laminas-validator/src/Barcode/Gtin14.php new file mode 100644 index 000000000..bd0538c28 --- /dev/null +++ b/lib/laminas/laminas-validator/src/Barcode/Gtin14.php @@ -0,0 +1,22 @@ +setLength(14); + $this->setCharacters('0123456789'); + $this->setChecksum('gtin'); + } +} diff --git a/lib/laminas/laminas-validator/src/Barcode/Identcode.php b/lib/laminas/laminas-validator/src/Barcode/Identcode.php new file mode 100644 index 000000000..8949ec93c --- /dev/null +++ b/lib/laminas/laminas-validator/src/Barcode/Identcode.php @@ -0,0 +1,40 @@ +setLength(12); + $this->setCharacters('0123456789'); + $this->setChecksum('identcode'); + } +} diff --git a/lib/laminas/laminas-validator/src/Barcode/Intelligentmail.php b/lib/laminas/laminas-validator/src/Barcode/Intelligentmail.php new file mode 100644 index 000000000..ea13b559b --- /dev/null +++ b/lib/laminas/laminas-validator/src/Barcode/Intelligentmail.php @@ -0,0 +1,24 @@ +setLength([20, 25, 29, 31]); + $this->setCharacters('0123456789'); + $this->useChecksum(false); + } +} diff --git a/lib/laminas/laminas-validator/src/Barcode/Issn.php b/lib/laminas/laminas-validator/src/Barcode/Issn.php new file mode 100644 index 000000000..2463944e7 --- /dev/null +++ b/lib/laminas/laminas-validator/src/Barcode/Issn.php @@ -0,0 +1,89 @@ +setLength([8, 13]); + $this->setCharacters('0123456789X'); + $this->setChecksum('gtin'); + } + + /** + * Allows X on length of 8 chars + * + * @param string $value The barcode to check for allowed characters + * @return bool + */ + public function hasValidCharacters($value) + { + if (strlen($value) != 8) { + if (strpos($value, 'X') !== false) { + return false; + } + } + + return parent::hasValidCharacters($value); + } + + /** + * Validates the checksum + * + * @param string $value The barcode to check the checksum for + * @return bool + */ + public function hasValidChecksum($value) + { + if (strlen($value) == 8) { + $this->setChecksum('issn'); + } else { + $this->setChecksum('gtin'); + } + + return parent::hasValidChecksum($value); + } + + /** + * Validates the checksum () + * ISSN implementation (reversed mod11) + * + * @param string $value The barcode to validate + * @return bool + */ + protected function issn($value) + { + $checksum = substr($value, -1, 1); + $values = str_split(substr($value, 0, -1)); + $check = 0; + $multi = 8; + foreach ($values as $token) { + if ($token == 'X') { + $token = 10; + } + + $check += $token * $multi; + --$multi; + } + + $check %= 11; + $check = $check === 0 ? 0 : 11 - $check; + if ($check == $checksum) { + return true; + } elseif (($check == 10) && ($checksum == 'X')) { + return true; + } + + return false; + } +} diff --git a/lib/laminas/laminas-validator/src/Barcode/Itf14.php b/lib/laminas/laminas-validator/src/Barcode/Itf14.php new file mode 100644 index 000000000..d7b196c34 --- /dev/null +++ b/lib/laminas/laminas-validator/src/Barcode/Itf14.php @@ -0,0 +1,22 @@ +setLength(14); + $this->setCharacters('0123456789'); + $this->setChecksum('gtin'); + } +} diff --git a/lib/laminas/laminas-validator/src/Barcode/Leitcode.php b/lib/laminas/laminas-validator/src/Barcode/Leitcode.php new file mode 100644 index 000000000..4bd641687 --- /dev/null +++ b/lib/laminas/laminas-validator/src/Barcode/Leitcode.php @@ -0,0 +1,22 @@ +setLength(14); + $this->setCharacters('0123456789'); + $this->setChecksum('identcode'); + } +} diff --git a/lib/laminas/laminas-validator/src/Barcode/Planet.php b/lib/laminas/laminas-validator/src/Barcode/Planet.php new file mode 100644 index 000000000..e99572aaa --- /dev/null +++ b/lib/laminas/laminas-validator/src/Barcode/Planet.php @@ -0,0 +1,22 @@ +setLength([12, 14]); + $this->setCharacters('0123456789'); + $this->setChecksum('postnet'); + } +} diff --git a/lib/laminas/laminas-validator/src/Barcode/Postnet.php b/lib/laminas/laminas-validator/src/Barcode/Postnet.php new file mode 100644 index 000000000..e6a4a50e2 --- /dev/null +++ b/lib/laminas/laminas-validator/src/Barcode/Postnet.php @@ -0,0 +1,22 @@ +setLength([6, 7, 10, 12]); + $this->setCharacters('0123456789'); + $this->setChecksum('postnet'); + } +} diff --git a/lib/laminas/laminas-validator/src/Barcode/Royalmail.php b/lib/laminas/laminas-validator/src/Barcode/Royalmail.php new file mode 100644 index 000000000..3cc5aa7ff --- /dev/null +++ b/lib/laminas/laminas-validator/src/Barcode/Royalmail.php @@ -0,0 +1,92 @@ + 1, '1' => 1, '2' => 1, '3' => 1, '4' => 1, '5' => 1, + '6' => 2, '7' => 2, '8' => 2, '9' => 2, 'A' => 2, 'B' => 2, + 'C' => 3, 'D' => 3, 'E' => 3, 'F' => 3, 'G' => 3, 'H' => 3, + 'I' => 4, 'J' => 4, 'K' => 4, 'L' => 4, 'M' => 4, 'N' => 4, + 'O' => 5, 'P' => 5, 'Q' => 5, 'R' => 5, 'S' => 5, 'T' => 5, + 'U' => 0, 'V' => 0, 'W' => 0, 'X' => 0, 'Y' => 0, 'Z' => 0, + ]; + + protected $columns = [ + '0' => 1, '1' => 2, '2' => 3, '3' => 4, '4' => 5, '5' => 0, + '6' => 1, '7' => 2, '8' => 3, '9' => 4, 'A' => 5, 'B' => 0, + 'C' => 1, 'D' => 2, 'E' => 3, 'F' => 4, 'G' => 5, 'H' => 0, + 'I' => 1, 'J' => 2, 'K' => 3, 'L' => 4, 'M' => 5, 'N' => 0, + 'O' => 1, 'P' => 2, 'Q' => 3, 'R' => 4, 'S' => 5, 'T' => 0, + 'U' => 1, 'V' => 2, 'W' => 3, 'X' => 4, 'Y' => 5, 'Z' => 0, + ]; + + /** + * Constructor for this barcode adapter + */ + public function __construct() + { + $this->setLength(-1); + $this->setCharacters('0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ'); + $this->setChecksum('royalmail'); + } + + /** + * Validates the checksum () + * + * @param string $value The barcode to validate + * @return bool + */ + protected function royalmail($value) + { + $checksum = substr($value, -1, 1); + $values = str_split(substr($value, 0, -1)); + $rowvalue = 0; + $colvalue = 0; + foreach ($values as $row) { + $rowvalue += $this->rows[$row]; + $colvalue += $this->columns[$row]; + } + + $rowvalue %= 6; + $colvalue %= 6; + + $rowchkvalue = array_keys($this->rows, $rowvalue); + $colchkvalue = array_keys($this->columns, $colvalue); + $intersect = array_intersect($rowchkvalue, $colchkvalue); + $chkvalue = current($intersect); + if ($chkvalue == $checksum) { + return true; + } + + return false; + } + + /** + * Allows start and stop tag within checked chars + * + * @param string $value The barcode to check for allowed characters + * @return bool + */ + public function hasValidCharacters($value) + { + if ($value[0] == '(') { + $value = substr($value, 1); + + if ($value[strlen($value) - 1] == ')') { + $value = substr($value, 0, -1); + } else { + return false; + } + } + + return parent::hasValidCharacters($value); + } +} diff --git a/lib/laminas/laminas-validator/src/Barcode/Sscc.php b/lib/laminas/laminas-validator/src/Barcode/Sscc.php new file mode 100644 index 000000000..efd4e6522 --- /dev/null +++ b/lib/laminas/laminas-validator/src/Barcode/Sscc.php @@ -0,0 +1,22 @@ +setLength(18); + $this->setCharacters('0123456789'); + $this->setChecksum('gtin'); + } +} diff --git a/lib/laminas/laminas-validator/src/Barcode/Upca.php b/lib/laminas/laminas-validator/src/Barcode/Upca.php new file mode 100644 index 000000000..559702429 --- /dev/null +++ b/lib/laminas/laminas-validator/src/Barcode/Upca.php @@ -0,0 +1,22 @@ +setLength(12); + $this->setCharacters('0123456789'); + $this->setChecksum('gtin'); + } +} diff --git a/lib/laminas/laminas-validator/src/Barcode/Upce.php b/lib/laminas/laminas-validator/src/Barcode/Upce.php new file mode 100644 index 000000000..9a419cc35 --- /dev/null +++ b/lib/laminas/laminas-validator/src/Barcode/Upce.php @@ -0,0 +1,39 @@ +setLength([6, 7, 8]); + $this->setCharacters('0123456789'); + $this->setChecksum('gtin'); + } + + /** + * Overrides parent checkLength + * + * @param string $value Value + * @return bool + */ + public function hasValidLength($value) + { + if (strlen($value) != 8) { + $this->useChecksum(false); + } else { + $this->useChecksum(true); + } + + return parent::hasValidLength($value); + } +} diff --git a/lib/laminas/laminas-validator/src/Between.php b/lib/laminas/laminas-validator/src/Between.php new file mode 100644 index 000000000..56653a430 --- /dev/null +++ b/lib/laminas/laminas-validator/src/Between.php @@ -0,0 +1,213 @@ + "The input is not between '%min%' and '%max%', inclusively", + self::NOT_BETWEEN_STRICT => "The input is not strictly between '%min%' and '%max%'", + self::VALUE_NOT_NUMERIC => "The min ('%min%') and max ('%max%') values are numeric, but the input is not", + self::VALUE_NOT_STRING => "The min ('%min%') and max ('%max%') values are non-numeric strings, " + . 'but the input is not a string', + ]; + + /** + * Additional variables available for validation failure messages + * + * @var array + */ + protected $messageVariables = [ + 'min' => ['options' => 'min'], + 'max' => ['options' => 'max'], + ]; + + /** + * Options for the between validator + * + * @var array + */ + protected $options = [ + 'inclusive' => true, // Whether to do inclusive comparisons, allowing equivalence to min and/or max + 'min' => 0, + 'max' => PHP_INT_MAX, + ]; + + /** + * Sets validator options + * Accepts the following option keys: + * 'min' => scalar, minimum border + * 'max' => scalar, maximum border + * 'inclusive' => boolean, inclusive border values + * + * @param array|Traversable $options + * + * @throws Exception\InvalidArgumentException + */ + public function __construct($options = null) + { + if ($options instanceof Traversable) { + $options = ArrayUtils::iteratorToArray($options); + } + if (! is_array($options)) { + $options = func_get_args(); + $temp['min'] = array_shift($options); + if (! empty($options)) { + $temp['max'] = array_shift($options); + } + + if (! empty($options)) { + $temp['inclusive'] = array_shift($options); + } + + $options = $temp; + } + + if (! array_key_exists('min', $options) || ! array_key_exists('max', $options)) { + throw new Exception\InvalidArgumentException("Missing option: 'min' and 'max' have to be given"); + } + + if ((isset($options['min']) && is_numeric($options['min'])) + && (isset($options['max']) && is_numeric($options['max'])) + ) { + $this->numeric = true; + } elseif ((isset($options['min']) && is_string($options['min'])) + && (isset($options['max']) && is_string($options['max'])) + ) { + $this->numeric = false; + } else { + throw new Exception\InvalidArgumentException( + "Invalid options: 'min' and 'max' should be of the same scalar type" + ); + } + + parent::__construct($options); + } + + /** + * Returns the min option + * + * @return mixed + */ + public function getMin() + { + return $this->options['min']; + } + + /** + * Sets the min option + * + * @param mixed $min + * @return $this Provides a fluent interface + */ + public function setMin($min) + { + $this->options['min'] = $min; + return $this; + } + + /** + * Returns the max option + * + * @return mixed + */ + public function getMax() + { + return $this->options['max']; + } + + /** + * Sets the max option + * + * @param mixed $max + * @return $this Provides a fluent interface + */ + public function setMax($max) + { + $this->options['max'] = $max; + return $this; + } + + /** + * Returns the inclusive option + * + * @return bool + */ + public function getInclusive() + { + return $this->options['inclusive']; + } + + /** + * Sets the inclusive option + * + * @param bool $inclusive + * @return $this Provides a fluent interface + */ + public function setInclusive($inclusive) + { + $this->options['inclusive'] = $inclusive; + return $this; + } + + /** + * Returns true if and only if $value is between min and max options, inclusively + * if inclusive option is true. + * + * @param mixed $value + * @return bool + */ + public function isValid($value) + { + $this->setValue($value); + + if ($this->numeric && ! is_numeric($value)) { + $this->error(self::VALUE_NOT_NUMERIC); + return false; + } + if (! $this->numeric && ! is_string($value)) { + $this->error(self::VALUE_NOT_STRING); + return false; + } + + if ($this->getInclusive()) { + if ($this->getMin() > $value || $value > $this->getMax()) { + $this->error(self::NOT_BETWEEN); + return false; + } + } else { + if ($this->getMin() >= $value || $value >= $this->getMax()) { + $this->error(self::NOT_BETWEEN_STRICT); + return false; + } + } + + return true; + } +} diff --git a/lib/laminas/laminas-validator/src/Bitwise.php b/lib/laminas/laminas-validator/src/Bitwise.php new file mode 100644 index 000000000..2def3f024 --- /dev/null +++ b/lib/laminas/laminas-validator/src/Bitwise.php @@ -0,0 +1,191 @@ + "The input has no common bit set with '%control%'", + self::NOT_AND_STRICT => "The input doesn't have the same bits set as '%control%'", + self::NOT_XOR => "The input has common bit set with '%control%'", + ]; + + /** + * Additional variables available for validation failure messages + * + * @var array + */ + protected $messageVariables = [ + 'control' => 'control', + ]; + + /** + * @var integer + */ + protected $operator; + + /** + * @var boolean + */ + protected $strict = false; + + /** + * Sets validator options + * Accepts the following option keys: + * 'control' => integer + * 'operator' => + * 'strict' => boolean + * + * @param array|Traversable $options + */ + public function __construct($options = null) + { + if ($options instanceof Traversable) { + $options = iterator_to_array($options); + } + + if (! is_array($options)) { + $options = func_get_args(); + + $temp['control'] = array_shift($options); + + if (! empty($options)) { + $temp['operator'] = array_shift($options); + } + + if (! empty($options)) { + $temp['strict'] = array_shift($options); + } + + $options = $temp; + } + + parent::__construct($options); + } + + /** + * Returns the control parameter. + * + * @return integer + */ + public function getControl() + { + return $this->control; + } + + /** + * Returns the operator parameter. + * + * @return string + */ + public function getOperator() + { + return $this->operator; + } + + /** + * Returns the strict parameter. + * + * @return boolean + */ + public function getStrict() + { + return $this->strict; + } + + /** + * Returns true if and only if $value is between min and max options, inclusively + * if inclusive option is true. + * + * @param mixed $value + * @return bool + */ + public function isValid($value) + { + $this->setValue($value); + + if (self::OP_AND === $this->operator) { + if ($this->strict) { + // All the bits set in value must be set in control + $this->error(self::NOT_AND_STRICT); + + return (bool) (($this->control & $value) == $value); + } else { + // At least one of the bits must be common between value and control + $this->error(self::NOT_AND); + + return (bool) ($this->control & $value); + } + } elseif (self::OP_XOR === $this->operator) { + $this->error(self::NOT_XOR); + + return (bool) (($this->control ^ $value) === ($this->control | $value)); + } + + return false; + } + + /** + * Sets the control parameter. + * + * @param integer $control + * @return $this + */ + public function setControl($control) + { + $this->control = (int) $control; + + return $this; + } + + /** + * Sets the operator parameter. + * + * @param string $operator + * @return $this + */ + public function setOperator($operator) + { + $this->operator = $operator; + + return $this; + } + + /** + * Sets the strict parameter. + * + * @param boolean $strict + * @return $this + */ + public function setStrict($strict) + { + $this->strict = (bool) $strict; + + return $this; + } +} diff --git a/lib/laminas/laminas-validator/src/Callback.php b/lib/laminas/laminas-validator/src/Callback.php new file mode 100644 index 000000000..9256cf815 --- /dev/null +++ b/lib/laminas/laminas-validator/src/Callback.php @@ -0,0 +1,149 @@ + 'The input is not valid', + self::INVALID_CALLBACK => 'An exception has been raised within the callback', + ]; + + /** + * Default options to set for the validator + * + * @var mixed + */ + protected $options = [ + 'callback' => null, // Callback in a call_user_func format, string || array + 'callbackOptions' => [], // Options for the callback + ]; + + /** + * Constructor + * + * @param array|callable $options + */ + public function __construct($options = null) + { + if (is_callable($options)) { + $options = ['callback' => $options]; + } + + parent::__construct($options); + } + + /** + * Returns the set callback + * + * @return mixed + */ + public function getCallback() + { + return $this->options['callback']; + } + + /** + * Sets the callback + * + * @param string|array|callable $callback + * @return $this Provides a fluent interface + * @throws Exception\InvalidArgumentException + */ + public function setCallback($callback) + { + if (! is_callable($callback)) { + throw new Exception\InvalidArgumentException('Invalid callback given'); + } + + $this->options['callback'] = $callback; + return $this; + } + + /** + * Returns the set options for the callback + * + * @return mixed + */ + public function getCallbackOptions() + { + return $this->options['callbackOptions']; + } + + /** + * Sets options for the callback + * + * @param mixed $options + * @return $this Provides a fluent interface + */ + public function setCallbackOptions($options) + { + $this->options['callbackOptions'] = (array) $options; + return $this; + } + + /** + * Returns true if and only if the set callback returns + * for the provided $value + * + * @param mixed $value + * @param mixed $context Additional context to provide to the callback + * @return bool + * @throws Exception\InvalidArgumentException + */ + public function isValid($value, $context = null) + { + $this->setValue($value); + + $options = $this->getCallbackOptions(); + $callback = $this->getCallback(); + if (empty($callback)) { + throw new Exception\InvalidArgumentException('No callback given'); + } + + $args = [$value]; + if (empty($options) && ! empty($context)) { + $args[] = $context; + } + if (! empty($options) && empty($context)) { + $args = array_merge($args, $options); + } + if (! empty($options) && ! empty($context)) { + $args[] = $context; + $args = array_merge($args, $options); + } + + try { + if (! call_user_func_array($callback, $args)) { + $this->error(self::INVALID_VALUE); + return false; + } + } catch (\Exception $e) { + $this->error(self::INVALID_CALLBACK); + return false; + } + + return true; + } +} diff --git a/lib/laminas/laminas-validator/src/ConfigProvider.php b/lib/laminas/laminas-validator/src/ConfigProvider.php new file mode 100644 index 000000000..445303a87 --- /dev/null +++ b/lib/laminas/laminas-validator/src/ConfigProvider.php @@ -0,0 +1,44 @@ + $this->getDependencyConfig(), + ]; + } + + /** + * Return dependency mappings for this component. + * + * @return array + */ + public function getDependencyConfig() + { + return [ + 'aliases' => [ + 'ValidatorManager' => ValidatorPluginManager::class, + + // Legacy Zend Framework aliases + \Zend\Validator\ValidatorPluginManager::class => ValidatorPluginManager::class, + ], + 'factories' => [ + ValidatorPluginManager::class => ValidatorPluginManagerFactory::class, + ], + ]; + } +} diff --git a/lib/laminas/laminas-validator/src/CreditCard.php b/lib/laminas/laminas-validator/src/CreditCard.php new file mode 100644 index 000000000..1a0477681 --- /dev/null +++ b/lib/laminas/laminas-validator/src/CreditCard.php @@ -0,0 +1,332 @@ + 'The input seems to contain an invalid checksum', + self::CONTENT => 'The input must contain only digits', + self::INVALID => 'Invalid type given. String expected', + self::LENGTH => 'The input contains an invalid amount of digits', + self::PREFIX => 'The input is not from an allowed institute', + self::SERVICE => 'The input seems to be an invalid credit card number', + self::SERVICEFAILURE => 'An exception has been raised while validating the input', + ]; + + /** + * List of CCV names + * + * @var array + */ + protected $cardName = [ + 0 => self::AMERICAN_EXPRESS, + 1 => self::DINERS_CLUB, + 2 => self::DINERS_CLUB_US, + 3 => self::DISCOVER, + 4 => self::JCB, + 5 => self::LASER, + 6 => self::MAESTRO, + 7 => self::MASTERCARD, + 8 => self::SOLO, + 9 => self::UNIONPAY, + 10 => self::VISA, + 11 => self::MIR, + ]; + + /** + * List of allowed CCV lengths + * + * @var array + */ + protected $cardLength = [ + self::AMERICAN_EXPRESS => [15], + self::DINERS_CLUB => [14], + self::DINERS_CLUB_US => [16], + self::DISCOVER => [16, 19], + self::JCB => [15, 16], + self::LASER => [16, 17, 18, 19], + self::MAESTRO => [12, 13, 14, 15, 16, 17, 18, 19], + self::MASTERCARD => [16], + self::SOLO => [16, 18, 19], + self::UNIONPAY => [16, 17, 18, 19], + self::VISA => [13, 16, 19], + self::MIR => [13, 16], + ]; + + /** + * List of accepted CCV provider tags + * + * @var array + */ + protected $cardType = [ + self::AMERICAN_EXPRESS => ['34', '37'], + self::DINERS_CLUB => ['300', '301', '302', '303', '304', '305', '36'], + self::DINERS_CLUB_US => ['54', '55'], + self::DISCOVER => ['6011', '622126', '622127', '622128', '622129', '62213', + '62214', '62215', '62216', '62217', '62218', '62219', + '6222', '6223', '6224', '6225', '6226', '6227', '6228', + '62290', '62291', '622920', '622921', '622922', '622923', + '622924', '622925', '644', '645', '646', '647', '648', + '649', '65'], + self::JCB => ['1800', '2131', '3528', '3529', '353', '354', '355', '356', '357', '358'], + self::LASER => ['6304', '6706', '6771', '6709'], + self::MAESTRO => ['5018', '5020', '5038', '6304', '6759', '6761', '6762', '6763', + '6764', '6765', '6766', '6772'], + self::MASTERCARD => ['2221', '2222', '2223', '2224', '2225', '2226', '2227', '2228', '2229', + '223', '224', '225', '226', '227', '228', '229', + '23', '24', '25', '26', '271', '2720', + '51', '52', '53', '54', '55'], + self::SOLO => ['6334', '6767'], + self::UNIONPAY => ['622126', '622127', '622128', '622129', '62213', '62214', + '62215', '62216', '62217', '62218', '62219', '6222', '6223', + '6224', '6225', '6226', '6227', '6228', '62290', '62291', + '622920', '622921', '622922', '622923', '622924', '622925'], + self::VISA => ['4'], + self::MIR => ['2200', '2201', '2202', '2203', '2204'], + ]; + + /** + * Options for this validator + * + * @var array + */ + protected $options = [ + 'service' => null, // Service callback for additional validation + 'type' => [], // CCIs which are accepted by validation + ]; + + /** + * Constructor + * + * @param string|array|Traversable $options OPTIONAL Type of CCI to allow + */ + public function __construct($options = []) + { + if ($options instanceof Traversable) { + $options = ArrayUtils::iteratorToArray($options); + } elseif (! is_array($options)) { + $options = func_get_args(); + $temp['type'] = array_shift($options); + if (! empty($options)) { + $temp['service'] = array_shift($options); + } + + $options = $temp; + } + + if (! array_key_exists('type', $options)) { + $options['type'] = self::ALL; + } + + $this->setType($options['type']); + unset($options['type']); + + if (array_key_exists('service', $options)) { + $this->setService($options['service']); + unset($options['service']); + } + + parent::__construct($options); + } + + /** + * Returns a list of accepted CCIs + * + * @return array + */ + public function getType() + { + return $this->options['type']; + } + + /** + * Sets CCIs which are accepted by validation + * + * @param string|array $type Type to allow for validation + * @return CreditCard Provides a fluid interface + */ + public function setType($type) + { + $this->options['type'] = []; + return $this->addType($type); + } + + /** + * Adds a CCI to be accepted by validation + * + * @param string|array $type Type to allow for validation + * @return $this Provides a fluid interface + */ + public function addType($type) + { + if (is_string($type)) { + $type = [$type]; + } + + foreach ($type as $typ) { + if ($typ == self::ALL) { + $this->options['type'] = array_keys($this->cardLength); + continue; + } + + if (in_array($typ, $this->options['type'])) { + continue; + } + + $constant = 'static::' . strtoupper($typ); + if (! defined($constant) || in_array(constant($constant), $this->options['type'])) { + continue; + } + $this->options['type'][] = constant($constant); + } + + return $this; + } + + /** + * Returns the actual set service + * + * @return callable + */ + public function getService() + { + return $this->options['service']; + } + + /** + * Sets a new callback for service validation + * + * @param callable $service + * @return $this + * @throws Exception\InvalidArgumentException on invalid service callback + */ + public function setService($service) + { + if (! is_callable($service)) { + throw new Exception\InvalidArgumentException('Invalid callback given'); + } + + $this->options['service'] = $service; + return $this; + } + + /** + * Returns true if and only if $value follows the Luhn algorithm (mod-10 checksum) + * + * @param string $value + * @return bool + */ + public function isValid($value) + { + $this->setValue($value); + + if (! is_string($value)) { + $this->error(self::INVALID, $value); + return false; + } + + if (! ctype_digit($value)) { + $this->error(self::CONTENT, $value); + return false; + } + + $length = strlen($value); + $types = $this->getType(); + $foundp = false; + $foundl = false; + foreach ($types as $type) { + foreach ($this->cardType[$type] as $prefix) { + if (0 === strpos($value, $prefix)) { + $foundp = true; + if (in_array($length, $this->cardLength[$type])) { + $foundl = true; + break 2; + } + } + } + } + + if ($foundp == false) { + $this->error(self::PREFIX, $value); + return false; + } + + if ($foundl == false) { + $this->error(self::LENGTH, $value); + return false; + } + + $sum = 0; + $weight = 2; + + for ($i = $length - 2; $i >= 0; $i--) { + $digit = $weight * $value[$i]; + $sum += floor($digit / 10) + $digit % 10; + $weight = $weight % 2 + 1; + } + + if ((10 - $sum % 10) % 10 != $value[$length - 1]) { + $this->error(self::CHECKSUM, $value); + return false; + } + + $service = $this->getService(); + if (! empty($service)) { + try { + $callback = new Callback($service); + $callback->setOptions($this->getType()); + if (! $callback->isValid($value)) { + $this->error(self::SERVICE, $value); + return false; + } + } catch (\Exception $e) { + $this->error(self::SERVICEFAILURE, $value); + return false; + } + } + + return true; + } +} diff --git a/lib/laminas/laminas-validator/src/Csrf.php b/lib/laminas/laminas-validator/src/Csrf.php new file mode 100644 index 000000000..f1ba847df --- /dev/null +++ b/lib/laminas/laminas-validator/src/Csrf.php @@ -0,0 +1,377 @@ + 'The form submitted did not originate from the expected site', + ]; + + /** + * Actual hash used. + * + * @var mixed + */ + protected $hash; + + /** + * Static cache of the session names to generated hashes + * @todo unused, left here to avoid BC breaks + * + * @var array + */ + protected static $hashCache; + + /** + * Name of CSRF element (used to create non-colliding hashes) + * + * @var string + */ + protected $name = 'csrf'; + + /** + * Salt for CSRF token + * @var string + */ + protected $salt = 'salt'; + + /** + * @var SessionContainer + */ + protected $session; + + /** + * TTL for CSRF token + * @var int|null + */ + protected $timeout = 300; + + /** + * Constructor + * + * @param array|Traversable $options + */ + public function __construct($options = []) + { + parent::__construct($options); + + if ($options instanceof Traversable) { + $options = ArrayUtils::iteratorToArray($options); + } + + if (! is_array($options)) { + $options = (array) $options; + } + + foreach ($options as $key => $value) { + switch (strtolower($key)) { + case 'name': + $this->setName($value); + break; + case 'salt': + $this->setSalt($value); + break; + case 'session': + $this->setSession($value); + break; + case 'timeout': + $this->setTimeout($value); + break; + default: + // ignore unknown options + break; + } + } + } + + /** + * Does the provided token match the one generated? + * + * @param string $value + * @param mixed $context + * @return bool + */ + public function isValid($value, $context = null) + { + if (! is_string($value)) { + return false; + } + + $this->setValue($value); + + $tokenId = $this->getTokenIdFromHash($value); + $hash = $this->getValidationToken($tokenId); + + $tokenFromValue = $this->getTokenFromHash($value); + $tokenFromHash = $this->getTokenFromHash($hash); + + if (! $tokenFromValue || ! $tokenFromHash || ($tokenFromValue !== $tokenFromHash)) { + $this->error(self::NOT_SAME); + return false; + } + + return true; + } + + /** + * Set CSRF name + * + * @param string $name + * @return $this + */ + public function setName($name) + { + $this->name = (string) $name; + return $this; + } + + /** + * Get CSRF name + * + * @return string + */ + public function getName() + { + return $this->name; + } + + /** + * Set session container + * + * @param SessionContainer $session + * @return $this + */ + public function setSession(SessionContainer $session) + { + $this->session = $session; + if ($this->hash) { + $this->initCsrfToken(); + } + return $this; + } + + /** + * Get session container + * + * Instantiate session container if none currently exists + * + * @return SessionContainer + */ + public function getSession() + { + if (null === $this->session) { + // Using fully qualified name, to ensure polyfill class alias is used + $this->session = new SessionContainer($this->getSessionName()); + } + return $this->session; + } + + /** + * Salt for CSRF token + * + * @param string $salt + * @return $this + */ + public function setSalt($salt) + { + $this->salt = (string) $salt; + return $this; + } + + /** + * Retrieve salt for CSRF token + * + * @return string + */ + public function getSalt() + { + return $this->salt; + } + + /** + * Retrieve CSRF token + * + * If no CSRF token currently exists, or should be regenerated, + * generates one. + * + * @param bool $regenerate default false + * @return string + */ + public function getHash($regenerate = false) + { + if ((null === $this->hash) || $regenerate) { + $this->generateHash(); + } + return $this->hash; + } + + /** + * Get session namespace for CSRF token + * + * Generates a session namespace based on salt, element name, and class. + * + * @return string + */ + public function getSessionName() + { + return str_replace('\\', '_', __CLASS__) . '_' + . $this->getSalt() . '_' + . strtr($this->getName(), ['[' => '_', ']' => '']); + } + + /** + * Set timeout for CSRF session token + * + * @param int|null $ttl + * @return $this + */ + public function setTimeout($ttl) + { + $this->timeout = $ttl !== null ? (int) $ttl : null; + return $this; + } + + /** + * Get CSRF session token timeout + * + * @return int + */ + public function getTimeout() + { + return $this->timeout; + } + + /** + * Initialize CSRF token in session + * + * @return void + */ + protected function initCsrfToken() + { + $session = $this->getSession(); + $timeout = $this->getTimeout(); + if (null !== $timeout) { + $session->setExpirationSeconds($timeout); + } + + $hash = $this->getHash(); + $token = $this->getTokenFromHash($hash); + $tokenId = $this->getTokenIdFromHash($hash); + + if (! $session->tokenList) { + $session->tokenList = []; + } + $session->tokenList[$tokenId] = $token; + $session->hash = $hash; // @todo remove this, left for BC + } + + /** + * Generate CSRF token + * + * Generates CSRF token and stores both in {@link $hash} and element + * value. + * + * @return void + */ + protected function generateHash() + { + $token = md5($this->getSalt() . Rand::getBytes(32) . $this->getName()); + + $this->hash = $this->formatHash($token, $this->generateTokenId()); + + $this->setValue($this->hash); + $this->initCsrfToken(); + } + + /** + * @return string + */ + protected function generateTokenId() + { + return md5(Rand::getBytes(32)); + } + + /** + * Get validation token + * + * Retrieve token from session, if it exists. + * + * @param string $tokenId + * @return null|string + */ + protected function getValidationToken($tokenId = null) + { + $session = $this->getSession(); + + /** + * if no tokenId is passed we revert to the old behaviour + * @todo remove, here for BC + */ + if (! $tokenId && isset($session->hash)) { + return $session->hash; + } + + if ($tokenId && isset($session->tokenList[$tokenId])) { + return $this->formatHash($session->tokenList[$tokenId], $tokenId); + } + + return; + } + + /** + * @param $token + * @param $tokenId + * @return string + */ + protected function formatHash($token, $tokenId) + { + return sprintf('%s-%s', $token, $tokenId); + } + + /** + * @param $hash + * @return string + */ + protected function getTokenFromHash($hash) + { + $data = explode('-', $hash); + return $data[0] ?: null; + } + + /** + * @param $hash + * @return string + */ + protected function getTokenIdFromHash($hash) + { + $data = explode('-', $hash); + + if (! isset($data[1])) { + return; + } + + return $data[1]; + } +} diff --git a/lib/laminas/laminas-validator/src/Date.php b/lib/laminas/laminas-validator/src/Date.php new file mode 100644 index 000000000..35f281862 --- /dev/null +++ b/lib/laminas/laminas-validator/src/Date.php @@ -0,0 +1,225 @@ + 'Invalid type given. String, integer, array or DateTime expected', + self::INVALID_DATE => 'The input does not appear to be a valid date', + self::FALSEFORMAT => "The input does not fit the date format '%format%'", + ]; + + /** + * @var array + */ + protected $messageVariables = [ + 'format' => 'format', + ]; + + /** + * @var string + */ + protected $format = self::FORMAT_DEFAULT; + + /** + * @var bool + */ + protected $strict = false; + + /** + * Sets validator options + * + * @param string|array|Traversable $options OPTIONAL + */ + public function __construct($options = []) + { + if ($options instanceof Traversable) { + $options = iterator_to_array($options); + } elseif (! is_array($options)) { + $options = func_get_args(); + $temp['format'] = array_shift($options); + $options = $temp; + } + + parent::__construct($options); + } + + /** + * Returns the format option + * + * @return string|null + */ + public function getFormat() + { + return $this->format; + } + + /** + * Sets the format option + * + * Format cannot be null. It will always default to 'Y-m-d', even + * if null is provided. + * + * @param string $format + * @return $this provides a fluent interface + * @todo validate the format + */ + public function setFormat($format = self::FORMAT_DEFAULT) + { + $this->format = empty($format) ? self::FORMAT_DEFAULT : $format; + return $this; + } + + public function setStrict(bool $strict) : self + { + $this->strict = $strict; + return $this; + } + + public function isStrict() : bool + { + return $this->strict; + } + + /** + * Returns true if $value is a DateTime instance or can be converted into one. + * + * @param string|array|int|DateTime $value + * @return bool + */ + public function isValid($value) + { + $this->setValue($value); + + $date = $this->convertToDateTime($value); + if (! $date) { + $this->error(self::INVALID_DATE); + return false; + } + + if ($this->isStrict() && $date->format($this->getFormat()) !== $value) { + $this->error(self::FALSEFORMAT); + return false; + } + + return true; + } + + /** + * Attempts to convert an int, string, or array to a DateTime object + * + * @param string|int|array $param + * @param bool $addErrors + * @return bool|DateTime + */ + protected function convertToDateTime($param, $addErrors = true) + { + if ($param instanceof DateTime || $param instanceof DateTimeImmutable) { + return $param; + } + + $type = gettype($param); + if (! in_array($type, ['string', 'integer', 'double', 'array'])) { + if ($addErrors) { + $this->error(self::INVALID); + } + return false; + } + + $convertMethod = 'convert' . ucfirst($type); + return $this->{$convertMethod}($param, $addErrors); + } + + /** + * Attempts to convert an integer into a DateTime object + * + * @param integer $value + * @return bool|DateTime + */ + protected function convertInteger($value) + { + return date_create("@$value"); + } + + /** + * Attempts to convert an double into a DateTime object + * + * @param double $value + * @return bool|DateTime + */ + protected function convertDouble($value) + { + return DateTime::createFromFormat('U', $value); + } + + /** + * Attempts to convert a string into a DateTime object + * + * @param string $value + * @param bool $addErrors + * @return bool|DateTime + */ + protected function convertString($value, $addErrors = true) + { + $date = DateTime::createFromFormat($this->format, $value); + + // Invalid dates can show up as warnings (ie. "2007-02-99") + // and still return a DateTime object. + $errors = DateTime::getLastErrors(); + if ($errors['warning_count'] > 0) { + if ($addErrors) { + $this->error(self::FALSEFORMAT); + } + return false; + } + + return $date; + } + + /** + * Implodes the array into a string and proxies to {@link convertString()}. + * + * @param array $value + * @param bool $addErrors + * @return bool|DateTime + * @todo enhance the implosion + */ + protected function convertArray(array $value, $addErrors = true) + { + return $this->convertString(implode('-', $value), $addErrors); + } +} diff --git a/lib/laminas/laminas-validator/src/DateStep.php b/lib/laminas/laminas-validator/src/DateStep.php new file mode 100644 index 000000000..93ad96b01 --- /dev/null +++ b/lib/laminas/laminas-validator/src/DateStep.php @@ -0,0 +1,478 @@ + 'Invalid type given. String, integer, array or DateTime expected', + self::INVALID_DATE => 'The input does not appear to be a valid date', + self::FALSEFORMAT => "The input does not fit the date format '%format%'", + self::NOT_STEP => 'The input is not a valid step', + ]; + + /** + * Optional base date value + * + * @var string|int|\DateTime + */ + protected $baseValue = '1970-01-01T00:00:00Z'; + + /** + * Date step interval (defaults to 1 day). + * Uses the DateInterval specification. + * + * @var DateInterval + */ + protected $step; + + /** + * Optional timezone to be used when the baseValue + * and validation values do not contain timezone info + * + * @var DateTimeZone + */ + protected $timezone; + + /** + * Set default options for this instance + * + * @param array $options + */ + public function __construct($options = []) + { + if ($options instanceof Traversable) { + $options = ArrayUtils::iteratorToArray($options); + } elseif (! is_array($options)) { + $options = func_get_args(); + $temp['baseValue'] = array_shift($options); + if (! empty($options)) { + $temp['step'] = array_shift($options); + } + if (! empty($options)) { + $temp['format'] = array_shift($options); + } + if (! empty($options)) { + $temp['timezone'] = array_shift($options); + } + + $options = $temp; + } + + if (! isset($options['step'])) { + $options['step'] = new DateInterval('P1D'); + } + if (! isset($options['timezone'])) { + $options['timezone'] = new DateTimeZone(date_default_timezone_get()); + } + + parent::__construct($options); + } + + /** + * Sets the base value from which the step should be computed + * + * @param string|int|\DateTime $baseValue + * @return $this + */ + public function setBaseValue($baseValue) + { + $this->baseValue = $baseValue; + return $this; + } + + /** + * Returns the base value from which the step should be computed + * + * @return string|int|\DateTime + */ + public function getBaseValue() + { + return $this->baseValue; + } + + /** + * Sets the step date interval + * + * @param DateInterval $step + * @return $this + */ + public function setStep(DateInterval $step) + { + $this->step = $step; + return $this; + } + + /** + * Returns the step date interval + * + * @return DateInterval + */ + public function getStep() + { + return $this->step; + } + + /** + * Returns the timezone option + * + * @return DateTimeZone + */ + public function getTimezone() + { + return $this->timezone; + } + + /** + * Sets the timezone option + * + * @param DateTimeZone $timezone + * @return $this + */ + public function setTimezone(DateTimeZone $timezone) + { + $this->timezone = $timezone; + return $this; + } + + /** + * Supports formats with ISO week (W) definitions + * + * @see Date::convertString() + */ + protected function convertString($value, $addErrors = true) + { + // Custom week format support + if (strpos($this->format, 'Y-\WW') === 0 + && preg_match('/^([0-9]{4})\-W([0-9]{2})/', $value, $matches) + ) { + $date = new DateTime(); + $date->setISODate($matches[1], $matches[2]); + } else { + $date = DateTime::createFromFormat($this->format, $value, new DateTimeZone('UTC')); + } + + // Invalid dates can show up as warnings (ie. "2007-02-99") + // and still return a DateTime object. + $errors = DateTime::getLastErrors(); + if ($errors['warning_count'] > 0) { + if ($addErrors) { + $this->error(self::FALSEFORMAT); + } + return false; + } + + return $date; + } + + /** + * Returns true if a date is within a valid step + * + * @param string|int|\DateTime $value + * @return bool + * @throws Exception\InvalidArgumentException + */ + public function isValid($value) + { + if (! parent::isValid($value)) { + return false; + } + + $valueDate = $this->convertToDateTime($value, false); // avoid duplicate errors + $baseDate = $this->convertToDateTime($this->baseValue, false); + $step = $this->getStep(); + + // Same date? + if ($valueDate == $baseDate) { + return true; + } + + // Optimization for simple intervals. + // Handle intervals of just one date or time unit. + $intervalParts = explode('|', $step->format('%y|%m|%d|%h|%i|%s')); + $partCounts = array_count_values($intervalParts); + + $unitKeys = ['years', 'months', 'days', 'hours', 'minutes', 'seconds']; + $intervalParts = array_combine($unitKeys, $intervalParts); + + // Get absolute time difference to avoid special cases of missing/added time + $absoluteValueDate = new DateTime($valueDate->format('Y-m-d H:i:s'), new DateTimeZone('UTC')); + $absoluteBaseDate = new DateTime($baseDate->format('Y-m-d H:i:s'), new DateTimeZone('UTC')); + + $timeDiff = $absoluteValueDate->diff($absoluteBaseDate, 1); + $diffParts = array_combine($unitKeys, explode('|', $timeDiff->format('%y|%m|%d|%h|%i|%s'))); + + if (5 === $partCounts['0']) { + // Find the unit with the non-zero interval + $intervalUnit = null; + $stepValue = null; + foreach ($intervalParts as $key => $value) { + if (0 != $value) { + $intervalUnit = $key; + $stepValue = (int) $value; + break; + } + } + + // Check date units + if (in_array($intervalUnit, ['years', 'months', 'days'])) { + switch ($intervalUnit) { + case 'years': + if (0 == $diffParts['months'] && 0 == $diffParts['days'] + && 0 == $diffParts['hours'] && 0 == $diffParts['minutes'] + && 0 == $diffParts['seconds'] + ) { + if (($diffParts['years'] % $stepValue) === 0) { + return true; + } + } + break; + case 'months': + if (0 == $diffParts['days'] && 0 == $diffParts['hours'] + && 0 == $diffParts['minutes'] && 0 == $diffParts['seconds'] + ) { + $months = ($diffParts['years'] * 12) + $diffParts['months']; + if (($months % $stepValue) === 0) { + return true; + } + } + break; + case 'days': + if (0 == $diffParts['hours'] && 0 == $diffParts['minutes'] + && 0 == $diffParts['seconds'] + ) { + $days = $timeDiff->format('%a'); // Total days + if (($days % $stepValue) === 0) { + return true; + } + } + break; + } + $this->error(self::NOT_STEP); + return false; + } + + // Check time units + if (in_array($intervalUnit, ['hours', 'minutes', 'seconds'])) { + // Simple test if $stepValue is 1. + if (1 == $stepValue) { + if ('hours' === $intervalUnit + && 0 == $diffParts['minutes'] && 0 == $diffParts['seconds'] + ) { + return true; + } elseif ('minutes' === $intervalUnit && 0 == $diffParts['seconds']) { + return true; + } elseif ('seconds' === $intervalUnit) { + return true; + } + + $this->error(self::NOT_STEP); + + return false; + } + + // Simple test for same day, when using default baseDate + if ($baseDate->format('Y-m-d') == $valueDate->format('Y-m-d') + && $baseDate->format('Y-m-d') == '1970-01-01' + ) { + switch ($intervalUnit) { + case 'hours': + if (0 == $diffParts['minutes'] && 0 == $diffParts['seconds']) { + if (($diffParts['hours'] % $stepValue) === 0) { + return true; + } + } + break; + case 'minutes': + if (0 == $diffParts['seconds']) { + $minutes = ($diffParts['hours'] * 60) + $diffParts['minutes']; + if (($minutes % $stepValue) === 0) { + return true; + } + } + break; + case 'seconds': + $seconds = ($diffParts['hours'] * 60 * 60) + + ($diffParts['minutes'] * 60) + + $diffParts['seconds']; + if (($seconds % $stepValue) === 0) { + return true; + } + break; + } + $this->error(self::NOT_STEP); + return false; + } + } + } + + return $this->fallbackIncrementalIterationLogic($baseDate, $valueDate, $intervalParts, $diffParts, $step); + } + + /** + * Fall back to slower (but accurate) method for complex intervals. + * Keep adding steps to the base date until a match is found + * or until the value is exceeded. + * + * This is really slow if the interval is small, especially if the + * default base date of 1/1/1970 is used. We can skip a chunk of + * iterations by starting at the lower bound of steps needed to reach + * the target + * + * @param DateTime $baseDate + * @param DateTime $valueDate + * @param int[] $intervalParts + * @param int[] $diffParts + * @param DateInterval $step + * + * @return bool + */ + private function fallbackIncrementalIterationLogic( + DateTime $baseDate, + DateTime $valueDate, + array $intervalParts, + array $diffParts, + DateInterval $step + ) { + list($minSteps, $requiredIterations) = $this->computeMinStepAndRequiredIterations($intervalParts, $diffParts); + $minimumInterval = $this->computeMinimumInterval($intervalParts, $minSteps); + $isIncrementalStepping = $baseDate < $valueDate; + $dateModificationOperation = $isIncrementalStepping ? 'add' : 'sub'; + + for ($offsetIterations = 0; $offsetIterations < $requiredIterations; $offsetIterations += 1) { + $baseDate->{$dateModificationOperation}($minimumInterval); + } + + while (($isIncrementalStepping && $baseDate < $valueDate) + || (! $isIncrementalStepping && $baseDate > $valueDate) + ) { + $baseDate->{$dateModificationOperation}($step); + + if ($baseDate == $valueDate) { + return true; + } + } + + $this->error(self::NOT_STEP); + + return false; + } + + /** + * Computes minimum interval to use for iterations while checking steps + * + * @param int[] $intervalParts + * @param int $minSteps + * + * @return DateInterval + */ + private function computeMinimumInterval(array $intervalParts, $minSteps) + { + return new DateInterval(sprintf( + 'P%dY%dM%dDT%dH%dM%dS', + $intervalParts['years'] * $minSteps, + $intervalParts['months'] * $minSteps, + $intervalParts['days'] * $minSteps, + $intervalParts['hours'] * $minSteps, + $intervalParts['minutes'] * $minSteps, + $intervalParts['seconds'] * $minSteps + )); + } + + /** + * @param int[] $intervalParts + * @param int[] $diffParts + * + * @return int[] (ordered tuple containing minimum steps and required step iterations + */ + private function computeMinStepAndRequiredIterations(array $intervalParts, array $diffParts) + { + $minSteps = $this->computeMinSteps($intervalParts, $diffParts); + + // If we use PHP_INT_MAX DateInterval::__construct falls over with a bad format error + // before we reach the max on 64 bit machines + $maxInteger = min(pow(2, 31), PHP_INT_MAX); + // check for integer overflow and split $minimum interval if needed + $maximumInterval = max($intervalParts); + $requiredStepIterations = 1; + + if (($minSteps * $maximumInterval) > $maxInteger) { + $requiredStepIterations = ceil(($minSteps * $maximumInterval) / $maxInteger); + $minSteps = floor($minSteps / $requiredStepIterations); + } + + return [$minSteps, $minSteps ? $requiredStepIterations : 0]; + } + + /** + * Multiply the step interval by the lower bound of steps to reach the target + * + * @param int[] $intervalParts + * @param int[] $diffParts + * + * @return int + */ + private function computeMinSteps(array $intervalParts, array $diffParts) + { + $intervalMaxSeconds = $this->computeIntervalMaxSeconds($intervalParts); + + return 0 == $intervalMaxSeconds + ? 0 + : max(floor($this->computeDiffMinSeconds($diffParts) / $intervalMaxSeconds) - 1, 0); + } + + /** + * Get upper bound of the given interval in seconds + * Converts a given `$intervalParts` array into seconds + * + * @param int[] $intervalParts + * + * @return int + */ + private function computeIntervalMaxSeconds(array $intervalParts) + { + return ($intervalParts['years'] * 60 * 60 * 24 * 366) + + ($intervalParts['months'] * 60 * 60 * 24 * 31) + + ($intervalParts['days'] * 60 * 60 * 24) + + ($intervalParts['hours'] * 60 * 60) + + ($intervalParts['minutes'] * 60) + + $intervalParts['seconds']; + } + + /** + * Get lower bound of difference in secondss + * Converts a given `$diffParts` array into seconds + * + * @param int[] $diffParts + * + * @return int + */ + private function computeDiffMinSeconds(array $diffParts) + { + return ($diffParts['years'] * 60 * 60 * 24 * 365) + + ($diffParts['months'] * 60 * 60 * 24 * 28) + + ($diffParts['days'] * 60 * 60 * 24) + + ($diffParts['hours'] * 60 * 60) + + ($diffParts['minutes'] * 60) + + $diffParts['seconds']; + } +} diff --git a/lib/laminas/laminas-validator/src/Db/AbstractDb.php b/lib/laminas/laminas-validator/src/Db/AbstractDb.php new file mode 100755 index 000000000..0100e854c --- /dev/null +++ b/lib/laminas/laminas-validator/src/Db/AbstractDb.php @@ -0,0 +1,325 @@ + 'No record matching the input was found', + self::ERROR_RECORD_FOUND => 'A record matching the input was found', + ]; + + /** + * Select object to use. can be set, or will be auto-generated + * + * @var Select + */ + protected $select; + + /** + * @var string + */ + protected $schema = null; + + /** + * @var string + */ + protected $table = ''; + + /** + * @var string + */ + protected $field = ''; + + /** + * @var mixed + */ + protected $exclude = null; + + /** + * Provides basic configuration for use with Laminas\Validator\Db Validators + * Setting $exclude allows a single record to be excluded from matching. + * Exclude can either be a String containing a where clause, or an array with `field` and `value` keys + * to define the where clause added to the sql. + * A database adapter may optionally be supplied to avoid using the registered default adapter. + * + * The following option keys are supported: + * 'table' => The database table to validate against + * 'schema' => The schema keys + * 'field' => The field to check for a match + * 'exclude' => An optional where clause or field/value pair to exclude from the query + * 'adapter' => An optional database adapter to use + * + * @param array|Traversable|Select $options Options to use for this validator + * @throws \Laminas\Validator\Exception\InvalidArgumentException + */ + public function __construct($options = null) + { + parent::__construct($options); + + if ($options instanceof Select) { + $this->setSelect($options); + return; + } + + if ($options instanceof Traversable) { + $options = ArrayUtils::iteratorToArray($options); + } elseif (func_num_args() > 1) { + $options = func_get_args(); + $firstArgument = array_shift($options); + if (is_array($firstArgument)) { + $temp = ArrayUtils::iteratorToArray($firstArgument); + } else { + $temp['table'] = $firstArgument; + } + + $temp['field'] = array_shift($options); + + if (! empty($options)) { + $temp['exclude'] = array_shift($options); + } + + if (! empty($options)) { + $temp['adapter'] = array_shift($options); + } + + $options = $temp; + } + + if (! array_key_exists('table', $options) && ! array_key_exists('schema', $options)) { + throw new Exception\InvalidArgumentException('Table or Schema option missing!'); + } + + if (! array_key_exists('field', $options)) { + throw new Exception\InvalidArgumentException('Field option missing!'); + } + + if (array_key_exists('adapter', $options)) { + $this->setAdapter($options['adapter']); + } + + if (array_key_exists('exclude', $options)) { + $this->setExclude($options['exclude']); + } + + $this->setField($options['field']); + if (array_key_exists('table', $options)) { + $this->setTable($options['table']); + } + + if (array_key_exists('schema', $options)) { + $this->setSchema($options['schema']); + } + } + + /** + * Returns the set adapter + * + * @throws \Laminas\Validator\Exception\RuntimeException When no database adapter is defined + * @return DbAdapter + */ + public function getAdapter() + { + return $this->adapter; + } + + /** + * Sets a new database adapter + * + * @param DbAdapter $adapter + * @return self Provides a fluent interface + */ + public function setAdapter(DbAdapter $adapter) + { + return $this->setDbAdapter($adapter); + } + + /** + * Returns the set exclude clause + * + * @return string|array + */ + public function getExclude() + { + return $this->exclude; + } + + /** + * Sets a new exclude clause + * + * @param string|array $exclude + * @return $this Provides a fluent interface + */ + public function setExclude($exclude) + { + $this->exclude = $exclude; + $this->select = null; + return $this; + } + + /** + * Returns the set field + * + * @return string|array + */ + public function getField() + { + return $this->field; + } + + /** + * Sets a new field + * + * @param string $field + * @return $this + */ + public function setField($field) + { + $this->field = (string) $field; + $this->select = null; + return $this; + } + + /** + * Returns the set table + * + * @return string + */ + public function getTable() + { + return $this->table; + } + + /** + * Sets a new table + * + * @param string $table + * @return $this Provides a fluent interface + */ + public function setTable($table) + { + $this->table = (string) $table; + $this->select = null; + return $this; + } + + /** + * Returns the set schema + * + * @return string + */ + public function getSchema() + { + return $this->schema; + } + + /** + * Sets a new schema + * + * @param string $schema + * @return $this Provides a fluent interface + */ + public function setSchema($schema) + { + $this->schema = $schema; + $this->select = null; + return $this; + } + + /** + * Sets the select object to be used by the validator + * + * @param Select $select + * @return $this Provides a fluent interface + */ + public function setSelect(Select $select) + { + $this->select = $select; + return $this; + } + + /** + * Gets the select object to be used by the validator. + * If no select object was supplied to the constructor, + * then it will auto-generate one from the given table, + * schema, field, and adapter options. + * + * @return Select The Select object which will be used + */ + public function getSelect() + { + if ($this->select instanceof Select) { + return $this->select; + } + + // Build select object + $select = new Select(); + $tableIdentifier = new TableIdentifier($this->table, $this->schema); + $select->from($tableIdentifier)->columns([$this->field]); + $select->where->equalTo($this->field, null); + + if ($this->exclude !== null) { + if (is_array($this->exclude)) { + $select->where->notEqualTo( + $this->exclude['field'], + $this->exclude['value'] + ); + } else { + $select->where($this->exclude); + } + } + + $this->select = $select; + + return $this->select; + } + + /** + * Run query and returns matches, or null if no matches are found. + * + * @param string $value + * @return array when matches are found. + */ + protected function query($value) + { + $sql = new Sql($this->getAdapter()); + $select = $this->getSelect(); + $statement = $sql->prepareStatementForSqlObject($select); + $parameters = $statement->getParameterContainer(); + $parameters['where1'] = $value; + $result = $statement->execute(); + + return $result->current(); + } +} diff --git a/lib/laminas/laminas-validator/src/Db/NoRecordExists.php b/lib/laminas/laminas-validator/src/Db/NoRecordExists.php new file mode 100644 index 000000000..16be50739 --- /dev/null +++ b/lib/laminas/laminas-validator/src/Db/NoRecordExists.php @@ -0,0 +1,38 @@ +adapter) { + throw new Exception\RuntimeException('No database adapter present'); + } + + $valid = true; + $this->setValue($value); + + $result = $this->query($value); + if ($result) { + $valid = false; + $this->error(self::ERROR_RECORD_FOUND); + } + + return $valid; + } +} diff --git a/lib/laminas/laminas-validator/src/Db/RecordExists.php b/lib/laminas/laminas-validator/src/Db/RecordExists.php new file mode 100644 index 000000000..5bb1cc951 --- /dev/null +++ b/lib/laminas/laminas-validator/src/Db/RecordExists.php @@ -0,0 +1,38 @@ +adapter) { + throw new Exception\RuntimeException('No database adapter present'); + } + + $valid = true; + $this->setValue($value); + + $result = $this->query($value); + if (! $result) { + $valid = false; + $this->error(self::ERROR_NO_RECORD_FOUND); + } + + return $valid; + } +} diff --git a/lib/laminas/laminas-validator/src/Digits.php b/lib/laminas/laminas-validator/src/Digits.php new file mode 100644 index 000000000..5831a0fbf --- /dev/null +++ b/lib/laminas/laminas-validator/src/Digits.php @@ -0,0 +1,68 @@ + 'The input must contain only digits', + self::STRING_EMPTY => 'The input is an empty string', + self::INVALID => 'Invalid type given. String, integer or float expected', + ]; + + /** + * Returns true if and only if $value only contains digit characters + * + * @param string $value + * @return bool + */ + public function isValid($value) + { + if (! is_string($value) && ! is_int($value) && ! is_float($value)) { + $this->error(self::INVALID); + return false; + } + + $this->setValue((string) $value); + + if ('' === $this->getValue()) { + $this->error(self::STRING_EMPTY); + return false; + } + + if (null === static::$filter) { + static::$filter = new DigitsFilter(); + } + + if ($this->getValue() !== static::$filter->filter($this->getValue())) { + $this->error(self::NOT_DIGITS); + return false; + } + + return true; + } +} diff --git a/lib/laminas/laminas-validator/src/EmailAddress.php b/lib/laminas/laminas-validator/src/EmailAddress.php new file mode 100644 index 000000000..f085785ac --- /dev/null +++ b/lib/laminas/laminas-validator/src/EmailAddress.php @@ -0,0 +1,590 @@ + "Invalid type given. String expected", + self::INVALID_FORMAT => "The input is not a valid email address. Use the basic format local-part@hostname", + self::INVALID_HOSTNAME => "'%hostname%' is not a valid hostname for the email address", + self::INVALID_MX_RECORD => "'%hostname%' does not appear to have any valid MX or A records for the email address", + self::INVALID_SEGMENT => "'%hostname%' is not in a routable network segment. The email address should not be resolved from public network", + self::DOT_ATOM => "'%localPart%' can not be matched against dot-atom format", + self::QUOTED_STRING => "'%localPart%' can not be matched against quoted-string format", + self::INVALID_LOCAL_PART => "'%localPart%' is not a valid local part for the email address", + self::LENGTH_EXCEEDED => "The input exceeds the allowed length", + ]; + // @codingStandardsIgnoreEnd + + /** + * @var array + */ + protected $messageVariables = [ + 'hostname' => 'hostname', + 'localPart' => 'localPart', + ]; + + /** + * @var string + */ + protected $hostname; + + /** + * @var string + */ + protected $localPart; + + /** + * Returns the found mx record information + * + * @var array + */ + protected $mxRecord = []; + + /** + * Internal options array + */ + protected $options = [ + 'useMxCheck' => false, + 'useDeepMxCheck' => false, + 'useDomainCheck' => true, + 'allow' => Hostname::ALLOW_DNS, + 'strict' => true, + 'hostnameValidator' => null, + ]; + + /** + * Instantiates hostname validator for local use + * + * The following additional option keys are supported: + * 'hostnameValidator' => A hostname validator, see Laminas\Validator\Hostname + * 'allow' => Options for the hostname validator, see Laminas\Validator\Hostname::ALLOW_* + * 'strict' => Whether to adhere to strictest requirements in the spec + * 'useMxCheck' => If MX check should be enabled, boolean + * 'useDeepMxCheck' => If a deep MX check should be done, boolean + * + * @param array|\Traversable $options OPTIONAL + */ + public function __construct($options = []) + { + if (! is_array($options)) { + $options = func_get_args(); + $temp['allow'] = array_shift($options); + if (! empty($options)) { + $temp['useMxCheck'] = array_shift($options); + } + + if (! empty($options)) { + $temp['hostnameValidator'] = array_shift($options); + } + + $options = $temp; + } + + parent::__construct($options); + } + + /** + * Sets the validation failure message template for a particular key + * Adds the ability to set messages to the attached hostname validator + * + * @param string $messageString + * @param string $messageKey OPTIONAL + * @return AbstractValidator Provides a fluent interface + */ + public function setMessage($messageString, $messageKey = null) + { + if ($messageKey === null) { + $this->getHostnameValidator()->setMessage($messageString); + parent::setMessage($messageString); + return $this; + } + + if (! isset($this->messageTemplates[$messageKey])) { + $this->getHostnameValidator()->setMessage($messageString, $messageKey); + } else { + parent::setMessage($messageString, $messageKey); + } + + return $this; + } + + /** + * Returns the set hostname validator + * + * If was not previously set then lazy load a new one + * + * @return Hostname + */ + public function getHostnameValidator() + { + if (! isset($this->options['hostnameValidator'])) { + $this->options['hostnameValidator'] = new Hostname($this->getAllow()); + } + + return $this->options['hostnameValidator']; + } + + /** + * @param Hostname $hostnameValidator OPTIONAL + * @return $this Provides a fluent interface + */ + public function setHostnameValidator(Hostname $hostnameValidator = null) + { + $this->options['hostnameValidator'] = $hostnameValidator; + + return $this; + } + + /** + * Returns the allow option of the attached hostname validator + * + * @return int + */ + public function getAllow() + { + return $this->options['allow']; + } + + /** + * Sets the allow option of the hostname validator to use + * + * @param int $allow + * @return $this Provides a fluent interface + */ + public function setAllow($allow) + { + $this->options['allow'] = $allow; + if (isset($this->options['hostnameValidator'])) { + $this->options['hostnameValidator']->setAllow($allow); + } + + return $this; + } + + /** + * Whether MX checking via getmxrr is supported or not + * + * @return bool + */ + public function isMxSupported() + { + return function_exists('getmxrr'); + } + + /** + * Returns the set validateMx option + * + * @return bool + */ + public function getMxCheck() + { + return $this->options['useMxCheck']; + } + + /** + * Set whether we check for a valid MX record via DNS + * + * This only applies when DNS hostnames are validated + * + * @param bool $mx Set allowed to true to validate for MX records, and false to not validate them + * @return $this Fluid Interface + */ + public function useMxCheck($mx) + { + $this->options['useMxCheck'] = (bool) $mx; + return $this; + } + + /** + * Returns the set deepMxCheck option + * + * @return bool + */ + public function getDeepMxCheck() + { + return $this->options['useDeepMxCheck']; + } + + /** + * Use deep validation for MX records + * + * @param bool $deep Set deep to true to perform a deep validation process for MX records + * @return $this Fluid Interface + */ + public function useDeepMxCheck($deep) + { + $this->options['useDeepMxCheck'] = (bool) $deep; + return $this; + } + + /** + * Returns the set domainCheck option + * + * @return bool + */ + public function getDomainCheck() + { + return $this->options['useDomainCheck']; + } + + /** + * Sets if the domain should also be checked + * or only the local part of the email address + * + * @param bool $domain + * @return $this Fluid Interface + */ + public function useDomainCheck($domain = true) + { + $this->options['useDomainCheck'] = (bool) $domain; + return $this; + } + + /** + * Returns if the given host is reserved + * + * The following addresses are seen as reserved + * '0.0.0.0/8', '10.0.0.0/8', '127.0.0.0/8' + * '100.64.0.0/10' + * '172.16.0.0/12' + * '198.18.0.0/15' + * '169.254.0.0/16', '192.168.0.0/16' + * '192.0.2.0/24', '192.88.99.0/24', '198.51.100.0/24', '203.0.113.0/24' + * '224.0.0.0/4', '240.0.0.0/4' + * @see http://en.wikipedia.org/wiki/Reserved_IP_addresses + * + * As of RFC5753 (JAN 2010), the following blocks are no longer reserved: + * - 128.0.0.0/16 + * - 191.255.0.0/16 + * - 223.255.255.0/24 + * @see http://tools.ietf.org/html/rfc5735#page-6 + * + * As of RFC6598 (APR 2012), the following blocks are now reserved: + * - 100.64.0.0/10 + * @see http://tools.ietf.org/html/rfc6598#section-7 + * + * @param string $host + * @return bool Returns false when minimal one of the given addresses is not reserved + */ + protected function isReserved($host) + { + if (! preg_match('/^([0-9]{1,3}\.){3}[0-9]{1,3}$/', $host)) { + $host = gethostbynamel($host); + } else { + $host = [$host]; + } + + if (empty($host)) { + return false; + } + + foreach ($host as $server) { + // @codingStandardsIgnoreStart + // Search for 0.0.0.0/8, 10.0.0.0/8, 127.0.0.0/8 + if (!preg_match('/^(0|10|127)(\.([0-9]|[1-9][0-9]|1([0-9][0-9])|2([0-4][0-9]|5[0-5]))){3}$/', $server) && + // Search for 100.64.0.0/10 + !preg_match('/^100\.(6[0-4]|[7-9][0-9]|1[0-1][0-9]|12[0-7])(\.([0-9]|[1-9][0-9]|1([0-9][0-9])|2([0-4][0-9]|5[0-5]))){2}$/', $server) && + // Search for 172.16.0.0/12 + !preg_match('/^172\.(1[6-9]|2[0-9]|3[0-1])(\.([0-9]|[1-9][0-9]|1([0-9][0-9])|2([0-4][0-9]|5[0-5]))){2}$/', $server) && + // Search for 198.18.0.0/15 + !preg_match('/^198\.(1[8-9])(\.([0-9]|[1-9][0-9]|1([0-9][0-9])|2([0-4][0-9]|5[0-5]))){2}$/', $server) && + // Search for 169.254.0.0/16, 192.168.0.0/16 + !preg_match('/^(169\.254|192\.168)(\.([0-9]|[1-9][0-9]|1([0-9][0-9])|2([0-4][0-9]|5[0-5]))){2}$/', $server) && + // Search for 192.0.2.0/24, 192.88.99.0/24, 198.51.100.0/24, 203.0.113.0/24 + !preg_match('/^(192\.0\.2|192\.88\.99|198\.51\.100|203\.0\.113)\.([0-9]|[1-9][0-9]|1([0-9][0-9])|2([0-4][0-9]|5[0-5]))$/', $server) && + // Search for 224.0.0.0/4, 240.0.0.0/4 + !preg_match('/^(2(2[4-9]|[3-4][0-9]|5[0-5]))(\.([0-9]|[1-9][0-9]|1([0-9][0-9])|2([0-4][0-9]|5[0-5]))){3}$/', $server) + ) { + return false; + } + // @codingStandardsIgnoreEnd + } + + return true; + } + + /** + * Internal method to validate the local part of the email address + * + * @return bool + */ + protected function validateLocalPart() + { + // First try to match the local part on the common dot-atom format + + // Dot-atom characters are: 1*atext *("." 1*atext) + // atext: ALPHA / DIGIT / and "!", "#", "$", "%", "&", "'", "*", + // "+", "-", "/", "=", "?", "^", "_", "`", "{", "|", "}", "~" + $atext = 'a-zA-Z0-9\x21\x23\x24\x25\x26\x27\x2a\x2b\x2d\x2f\x3d\x3f\x5e\x5f\x60\x7b\x7c\x7d\x7e'; + if (preg_match('/^[' . $atext . ']+(\x2e+[' . $atext . ']+)*$/', $this->localPart)) { + return true; + } + + if ($this->validateInternationalizedLocalPart($this->localPart)) { + return true; + } + + // Try quoted string format (RFC 5321 Chapter 4.1.2) + + // Quoted-string characters are: DQUOTE *(qtext/quoted-pair) DQUOTE + $qtext = '\x20-\x21\x23-\x5b\x5d-\x7e'; // %d32-33 / %d35-91 / %d93-126 + $quotedPair = '\x20-\x7e'; // %d92 %d32-126 + if (preg_match('/^"(['. $qtext .']|\x5c[' . $quotedPair . '])*"$/', $this->localPart)) { + return true; + } + + $this->error(self::DOT_ATOM); + $this->error(self::QUOTED_STRING); + $this->error(self::INVALID_LOCAL_PART); + + return false; + } + + /** + * @param string $localPart Address local part to validate. + * @return bool + */ + protected function validateInternationalizedLocalPart($localPart) + { + if (extension_loaded('intl') + && false === UConverter::transcode($localPart, 'UTF-8', 'UTF-8') + ) { + // invalid utf? + return false; + } + + $atext = 'a-zA-Z0-9\x21\x23\x24\x25\x26\x27\x2a\x2b\x2d\x2f\x3d\x3f\x5e\x5f\x60\x7b\x7c\x7d\x7e'; + // RFC 6532 extends atext to include non-ascii utf + // @see https://tools.ietf.org/html/rfc6532#section-3.1 + $uatext = $atext . '\x{80}-\x{FFFF}'; + return (bool) preg_match('/^[' . $uatext . ']+(\x2e+[' . $uatext . ']+)*$/u', $localPart); + } + + /** + * Returns the found MX Record information after validation including weight for further processing + * + * @return array + */ + public function getMXRecord() + { + return $this->mxRecord; + } + + /** + * Internal method to validate the servers MX records + * + * @return bool + */ + protected function validateMXRecords() + { + $mxHosts = []; + $weight = []; + $result = getmxrr($this->hostname, $mxHosts, $weight); + if (! empty($mxHosts) && ! empty($weight)) { + $this->mxRecord = array_combine($mxHosts, $weight) ?: []; + } else { + $this->mxRecord = []; + } + + arsort($this->mxRecord); + + // Fallback to IPv4 hosts if no MX record found (RFC 2821 SS 5). + if (! $result) { + $result = gethostbynamel($this->hostname); + if (is_array($result)) { + $this->mxRecord = array_flip($result); + } + } + + if (! $result) { + $this->error(self::INVALID_MX_RECORD); + return $result; + } + + if (! $this->options['useDeepMxCheck']) { + return $result; + } + + $validAddress = false; + $reserved = true; + foreach ($this->mxRecord as $hostname => $weight) { + $res = $this->isReserved($hostname); + if (! $res) { + $reserved = false; + } + + if (! $res + && (checkdnsrr($hostname, 'A') + || checkdnsrr($hostname, 'AAAA') + || checkdnsrr($hostname, 'A6')) + ) { + $validAddress = true; + break; + } + } + + if (! $validAddress) { + $result = false; + $error = $reserved ? self::INVALID_SEGMENT : self::INVALID_MX_RECORD; + $this->error($error); + } + + return $result; + } + + /** + * Internal method to validate the hostname part of the email address + * + * @return bool + */ + protected function validateHostnamePart() + { + $hostname = $this->getHostnameValidator()->setTranslator($this->getTranslator()) + ->isValid($this->hostname); + if (! $hostname) { + $this->error(self::INVALID_HOSTNAME); + // Get messages and errors from hostnameValidator + foreach ($this->getHostnameValidator()->getMessages() as $code => $message) { + $this->abstractOptions['messages'][$code] = $message; + } + } elseif ($this->options['useMxCheck']) { + // MX check on hostname + $hostname = $this->validateMXRecords(); + } + + return $hostname; + } + + /** + * Splits the given value in hostname and local part of the email address + * + * @param string $value Email address to be split + * @return bool Returns false when the email can not be split + */ + protected function splitEmailParts($value) + { + $value = is_string($value) ? $value : ''; + + // Split email address up and disallow '..' + if (strpos($value, '..') !== false + || ! preg_match('/^(.+)@([^@]+)$/', $value, $matches) + ) { + return false; + } + + $this->localPart = $matches[1]; + $this->hostname = $this->idnToAscii($matches[2]); + + return true; + } + + /** + * Defined by Laminas\Validator\ValidatorInterface + * + * Returns true if and only if $value is a valid email address + * according to RFC2822 + * + * @link http://www.ietf.org/rfc/rfc2822.txt RFC2822 + * @link http://www.columbia.edu/kermit/ascii.html US-ASCII characters + * @param string $value + * @return bool + */ + public function isValid($value) + { + if (! is_string($value)) { + $this->error(self::INVALID); + return false; + } + + $length = true; + $this->setValue($value); + + // Split email address up and disallow '..' + if (! $this->splitEmailParts($this->getValue())) { + $this->error(self::INVALID_FORMAT); + return false; + } + + if ($this->getOption('strict') && (strlen($this->localPart) > 64) || (strlen($this->hostname) > 255)) { + $length = false; + $this->error(self::LENGTH_EXCEEDED); + } + + // Match hostname part + $hostname = false; + if ($this->options['useDomainCheck']) { + $hostname = $this->validateHostnamePart(); + } + + $local = $this->validateLocalPart(); + + // If both parts valid, return true + return ($local && $length) && (! $this->options['useDomainCheck'] || $hostname); + } + + /** + * Safely convert UTF-8 encoded domain name to ASCII + * @param string $email the UTF-8 encoded email + * @return string + */ + protected function idnToAscii($email) + { + if (extension_loaded('intl')) { + if (defined('INTL_IDNA_VARIANT_UTS46')) { + return idn_to_ascii($email, 0, INTL_IDNA_VARIANT_UTS46) ?: $email; + } + return idn_to_ascii($email) ?: $email; + } + return $email; + } + + /** + * Safely convert ASCII encoded domain name to UTF-8 + * @param string $email the ASCII encoded email + * @return string + */ + protected function idnToUtf8($email) + { + if (strlen($email) == 0) { + return $email; + } + + if (extension_loaded('intl')) { + // The documentation does not clarify what kind of failure + // can happen in idn_to_utf8. One can assume if the source + // is not IDN encoded, it would fail, but it usually returns + // the source string in those cases. + // But not when the source string is long enough. + // Thus we default to source string ourselves. + if (defined('INTL_IDNA_VARIANT_UTS46')) { + return idn_to_utf8($email, 0, INTL_IDNA_VARIANT_UTS46) ?: $email; + } + return idn_to_utf8($email) ?: $email; + } + return $email; + } +} diff --git a/lib/laminas/laminas-validator/src/Exception/BadMethodCallException.php b/lib/laminas/laminas-validator/src/Exception/BadMethodCallException.php new file mode 100644 index 000000000..460d78821 --- /dev/null +++ b/lib/laminas/laminas-validator/src/Exception/BadMethodCallException.php @@ -0,0 +1,13 @@ + 'Invalid type given', + ]; + + /** + * @var array + */ + protected $messageVariables = []; + + /** + * @var string + */ + protected $valueDelimiter = ','; + + /** + * @var ValidatorInterface + */ + protected $validator; + + /** + * @var bool + */ + protected $breakOnFirstFailure = false; + + /** + * Sets the delimiter string that the values will be split upon + * + * @param string $delimiter + * @return $this + */ + public function setValueDelimiter($delimiter) + { + $this->valueDelimiter = $delimiter; + return $this; + } + + /** + * Returns the delimiter string that the values will be split upon + * + * @return string + */ + public function getValueDelimiter() + { + return $this->valueDelimiter; + } + + /** + * Set validator plugin manager + * + * @param ValidatorPluginManager $pluginManager + */ + public function setValidatorPluginManager(ValidatorPluginManager $pluginManager) + { + $this->pluginManager = $pluginManager; + } + + /** + * Get validator plugin manager + * + * @return ValidatorPluginManager + */ + public function getValidatorPluginManager() + { + if (! $this->pluginManager) { + $this->setValidatorPluginManager(new ValidatorPluginManager(new ServiceManager)); + } + + return $this->pluginManager; + } + + /** + * Sets the Validator for validating each value + * + * @param ValidatorInterface|array $validator + * @throws Exception\RuntimeException + * @return $this + */ + public function setValidator($validator) + { + if (is_array($validator)) { + if (! isset($validator['name'])) { + throw new Exception\RuntimeException( + 'Invalid validator specification provided; does not include "name" key' + ); + } + $name = $validator['name']; + $options = isset($validator['options']) ? $validator['options'] : []; + $validator = $this->getValidatorPluginManager()->get($name, $options); + } + + if (! $validator instanceof ValidatorInterface) { + throw new Exception\RuntimeException( + 'Invalid validator given' + ); + } + + $this->validator = $validator; + return $this; + } + + /** + * Gets the Validator for validating each value + * + * @return ValidatorInterface + */ + public function getValidator() + { + return $this->validator; + } + + /** + * Set break on first failure setting + * + * @param bool $break + * @return $this + */ + public function setBreakOnFirstFailure($break) + { + $this->breakOnFirstFailure = (bool) $break; + return $this; + } + + /** + * Get break on first failure setting + * + * @return bool + */ + public function isBreakOnFirstFailure() + { + return $this->breakOnFirstFailure; + } + + /** + * Defined by Laminas\Validator\ValidatorInterface + * + * Returns true if all values validate true + * + * @param mixed $value + * @param mixed $context Extra "context" to provide the composed validator + * @return bool + * @throws Exception\RuntimeException + */ + public function isValid($value, $context = null) + { + $this->setValue($value); + + if ($value instanceof Traversable) { + $value = ArrayUtils::iteratorToArray($value); + } + + if (is_array($value)) { + $values = $value; + } elseif (is_string($value)) { + $delimiter = $this->getValueDelimiter(); + // Skip explode if delimiter is null, + // used when value is expected to be either an + // array when multiple values and a string for + // single values (ie. MultiCheckbox form behavior) + $values = null !== $delimiter + ? explode($this->valueDelimiter, $value) + : [$value]; + } else { + $values = [$value]; + } + + $validator = $this->getValidator(); + + if (! $validator) { + throw new Exception\RuntimeException(sprintf( + '%s expects a validator to be set; none given', + __METHOD__ + )); + } + + foreach ($values as $value) { + if (! $validator->isValid($value, $context)) { + $this->abstractOptions['messages'][] = $validator->getMessages(); + + if ($this->isBreakOnFirstFailure()) { + return false; + } + } + } + + return ! $this->abstractOptions['messages']; + } +} diff --git a/lib/laminas/laminas-validator/src/File/Count.php b/lib/laminas/laminas-validator/src/File/Count.php new file mode 100644 index 000000000..226da5c9f --- /dev/null +++ b/lib/laminas/laminas-validator/src/File/Count.php @@ -0,0 +1,253 @@ + "Too many files, maximum '%max%' are allowed but '%count%' are given", + self::TOO_FEW => "Too few files, minimum '%min%' are expected but '%count%' are given", + ]; + + /** + * @var array Error message template variables + */ + protected $messageVariables = [ + 'min' => ['options' => 'min'], + 'max' => ['options' => 'max'], + 'count' => 'count', + ]; + + /** + * Actual filecount + * + * @var int + */ + protected $count; + + /** + * Internal file array + * @var array + */ + protected $files; + + /** + * Options for this validator + * + * @var array + */ + protected $options = [ + 'min' => null, // Minimum file count, if null there is no minimum file count + 'max' => null, // Maximum file count, if null there is no maximum file count + ]; + + /** + * Sets validator options + * + * Min limits the file count, when used with max=null it is the maximum file count + * It also accepts an array with the keys 'min' and 'max' + * + * If $options is an integer, it will be used as maximum file count + * As Array is accepts the following keys: + * 'min': Minimum filecount + * 'max': Maximum filecount + * + * @param int|array|\Traversable $options Options for the adapter + */ + public function __construct($options = null) + { + if (1 < func_num_args()) { + $args = func_get_args(); + $options = [ + 'min' => array_shift($args), + 'max' => array_shift($args), + ]; + } + + if (is_string($options) || is_numeric($options)) { + $options = ['max' => $options]; + } + + parent::__construct($options); + } + + /** + * Returns the minimum file count + * + * @return int + */ + public function getMin() + { + return $this->options['min']; + } + + /** + * Sets the minimum file count + * + * @param int|array $min The minimum file count + * @return $this Provides a fluent interface + * @throws Exception\InvalidArgumentException When min is greater than max + */ + public function setMin($min) + { + if (is_array($min) && isset($min['min'])) { + $min = $min['min']; + } + + if (! is_numeric($min)) { + throw new Exception\InvalidArgumentException('Invalid options to validator provided'); + } + + $min = (int) $min; + if (($this->getMax() !== null) && ($min > $this->getMax())) { + throw new Exception\InvalidArgumentException( + "The minimum must be less than or equal to the maximum file count, but {$min} > {$this->getMax()}" + ); + } + + $this->options['min'] = $min; + return $this; + } + + /** + * Returns the maximum file count + * + * @return int + */ + public function getMax() + { + return $this->options['max']; + } + + /** + * Sets the maximum file count + * + * @param int|array $max The maximum file count + * @return $this Provides a fluent interface + * @throws Exception\InvalidArgumentException When max is smaller than min + */ + public function setMax($max) + { + if (is_array($max) && isset($max['max'])) { + $max = $max['max']; + } + + if (! is_numeric($max)) { + throw new Exception\InvalidArgumentException('Invalid options to validator provided'); + } + + $max = (int) $max; + if (($this->getMin() !== null) && ($max < $this->getMin())) { + throw new Exception\InvalidArgumentException( + "The maximum must be greater than or equal to the minimum file count, but {$max} < {$this->getMin()}" + ); + } + + $this->options['max'] = $max; + return $this; + } + + /** + * Adds a file for validation + * + * @param string|array $file + * @return $this + */ + public function addFile($file) + { + if (is_string($file)) { + $file = [$file]; + } + + if (is_array($file)) { + foreach ($file as $name) { + if (! isset($this->files[$name]) && ! empty($name)) { + $this->files[$name] = $name; + } + } + } + + return $this; + } + + /** + * Returns true if and only if the file count of all checked files is at least min and + * not bigger than max (when max is not null). Attention: When checking with set min you + * must give all files with the first call, otherwise you will get a false. + * + * @param string|array $value Filenames to check for count + * @param array $file File data from \Laminas\File\Transfer\Transfer + * @return bool + */ + public function isValid($value, $file = null) + { + if (($file !== null) && ! array_key_exists('destination', $file)) { + $file['destination'] = dirname($value); + } + + if (($file !== null) && array_key_exists('tmp_name', $file)) { + $value = $file['destination'] . DIRECTORY_SEPARATOR . $file['name']; + } + + if (($file === null) || ! empty($file['tmp_name'])) { + $this->addFile($value); + } + + $this->count = count($this->files); + if (($this->getMax() !== null) && ($this->count > $this->getMax())) { + return $this->throwError($file, self::TOO_MANY); + } + + if (($this->getMin() !== null) && ($this->count < $this->getMin())) { + return $this->throwError($file, self::TOO_FEW); + } + + return true; + } + + /** + * Throws an error of the given type + * + * @param string $file + * @param string $errorType + * @return false + */ + protected function throwError($file, $errorType) + { + if ($file !== null) { + if (is_array($file)) { + if (array_key_exists('name', $file)) { + $this->value = $file['name']; + } + } elseif (is_string($file)) { + $this->value = $file; + } + } + + $this->error($errorType); + return false; + } +} diff --git a/lib/laminas/laminas-validator/src/File/Crc32.php b/lib/laminas/laminas-validator/src/File/Crc32.php new file mode 100644 index 000000000..f546cad18 --- /dev/null +++ b/lib/laminas/laminas-validator/src/File/Crc32.php @@ -0,0 +1,113 @@ + 'File does not match the given crc32 hashes', + self::NOT_DETECTED => 'A crc32 hash could not be evaluated for the given file', + self::NOT_FOUND => 'File is not readable or does not exist', + ]; + + /** + * Options for this validator + * + * @var string + */ + protected $options = [ + 'algorithm' => 'crc32', + 'hash' => null, + ]; + + /** + * Returns all set crc32 hashes + * + * @return array + */ + public function getCrc32() + { + return $this->getHash(); + } + + /** + * Sets the crc32 hash for one or multiple files + * + * @param string|array $options + * @return $this Provides a fluent interface + */ + public function setCrc32($options) + { + $this->setHash($options); + return $this; + } + + /** + * Adds the crc32 hash for one or multiple files + * + * @param string|array $options + * @return $this Provides a fluent interface + */ + public function addCrc32($options) + { + $this->addHash($options); + return $this; + } + + /** + * Returns true if and only if the given file confirms the set hash + * + * @param string|array $value Filename to check for hash + * @param array $file File data from \Laminas\File\Transfer\Transfer (optional) + * @return bool + */ + public function isValid($value, $file = null) + { + $fileInfo = $this->getFileInfo($value, $file); + + $this->setValue($fileInfo['filename']); + + // Is file readable ? + if (empty($fileInfo['file']) || false === is_readable($fileInfo['file'])) { + $this->error(self::NOT_FOUND); + return false; + } + + $hashes = array_unique(array_keys($this->getHash())); + $filehash = hash_file('crc32', $fileInfo['file']); + if ($filehash === false) { + $this->error(self::NOT_DETECTED); + return false; + } + + foreach ($hashes as $hash) { + if ($filehash === $hash) { + return true; + } + } + + $this->error(self::DOES_NOT_MATCH); + return false; + } +} diff --git a/lib/laminas/laminas-validator/src/File/ExcludeExtension.php b/lib/laminas/laminas-validator/src/File/ExcludeExtension.php new file mode 100644 index 000000000..0a745057c --- /dev/null +++ b/lib/laminas/laminas-validator/src/File/ExcludeExtension.php @@ -0,0 +1,77 @@ + 'File has an incorrect extension', + self::NOT_FOUND => 'File is not readable or does not exist', + ]; + + /** + * Returns true if and only if the file extension of $value is not included in the + * set extension list + * + * @param string|array $value Real file to check for extension + * @param array $file File data from \Laminas\File\Transfer\Transfer (optional) + * @return bool + */ + public function isValid($value, $file = null) + { + $fileInfo = $this->getFileInfo($value, $file); + + // Is file readable ? + if (! $this->getAllowNonExistentFile() + && (empty($fileInfo['file']) || false === is_readable($fileInfo['file'])) + ) { + if (preg_match('/nofile\.mo$/', $fileInfo['file'])) { + } + $this->error(self::NOT_FOUND); + return false; + } + + $this->setValue($fileInfo['filename']); + + $extension = substr($fileInfo['filename'], strrpos($fileInfo['filename'], '.') + 1); + $extensions = $this->getExtension(); + + if ($this->getCase() && (! in_array($extension, $extensions))) { + return true; + } elseif (! $this->getCase()) { + foreach ($extensions as $ext) { + if (strtolower($ext) == strtolower($extension)) { + if (preg_match('/nofile\.mo$/', $fileInfo['file'])) { + } + $this->error(self::FALSE_EXTENSION); + return false; + } + } + + return true; + } + + $this->error(self::FALSE_EXTENSION); + return false; + } +} diff --git a/lib/laminas/laminas-validator/src/File/ExcludeMimeType.php b/lib/laminas/laminas-validator/src/File/ExcludeMimeType.php new file mode 100644 index 000000000..f5d2f2ded --- /dev/null +++ b/lib/laminas/laminas-validator/src/File/ExcludeMimeType.php @@ -0,0 +1,95 @@ + "File has an incorrect mimetype of '%type%'", + self::NOT_DETECTED => 'The mimetype could not be detected from the file', + self::NOT_READABLE => 'File is not readable or does not exist', + ]; + + /** + * Returns true if the mimetype of the file does not matche the given ones. Also parts + * of mimetypes can be checked. If you give for example "image" all image + * mime types will not be accepted like "image/gif", "image/jpeg" and so on. + * + * @param string|array $value Real file to check for mimetype + * @param array $file File data from \Laminas\File\Transfer\Transfer (optional) + * @return bool + */ + public function isValid($value, $file = null) + { + $fileInfo = $this->getFileInfo($value, $file, true); + + $this->setValue($fileInfo['filename']); + + // Is file readable ? + if (empty($fileInfo['file']) || false === is_readable($fileInfo['file'])) { + $this->error(self::NOT_READABLE); + return false; + } + + $mimefile = $this->getMagicFile(); + if (class_exists('finfo', false)) { + if (! $this->isMagicFileDisabled() && (! empty($mimefile) && empty($this->finfo))) { + $this->finfo = finfo_open(FILEINFO_MIME_TYPE, $mimefile); + } + + if (empty($this->finfo)) { + $this->finfo = finfo_open(FILEINFO_MIME_TYPE); + } + + $this->type = null; + if (! empty($this->finfo)) { + $this->type = finfo_file($this->finfo, $fileInfo['file']); + } + } + + if (empty($this->type) && $this->getHeaderCheck()) { + $this->type = $fileInfo['filetype']; + } + + if (empty($this->type)) { + $this->error(self::NOT_DETECTED); + return false; + } + + $mimetype = $this->getMimeType(true); + if (in_array($this->type, $mimetype)) { + $this->error(self::FALSE_TYPE); + return false; + } + + $types = explode('/', $this->type); + $types = array_merge($types, explode('-', $this->type)); + $types = array_merge($types, explode(';', $this->type)); + foreach ($mimetype as $mime) { + if (in_array($mime, $types)) { + $this->error(self::FALSE_TYPE); + return false; + } + } + + return true; + } +} diff --git a/lib/laminas/laminas-validator/src/File/Exists.php b/lib/laminas/laminas-validator/src/File/Exists.php new file mode 100644 index 000000000..e095b28ac --- /dev/null +++ b/lib/laminas/laminas-validator/src/File/Exists.php @@ -0,0 +1,181 @@ + 'File does not exist', + ]; + + /** + * Options for this validator + * + * @var array + */ + protected $options = [ + 'directory' => null, // internal list of directories + ]; + + /** + * @var array Error message template variables + */ + protected $messageVariables = [ + 'directory' => ['options' => 'directory'], + ]; + + /** + * Sets validator options + * + * @param string|array|\Traversable $options + */ + public function __construct($options = null) + { + if (is_string($options)) { + $options = explode(',', $options); + } + + if (is_array($options) && ! array_key_exists('directory', $options)) { + $options = ['directory' => $options]; + } + + parent::__construct($options); + } + + /** + * Returns the set file directories which are checked + * + * @param bool $asArray Returns the values as array; when false, a concatenated string is returned + * @return string|null + */ + public function getDirectory($asArray = false) + { + $asArray = (bool) $asArray; + $directory = $this->options['directory']; + if ($asArray && isset($directory)) { + $directory = explode(',', (string) $directory); + } + + return $directory; + } + + /** + * Sets the file directory which will be checked + * + * @param string|array $directory The directories to validate + * @return Extension Provides a fluent interface + */ + public function setDirectory($directory) + { + $this->options['directory'] = null; + $this->addDirectory($directory); + return $this; + } + + /** + * Adds the file directory which will be checked + * + * @param string|array $directory The directory to add for validation + * @return Extension Provides a fluent interface + * @throws Exception\InvalidArgumentException + */ + public function addDirectory($directory) + { + $directories = $this->getDirectory(true); + if (! isset($directories)) { + $directories = []; + } + + if (is_string($directory)) { + $directory = explode(',', $directory); + } elseif (! is_array($directory)) { + throw new Exception\InvalidArgumentException('Invalid options to validator provided'); + } + + foreach ($directory as $content) { + if (empty($content) || ! is_string($content)) { + continue; + } + + $directories[] = trim($content); + } + $directories = array_unique($directories); + + // Sanity check to ensure no empty values + foreach ($directories as $key => $dir) { + if (empty($dir)) { + unset($directories[$key]); + } + } + + $this->options['directory'] = ! empty($directory) + ? implode(',', $directories) : null; + + return $this; + } + + /** + * Returns true if and only if the file already exists in the set directories + * + * @param string|array $value Real file to check for existence + * @param array $file File data from \Laminas\File\Transfer\Transfer (optional) + * @return bool + */ + public function isValid($value, $file = null) + { + $fileInfo = $this->getFileInfo($value, $file, false, true); + + $this->setValue($fileInfo['filename']); + + $check = false; + $directories = $this->getDirectory(true); + if (! isset($directories)) { + $check = true; + if (! file_exists($fileInfo['file'])) { + $this->error(self::DOES_NOT_EXIST); + return false; + } + } else { + foreach ($directories as $directory) { + if (! isset($directory) || '' === $directory) { + continue; + } + + $check = true; + if (! file_exists($directory . DIRECTORY_SEPARATOR . $fileInfo['basename'])) { + $this->error(self::DOES_NOT_EXIST); + return false; + } + } + } + + if (! $check) { + $this->error(self::DOES_NOT_EXIST); + return false; + } + + return true; + } +} diff --git a/lib/laminas/laminas-validator/src/File/Extension.php b/lib/laminas/laminas-validator/src/File/Extension.php new file mode 100644 index 000000000..c0d580c7a --- /dev/null +++ b/lib/laminas/laminas-validator/src/File/Extension.php @@ -0,0 +1,231 @@ + 'File has an incorrect extension', + self::NOT_FOUND => 'File is not readable or does not exist', + ]; + + /** + * Options for this validator + * + * @var array + */ + protected $options = [ + 'case' => false, // Validate case sensitive + 'extension' => '', // List of extensions + 'allowNonExistentFile' => false, // Allow validation even if file does not exist + ]; + + /** + * @var array Error message template variables + */ + protected $messageVariables = [ + 'extension' => ['options' => 'extension'], + ]; + + /** + * Sets validator options + * + * @param string|array|Traversable $options + */ + public function __construct($options = null) + { + if ($options instanceof Traversable) { + $options = ArrayUtils::iteratorToArray($options); + } + + $case = null; + if (1 < func_num_args()) { + $case = func_get_arg(1); + } + + if (is_array($options)) { + if (isset($options['case'])) { + $case = $options['case']; + unset($options['case']); + } + + if (! array_key_exists('extension', $options)) { + $options = ['extension' => $options]; + } + } else { + $options = ['extension' => $options]; + } + + if ($case !== null) { + $options['case'] = $case; + } + + parent::__construct($options); + } + + /** + * Returns the case option + * + * @return bool + */ + public function getCase() + { + return $this->options['case']; + } + + /** + * Sets the case to use + * + * @param bool $case + * @return $this Provides a fluent interface + */ + public function setCase($case) + { + $this->options['case'] = (bool) $case; + return $this; + } + + /** + * Returns the set file extension + * + * @return array + */ + public function getExtension() + { + $extension = explode(',', $this->options['extension']); + + return $extension; + } + + /** + * Sets the file extensions + * + * @param string|array $extension The extensions to validate + * @return $this Provides a fluent interface + */ + public function setExtension($extension) + { + $this->options['extension'] = null; + $this->addExtension($extension); + return $this; + } + + /** + * Adds the file extensions + * + * @param string|array $extension The extensions to add for validation + * @return $this Provides a fluent interface + */ + public function addExtension($extension) + { + $extensions = $this->getExtension(); + if (is_string($extension)) { + $extension = explode(',', $extension); + } + + foreach ($extension as $content) { + if (empty($content) || ! is_string($content)) { + continue; + } + + $extensions[] = trim($content); + } + + $extensions = array_unique($extensions); + + // Sanity check to ensure no empty values + foreach ($extensions as $key => $ext) { + if (empty($ext)) { + unset($extensions[$key]); + } + } + + $this->options['extension'] = implode(',', $extensions); + return $this; + } + + /** + * Returns whether or not to allow validation of non-existent files. + * + * @return bool + */ + public function getAllowNonExistentFile() + { + return $this->options['allowNonExistentFile']; + } + + /** + * Sets the flag indicating whether or not to allow validation of non-existent files. + * + * @param bool $flag Whether or not to allow validation of non-existent files. + * @return $this Provides a fluent interface + */ + public function setAllowNonExistentFile($flag) + { + $this->options['allowNonExistentFile'] = (bool) $flag; + return $this; + } + + /** + * Returns true if and only if the file extension of $value is included in the + * set extension list + * + * @param string|array $value Real file to check for extension + * @param array $file File data from \Laminas\File\Transfer\Transfer (optional) + * @return bool + */ + public function isValid($value, $file = null) + { + $fileInfo = $this->getFileInfo($value, $file); + + // Is file readable ? + if (! $this->getAllowNonExistentFile() + && (empty($fileInfo['file']) || false === is_readable($fileInfo['file'])) + ) { + $this->error(self::NOT_FOUND); + return false; + } + + $this->setValue($fileInfo['filename']); + + $extension = substr($fileInfo['filename'], strrpos($fileInfo['filename'], '.') + 1); + $extensions = $this->getExtension(); + + if ($this->getCase() && (in_array($extension, $extensions))) { + return true; + } elseif (! $this->getCase()) { + foreach ($extensions as $ext) { + if (strtolower($ext) == strtolower($extension)) { + return true; + } + } + } + + $this->error(self::FALSE_EXTENSION); + return false; + } +} diff --git a/lib/laminas/laminas-validator/src/File/FileInformationTrait.php b/lib/laminas/laminas-validator/src/File/FileInformationTrait.php new file mode 100644 index 000000000..12c827e53 --- /dev/null +++ b/lib/laminas/laminas-validator/src/File/FileInformationTrait.php @@ -0,0 +1,167 @@ +getLegacyFileInfo($file, $hasType, $hasBasename); + } + + if (is_array($value)) { + return $this->getSapiFileInfo($value, $hasType, $hasBasename); + } + + if ($value instanceof UploadedFileInterface) { + return $this->getPsr7FileInfo($value, $hasType, $hasBasename); + } + + return $this->getFileBasedFileInfo($value, $hasType, $hasBasename); + } + + /** + * Generate file information array with legacy Laminas_File_Transfer API + * + * @param array $file File data + * @param bool $hasType Return with filetype + * @param bool $hasBasename Basename is calculated from location path + * @return array + */ + private function getLegacyFileInfo( + array $file, + $hasType = false, + $hasBasename = false + ) { + $fileInfo = []; + + $fileInfo['filename'] = $file['name']; + $fileInfo['file'] = $file['tmp_name']; + + if ($hasBasename) { + $fileInfo['basename'] = basename($fileInfo['file']); + } + + if ($hasType) { + $fileInfo['filetype'] = $file['type']; + } + + return $fileInfo; + } + + /** + * Generate file information array with SAPI + * + * @param array $file File data from SAPI + * @param bool $hasType Return with filetype + * @param bool $hasBasename Filename is calculated from location path + * @return array + */ + private function getSapiFileInfo( + array $file, + $hasType = false, + $hasBasename = false + ) { + if (! isset($file['tmp_name']) || ! isset($file['name'])) { + throw new Exception\InvalidArgumentException( + 'Value array must be in $_FILES format' + ); + } + + $fileInfo = []; + + $fileInfo['file'] = $file['tmp_name']; + $fileInfo['filename'] = $file['name']; + + if ($hasBasename) { + $fileInfo['basename'] = basename($fileInfo['file']); + } + + if ($hasType) { + $fileInfo['filetype'] = $file['type']; + } + + return $fileInfo; + } + + /** + * Generate file information array with PSR-7 UploadedFileInterface + * + * @param UploadedFileInterface $file + * @param bool $hasType Return with filetype + * @param bool $hasBasename Filename is calculated from location path + * @return array + */ + private function getPsr7FileInfo( + UploadedFileInterface $file, + $hasType = false, + $hasBasename = false + ) { + $fileInfo = []; + + $fileInfo['file'] = $file->getStream()->getMetadata('uri'); + $fileInfo['filename'] = $file->getClientFilename(); + + if ($hasBasename) { + $fileInfo['basename'] = basename($fileInfo['file']); + } + + if ($hasType) { + $fileInfo['filetype'] = $file->getClientMediaType(); + } + + return $fileInfo; + } + + /** + * Generate file information array with base method + * + * @param string $file File path + * @param bool $hasType Return with filetype + * @param bool $hasBasename Filename is calculated from location path + * @return array + */ + private function getFileBasedFileInfo( + $file, + $hasType = false, + $hasBasename = false + ) { + $fileInfo = []; + + $fileInfo['file'] = $file; + $fileInfo['filename'] = basename($fileInfo['file']); + + if ($hasBasename) { + $fileInfo['basename'] = basename($fileInfo['file']); + } + + if ($hasType) { + $fileInfo['filetype'] = null; + } + + return $fileInfo; + } +} diff --git a/lib/laminas/laminas-validator/src/File/FilesSize.php b/lib/laminas/laminas-validator/src/File/FilesSize.php new file mode 100644 index 000000000..a6c89c089 --- /dev/null +++ b/lib/laminas/laminas-validator/src/File/FilesSize.php @@ -0,0 +1,182 @@ + "All files in sum should have a maximum size of '%max%' but '%size%' were detected", + self::TOO_SMALL => "All files in sum should have a minimum size of '%min%' but '%size%' were detected", + self::NOT_READABLE => 'One or more files can not be read', + ]; + + /** + * Internal file array + * + * @var array + */ + protected $files; + + /** + * Sets validator options + * + * Min limits the used disk space for all files, when used with max=null it is the maximum file size + * It also accepts an array with the keys 'min' and 'max' + * + * @param int|array|Traversable $options Options for this validator + * @throws \Laminas\Validator\Exception\InvalidArgumentException + */ + public function __construct($options = null) + { + $this->files = []; + $this->setSize(0); + + if ($options instanceof Traversable) { + $options = ArrayUtils::iteratorToArray($options); + } elseif (is_scalar($options)) { + $options = ['max' => $options]; + } elseif (! is_array($options)) { + throw new Exception\InvalidArgumentException('Invalid options to validator provided'); + } + + if (1 < func_num_args()) { + $argv = func_get_args(); + array_shift($argv); + $options['max'] = array_shift($argv); + if (! empty($argv)) { + $options['useByteString'] = array_shift($argv); + } + } + + parent::__construct($options); + } + + /** + * Returns true if and only if the disk usage of all files is at least min and + * not bigger than max (when max is not null). + * + * @param string|array $value Real file to check for size + * @param array $file File data from \Laminas\File\Transfer\Transfer + * @return bool + */ + public function isValid($value, $file = null) + { + if (is_string($value)) { + $value = [$value]; + } elseif (is_array($value) && isset($value['tmp_name'])) { + $value = [$value]; + } + + $min = $this->getMin(true); + $max = $this->getMax(true); + $size = $this->getSize(); + foreach ($value as $files) { + if (is_array($files)) { + if (! isset($files['tmp_name']) || ! isset($files['name'])) { + throw new Exception\InvalidArgumentException( + 'Value array must be in $_FILES format' + ); + } + $file = $files; + $files = $files['tmp_name']; + } + + // Is file readable ? + if (empty($files) || false === is_readable($files)) { + $this->throwError($file, self::NOT_READABLE); + continue; + } + + if (! isset($this->files[$files])) { + $this->files[$files] = $files; + } else { + // file already counted... do not count twice + continue; + } + + // limited to 2GB files + ErrorHandler::start(); + $size += filesize($files); + ErrorHandler::stop(); + $this->size = $size; + if (($max !== null) && ($max < $size)) { + if ($this->getByteString()) { + $this->options['max'] = $this->toByteString($max); + $this->size = $this->toByteString($size); + $this->throwError($file, self::TOO_BIG); + $this->options['max'] = $max; + $this->size = $size; + } else { + $this->throwError($file, self::TOO_BIG); + } + } + } + + // Check that aggregate files are >= minimum size + if (($min !== null) && ($size < $min)) { + if ($this->getByteString()) { + $this->options['min'] = $this->toByteString($min); + $this->size = $this->toByteString($size); + $this->throwError($file, self::TOO_SMALL); + $this->options['min'] = $min; + $this->size = $size; + } else { + $this->throwError($file, self::TOO_SMALL); + } + } + + if ($this->getMessages()) { + return false; + } + + return true; + } + + /** + * Throws an error of the given type + * + * @param string $file + * @param string $errorType + * @return false + */ + protected function throwError($file, $errorType) + { + if ($file !== null) { + if (is_array($file)) { + if (array_key_exists('name', $file)) { + $this->value = $file['name']; + } + } elseif (is_string($file)) { + $this->value = $file; + } + } + + $this->error($errorType); + return false; + } +} diff --git a/lib/laminas/laminas-validator/src/File/Hash.php b/lib/laminas/laminas-validator/src/File/Hash.php new file mode 100644 index 000000000..c6b60f58f --- /dev/null +++ b/lib/laminas/laminas-validator/src/File/Hash.php @@ -0,0 +1,166 @@ + 'File does not match the given hashes', + self::NOT_DETECTED => 'A hash could not be evaluated for the given file', + self::NOT_FOUND => 'File is not readable or does not exist', + ]; + + /** + * Options for this validator + * + * @var string + */ + protected $options = [ + 'algorithm' => 'crc32', + 'hash' => null, + ]; + + /** + * Sets validator options + * + * @param string|array $options + */ + public function __construct($options = null) + { + if (is_scalar($options) || + (is_array($options) && ! array_key_exists('hash', $options))) { + $options = ['hash' => $options]; + } + + if (1 < func_num_args()) { + $options['algorithm'] = func_get_arg(1); + } + + parent::__construct($options); + } + + /** + * Returns the set hash values as array, the hash as key and the algorithm the value + * + * @return array + */ + public function getHash() + { + return $this->options['hash']; + } + + /** + * Sets the hash for one or multiple files + * + * @param string|array $options + * @return $this Provides a fluent interface + */ + public function setHash($options) + { + $this->options['hash'] = null; + $this->addHash($options); + + return $this; + } + + /** + * Adds the hash for one or multiple files + * + * @param string|array $options + * @throws Exception\InvalidArgumentException + * @return $this Provides a fluent interface + */ + public function addHash($options) + { + if (is_string($options)) { + $options = [$options]; + } elseif (! is_array($options)) { + throw new Exception\InvalidArgumentException('False parameter given'); + } + + $known = hash_algos(); + if (! isset($options['algorithm'])) { + $algorithm = $this->options['algorithm']; + } else { + $algorithm = $options['algorithm']; + unset($options['algorithm']); + } + + if (! in_array($algorithm, $known)) { + throw new Exception\InvalidArgumentException("Unknown algorithm '{$algorithm}'"); + } + + foreach ($options as $value) { + if (! is_string($value)) { + throw new Exception\InvalidArgumentException(sprintf( + 'Hash must be a string, %s received', + is_object($value) ? get_class($value) : gettype($value) + )); + } + $this->options['hash'][$value] = $algorithm; + } + + return $this; + } + + /** + * Returns true if and only if the given file confirms the set hash + * + * @param string|array $value File to check for hash + * @param array $file File data from \Laminas\File\Transfer\Transfer (optional) + * @return bool + */ + public function isValid($value, $file = null) + { + $fileInfo = $this->getFileInfo($value, $file); + + $this->setValue($fileInfo['filename']); + + // Is file readable ? + if (empty($fileInfo['file']) || false === is_readable($fileInfo['file'])) { + $this->error(self::NOT_FOUND); + return false; + } + + $algos = array_unique(array_values($this->getHash())); + foreach ($algos as $algorithm) { + $filehash = hash_file($algorithm, $fileInfo['file']); + + if ($filehash === false) { + $this->error(self::NOT_DETECTED); + return false; + } + + if (isset($this->getHash()[$filehash]) && $this->getHash()[$filehash] === $algorithm) { + return true; + } + } + + $this->error(self::DOES_NOT_MATCH); + return false; + } +} diff --git a/lib/laminas/laminas-validator/src/File/ImageSize.php b/lib/laminas/laminas-validator/src/File/ImageSize.php new file mode 100644 index 000000000..fcae69ea1 --- /dev/null +++ b/lib/laminas/laminas-validator/src/File/ImageSize.php @@ -0,0 +1,379 @@ + "Maximum allowed width for image should be '%maxwidth%' but '%width%' detected", + self::WIDTH_TOO_SMALL => "Minimum expected width for image should be '%minwidth%' but '%width%' detected", + self::HEIGHT_TOO_BIG => "Maximum allowed height for image should be '%maxheight%' but '%height%' detected", + self::HEIGHT_TOO_SMALL => "Minimum expected height for image should be '%minheight%' but '%height%' detected", + self::NOT_DETECTED => 'The size of image could not be detected', + self::NOT_READABLE => 'File is not readable or does not exist', + ]; + + /** + * @var array Error message template variables + */ + protected $messageVariables = [ + 'minwidth' => ['options' => 'minWidth'], + 'maxwidth' => ['options' => 'maxWidth'], + 'minheight' => ['options' => 'minHeight'], + 'maxheight' => ['options' => 'maxHeight'], + 'width' => 'width', + 'height' => 'height', + ]; + + /** + * Detected width + * + * @var int + */ + protected $width; + + /** + * Detected height + * + * @var int + */ + protected $height; + + /** + * Options for this validator + * + * @var array + */ + protected $options = [ + 'minWidth' => null, // Minimum image width + 'maxWidth' => null, // Maximum image width + 'minHeight' => null, // Minimum image height + 'maxHeight' => null, // Maximum image height + ]; + + /** + * Sets validator options + * + * Accepts the following option keys: + * - minheight + * - minwidth + * - maxheight + * - maxwidth + * + * @param array|\Traversable $options + */ + public function __construct($options = null) + { + if (1 < func_num_args()) { + if (! is_array($options)) { + $options = ['minWidth' => $options]; + } + + $argv = func_get_args(); + array_shift($argv); + $options['minHeight'] = array_shift($argv); + if (! empty($argv)) { + $options['maxWidth'] = array_shift($argv); + if (! empty($argv)) { + $options['maxHeight'] = array_shift($argv); + } + } + } + + parent::__construct($options); + } + + /** + * Returns the minimum allowed width + * + * @return int + */ + public function getMinWidth() + { + return $this->options['minWidth']; + } + + /** + * Sets the minimum allowed width + * + * @param int $minWidth + * @throws Exception\InvalidArgumentException When minwidth is greater than maxwidth + * @return $this Provides a fluid interface + */ + public function setMinWidth($minWidth) + { + if (($this->getMaxWidth() !== null) && ($minWidth > $this->getMaxWidth())) { + throw new Exception\InvalidArgumentException( + 'The minimum image width must be less than or equal to the ' + . " maximum image width, but {$minWidth} > {$this->getMaxWidth()}" + ); + } + + $this->options['minWidth'] = (int) $minWidth; + return $this; + } + + /** + * Returns the maximum allowed width + * + * @return int + */ + public function getMaxWidth() + { + return $this->options['maxWidth']; + } + + /** + * Sets the maximum allowed width + * + * @param int $maxWidth + * @throws Exception\InvalidArgumentException When maxwidth is less than minwidth + * @return $this Provides a fluid interface + */ + public function setMaxWidth($maxWidth) + { + if (($this->getMinWidth() !== null) && ($maxWidth < $this->getMinWidth())) { + throw new Exception\InvalidArgumentException( + 'The maximum image width must be greater than or equal to the ' + . "minimum image width, but {$maxWidth} < {$this->getMinWidth()}" + ); + } + + $this->options['maxWidth'] = (int) $maxWidth; + return $this; + } + + /** + * Returns the minimum allowed height + * + * @return int + */ + public function getMinHeight() + { + return $this->options['minHeight']; + } + + /** + * Sets the minimum allowed height + * + * @param int $minHeight + * @throws Exception\InvalidArgumentException When minheight is greater than maxheight + * @return $this Provides a fluid interface + */ + public function setMinHeight($minHeight) + { + if (($this->getMaxHeight() !== null) && ($minHeight > $this->getMaxHeight())) { + throw new Exception\InvalidArgumentException( + 'The minimum image height must be less than or equal to the ' + . " maximum image height, but {$minHeight} > {$this->getMaxHeight()}" + ); + } + + $this->options['minHeight'] = (int) $minHeight; + return $this; + } + + /** + * Returns the maximum allowed height + * + * @return int + */ + public function getMaxHeight() + { + return $this->options['maxHeight']; + } + + /** + * Sets the maximum allowed height + * + * @param int $maxHeight + * @throws Exception\InvalidArgumentException When maxheight is less than minheight + * @return $this Provides a fluid interface + */ + public function setMaxHeight($maxHeight) + { + if (($this->getMinHeight() !== null) && ($maxHeight < $this->getMinHeight())) { + throw new Exception\InvalidArgumentException( + 'The maximum image height must be greater than or equal to the ' + . "minimum image height, but {$maxHeight} < {$this->getMinHeight()}" + ); + } + + $this->options['maxHeight'] = (int) $maxHeight; + return $this; + } + + /** + * Returns the set minimum image sizes + * + * @return array + */ + public function getImageMin() + { + return ['minWidth' => $this->getMinWidth(), 'minHeight' => $this->getMinHeight()]; + } + + /** + * Returns the set maximum image sizes + * + * @return array + */ + public function getImageMax() + { + return ['maxWidth' => $this->getMaxWidth(), 'maxHeight' => $this->getMaxHeight()]; + } + + /** + * Returns the set image width sizes + * + * @return array + */ + public function getImageWidth() + { + return ['minWidth' => $this->getMinWidth(), 'maxWidth' => $this->getMaxWidth()]; + } + + /** + * Returns the set image height sizes + * + * @return array + */ + public function getImageHeight() + { + return ['minHeight' => $this->getMinHeight(), 'maxHeight' => $this->getMaxHeight()]; + } + + /** + * Sets the minimum image size + * + * @param array $options The minimum image dimensions + * @return $this Provides a fluent interface + */ + public function setImageMin($options) + { + $this->setOptions($options); + return $this; + } + + /** + * Sets the maximum image size + * + * @param array|\Traversable $options The maximum image dimensions + * @return $this Provides a fluent interface + */ + public function setImageMax($options) + { + $this->setOptions($options); + return $this; + } + + /** + * Sets the minimum and maximum image width + * + * @param array $options The image width dimensions + * @return $this Provides a fluent interface + */ + public function setImageWidth($options) + { + $this->setImageMin($options); + $this->setImageMax($options); + + return $this; + } + + /** + * Sets the minimum and maximum image height + * + * @param array $options The image height dimensions + * @return $this Provides a fluent interface + */ + public function setImageHeight($options) + { + $this->setImageMin($options); + $this->setImageMax($options); + + return $this; + } + + /** + * Returns true if and only if the image size of $value is at least min and + * not bigger than max + * + * @param string|array $value Real file to check for image size + * @param array $file File data from \Laminas\File\Transfer\Transfer (optional) + * @return bool + */ + public function isValid($value, $file = null) + { + $fileInfo = $this->getFileInfo($value, $file); + + $this->setValue($fileInfo['filename']); + + // Is file readable ? + if (empty($fileInfo['file']) || false === is_readable($fileInfo['file'])) { + $this->error(self::NOT_READABLE); + return false; + } + + ErrorHandler::start(); + $size = getimagesize($fileInfo['file']); + ErrorHandler::stop(); + + if (empty($size) || ($size[0] === 0) || ($size[1] === 0)) { + $this->error(self::NOT_DETECTED); + return false; + } + + $this->width = $size[0]; + $this->height = $size[1]; + if ($this->width < $this->getMinWidth()) { + $this->error(self::WIDTH_TOO_SMALL); + } + + if (($this->getMaxWidth() !== null) && ($this->getMaxWidth() < $this->width)) { + $this->error(self::WIDTH_TOO_BIG); + } + + if ($this->height < $this->getMinHeight()) { + $this->error(self::HEIGHT_TOO_SMALL); + } + + if (($this->getMaxHeight() !== null) && ($this->getMaxHeight() < $this->height)) { + $this->error(self::HEIGHT_TOO_BIG); + } + + if ($this->getMessages()) { + return false; + } + + return true; + } +} diff --git a/lib/laminas/laminas-validator/src/File/IsCompressed.php b/lib/laminas/laminas-validator/src/File/IsCompressed.php new file mode 100644 index 000000000..e5e589147 --- /dev/null +++ b/lib/laminas/laminas-validator/src/File/IsCompressed.php @@ -0,0 +1,92 @@ + "File is not compressed, '%type%' detected", + self::NOT_DETECTED => 'The mimetype could not be detected from the file', + self::NOT_READABLE => 'File is not readable or does not exist', + ]; + + /** + * Sets validator options + * + * @param string|array|Traversable $options + */ + public function __construct($options = []) + { + // http://hul.harvard.edu/ois/systems/wax/wax-public-help/mimetypes.htm + $default = [ + 'application/arj', + 'application/gnutar', + 'application/lha', + 'application/lzx', + 'application/vnd.ms-cab-compressed', + 'application/x-ace-compressed', + 'application/x-arc', + 'application/x-archive', + 'application/x-arj', + 'application/x-bzip', + 'application/x-bzip2', + 'application/x-cab-compressed', + 'application/x-compress', + 'application/x-compressed', + 'application/x-cpio', + 'application/x-debian-package', + 'application/x-eet', + 'application/x-gzip', + 'application/x-java-pack200', + 'application/x-lha', + 'application/x-lharc', + 'application/x-lzh', + 'application/x-lzma', + 'application/x-lzx', + 'application/x-rar', + 'application/x-sit', + 'application/x-stuffit', + 'application/x-tar', + 'application/zip', + 'application/x-zip', + 'application/zoo', + 'multipart/x-gzip', + ]; + + if ($options instanceof Traversable) { + $options = ArrayUtils::iteratorToArray($options); + } + + if ($options === null) { + $options = []; + } + + parent::__construct($options); + + if (! $this->getMimeType()) { + $this->setMimeType($default); + } + } +} diff --git a/lib/laminas/laminas-validator/src/File/IsImage.php b/lib/laminas/laminas-validator/src/File/IsImage.php new file mode 100644 index 000000000..5ea93601b --- /dev/null +++ b/lib/laminas/laminas-validator/src/File/IsImage.php @@ -0,0 +1,116 @@ + "File is no image, '%type%' detected", + self::NOT_DETECTED => 'The mimetype could not be detected from the file', + self::NOT_READABLE => 'File is not readable or does not exist', + ]; + + /** + * Sets validator options + * + * @param array|Traversable|string $options + */ + public function __construct($options = []) + { + // http://www.iana.org/assignments/media-types/media-types.xhtml#image + $default = [ + 'application/cdf', + 'application/dicom', + 'application/fractals', + 'application/postscript', + 'application/vnd.hp-hpgl', + 'application/vnd.oasis.opendocument.graphics', + 'application/x-cdf', + 'application/x-cmu-raster', + 'application/x-ima', + 'application/x-inventor', + 'application/x-koan', + 'application/x-portable-anymap', + 'application/x-world-x-3dmf', + 'image/bmp', + 'image/c', + 'image/cgm', + 'image/fif', + 'image/gif', + 'image/jpeg', + 'image/jpm', + 'image/jpx', + 'image/jp2', + 'image/naplps', + 'image/pjpeg', + 'image/png', + 'image/svg', + 'image/svg+xml', + 'image/tiff', + 'image/vnd.adobe.photoshop', + 'image/vnd.djvu', + 'image/vnd.fpx', + 'image/vnd.net-fpx', + 'image/webp', + 'image/x-cmu-raster', + 'image/x-cmx', + 'image/x-coreldraw', + 'image/x-cpi', + 'image/x-emf', + 'image/x-ico', + 'image/x-icon', + 'image/x-jg', + 'image/x-ms-bmp', + 'image/x-niff', + 'image/x-pict', + 'image/x-pcx', + 'image/x-png', + 'image/x-portable-anymap', + 'image/x-portable-bitmap', + 'image/x-portable-greymap', + 'image/x-portable-pixmap', + 'image/x-quicktime', + 'image/x-rgb', + 'image/x-tiff', + 'image/x-unknown', + 'image/x-windows-bmp', + 'image/x-xpmi', + ]; + + if ($options instanceof Traversable) { + $options = ArrayUtils::iteratorToArray($options); + } + + if ($options === null) { + $options = []; + } + + parent::__construct($options); + + if (! $this->getMimeType()) { + $this->setMimeType($default); + } + } +} diff --git a/lib/laminas/laminas-validator/src/File/Md5.php b/lib/laminas/laminas-validator/src/File/Md5.php new file mode 100644 index 000000000..d5cf729ae --- /dev/null +++ b/lib/laminas/laminas-validator/src/File/Md5.php @@ -0,0 +1,113 @@ + 'File does not match the given md5 hashes', + self::NOT_DETECTED => 'An md5 hash could not be evaluated for the given file', + self::NOT_FOUND => 'File is not readable or does not exist', + ]; + + /** + * Options for this validator + * + * @var string + */ + protected $options = [ + 'algorithm' => 'md5', + 'hash' => null, + ]; + + /** + * Returns all set md5 hashes + * + * @return array + */ + public function getMd5() + { + return $this->getHash(); + } + + /** + * Sets the md5 hash for one or multiple files + * + * @param string|array $options + * @return Hash Provides a fluent interface + */ + public function setMd5($options) + { + $this->setHash($options); + return $this; + } + + /** + * Adds the md5 hash for one or multiple files + * + * @param string|array $options + * @return Hash Provides a fluent interface + */ + public function addMd5($options) + { + $this->addHash($options); + return $this; + } + + /** + * Returns true if and only if the given file confirms the set hash + * + * @param string|array $value Filename to check for hash + * @param array $file File data from \Laminas\File\Transfer\Transfer (optional) + * @return bool + */ + public function isValid($value, $file = null) + { + $fileInfo = $this->getFileInfo($value, $file); + + $this->setValue($fileInfo['filename']); + + // Is file readable ? + if (empty($fileInfo['file']) || false === is_readable($fileInfo['file'])) { + $this->error(self::NOT_FOUND); + return false; + } + + $hashes = array_unique(array_keys($this->getHash())); + $filehash = hash_file('md5', $fileInfo['file']); + if ($filehash === false) { + $this->error(self::NOT_DETECTED); + return false; + } + + foreach ($hashes as $hash) { + if ($filehash === $hash) { + return true; + } + } + + $this->error(self::DOES_NOT_MATCH); + return false; + } +} diff --git a/lib/laminas/laminas-validator/src/File/MimeType.php b/lib/laminas/laminas-validator/src/File/MimeType.php new file mode 100644 index 000000000..a6cddc337 --- /dev/null +++ b/lib/laminas/laminas-validator/src/File/MimeType.php @@ -0,0 +1,402 @@ + "File has an incorrect mimetype of '%type%'", + self::NOT_DETECTED => 'The mimetype could not be detected from the file', + self::NOT_READABLE => 'File is not readable or does not exist', + ]; + + /** + * @var array + */ + protected $messageVariables = [ + 'type' => 'type', + ]; + + /** + * @var string + */ + protected $type; + + /** + * Finfo object to use + * + * @var resource + */ + protected $finfo; + + /** + * If no environment variable 'MAGIC' is set, try and autodiscover it based on common locations + * @var array + */ + protected $magicFiles = [ + '/usr/share/misc/magic', + '/usr/share/misc/magic.mime', + '/usr/share/misc/magic.mgc', + '/usr/share/mime/magic', + '/usr/share/mime/magic.mime', + '/usr/share/mime/magic.mgc', + '/usr/share/file/magic', + '/usr/share/file/magic.mime', + '/usr/share/file/magic.mgc', + ]; + + /** + * Options for this validator + * + * @var array + */ + protected $options = [ + 'enableHeaderCheck' => false, // Allow header check + 'disableMagicFile' => false, // Disable usage of magicfile + 'magicFile' => null, // Magicfile to use + 'mimeType' => null, // Mimetype to allow + ]; + + /** + * Sets validator options + * + * Mimetype to accept + * - NULL means default PHP usage by using the environment variable 'magic' + * - FALSE means disabling searching for mimetype, should be used for PHP 5.3 + * - A string is the mimetype file to use + * + * @param string|array|Traversable $options + */ + public function __construct($options = null) + { + if ($options instanceof Traversable) { + $options = ArrayUtils::iteratorToArray($options); + } elseif (is_string($options)) { + $this->setMimeType($options); + $options = []; + } elseif (is_array($options)) { + if (isset($options['magicFile'])) { + $this->setMagicFile($options['magicFile']); + unset($options['magicFile']); + } + + if (isset($options['enableHeaderCheck'])) { + $this->enableHeaderCheck($options['enableHeaderCheck']); + unset($options['enableHeaderCheck']); + } + + if (array_key_exists('mimeType', $options)) { + $this->setMimeType($options['mimeType']); + unset($options['mimeType']); + } + + // Handle cases where mimetypes are interspersed with options, or + // options are simply an array of mime types + foreach (array_keys($options) as $key) { + if (! is_int($key)) { + continue; + } + $this->addMimeType($options[$key]); + unset($options[$key]); + } + } + + parent::__construct($options); + } + + /** + * Returns the actual set magicfile + * + * @return string + */ + public function getMagicFile() + { + if (null === $this->options['magicFile']) { + $magic = getenv('magic'); + if (! empty($magic)) { + $this->setMagicFile($magic); + if ($this->options['magicFile'] === null) { + $this->options['magicFile'] = false; + } + return $this->options['magicFile']; + } + + foreach ($this->magicFiles as $file) { + try { + $this->setMagicFile($file); + } catch (Exception\ExceptionInterface $e) { + // suppressing errors which are thrown due to open_basedir restrictions + continue; + } + + if ($this->options['magicFile'] !== null) { + return $this->options['magicFile']; + } + } + + if ($this->options['magicFile'] === null) { + $this->options['magicFile'] = false; + } + } + + return $this->options['magicFile']; + } + + /** + * Sets the magicfile to use + * if null, the MAGIC constant from php is used + * if the MAGIC file is erroneous, no file will be set + * if false, the default MAGIC file from PHP will be used + * + * @param string $file + * @throws Exception\RuntimeException When finfo can not read the magicfile + * @throws Exception\InvalidArgumentException + * @throws Exception\InvalidMagicMimeFileException + * @return $this Provides fluid interface + */ + public function setMagicFile($file) + { + if ($file === false) { + $this->options['magicFile'] = false; + } elseif (empty($file)) { + $this->options['magicFile'] = null; + } elseif (! class_exists('finfo', false)) { + $this->options['magicFile'] = null; + throw new Exception\RuntimeException('Magicfile can not be set; there is no finfo extension installed'); + } elseif (! is_file($file) || ! is_readable($file)) { + throw new Exception\InvalidArgumentException(sprintf( + 'The given magicfile ("%s") could not be read', + $file + )); + } else { + ErrorHandler::start(E_NOTICE | E_WARNING); + $this->finfo = finfo_open(FILEINFO_MIME_TYPE, $file); + $error = ErrorHandler::stop(); + if (empty($this->finfo)) { + $this->finfo = null; + throw new Exception\InvalidMagicMimeFileException(sprintf( + 'The given magicfile ("%s") could not be used by ext/finfo', + $file + ), 0, $error); + } + $this->options['magicFile'] = $file; + } + + return $this; + } + + /** + * Disables usage of MagicFile + * + * @param $disable boolean False disables usage of magic file + * @return $this Provides fluid interface + */ + public function disableMagicFile($disable) + { + $this->options['disableMagicFile'] = (bool) $disable; + return $this; + } + + /** + * Is usage of MagicFile disabled? + * + * @return bool + */ + public function isMagicFileDisabled() + { + return $this->options['disableMagicFile']; + } + + /** + * Returns the Header Check option + * + * @return bool + */ + public function getHeaderCheck() + { + return $this->options['enableHeaderCheck']; + } + + /** + * Defines if the http header should be used + * Note that this is unsafe and therefor the default value is false + * + * @param bool $headerCheck + * @return $this Provides fluid interface + */ + public function enableHeaderCheck($headerCheck = true) + { + $this->options['enableHeaderCheck'] = (bool) $headerCheck; + return $this; + } + + /** + * Returns the set mimetypes + * + * @param bool $asArray Returns the values as array, when false a concatenated string is returned + * @return string|array + */ + public function getMimeType($asArray = false) + { + $asArray = (bool) $asArray; + $mimetype = (string) $this->options['mimeType']; + if ($asArray) { + $mimetype = explode(',', $mimetype); + } + + return $mimetype; + } + + /** + * Sets the mimetypes + * + * @param string|array $mimetype The mimetypes to validate + * @return $this Provides a fluent interface + */ + public function setMimeType($mimetype) + { + $this->options['mimeType'] = null; + $this->addMimeType($mimetype); + return $this; + } + + /** + * Adds the mimetypes + * + * @param string|array $mimetype The mimetypes to add for validation + * @throws Exception\InvalidArgumentException + * @return $this Provides a fluent interface + */ + public function addMimeType($mimetype) + { + $mimetypes = $this->getMimeType(true); + + if (is_string($mimetype)) { + $mimetype = explode(',', $mimetype); + } elseif (! is_array($mimetype)) { + throw new Exception\InvalidArgumentException('Invalid options to validator provided'); + } + + if (isset($mimetype['magicFile'])) { + unset($mimetype['magicFile']); + } + + foreach ($mimetype as $content) { + if (empty($content) || ! is_string($content)) { + continue; + } + $mimetypes[] = trim($content); + } + $mimetypes = array_unique($mimetypes); + + // Sanity check to ensure no empty values + foreach ($mimetypes as $key => $mt) { + if (empty($mt)) { + unset($mimetypes[$key]); + } + } + + $this->options['mimeType'] = implode(',', $mimetypes); + + return $this; + } + + /** + * Defined by Laminas\Validator\ValidatorInterface + * + * Returns true if the mimetype of the file matches the given ones. Also parts + * of mimetypes can be checked. If you give for example "image" all image + * mime types will be accepted like "image/gif", "image/jpeg" and so on. + * + * @param string|array $value Real file to check for mimetype + * @param array $file File data from \Laminas\File\Transfer\Transfer (optional) + * @return bool + */ + public function isValid($value, $file = null) + { + $fileInfo = $this->getFileInfo($value, $file, true); + + $this->setValue($fileInfo['filename']); + + // Is file readable ? + if (empty($fileInfo['file']) || false === is_readable($fileInfo['file'])) { + $this->error(static::NOT_READABLE); + return false; + } + + $mimefile = $this->getMagicFile(); + if (class_exists('finfo', false)) { + if (! $this->isMagicFileDisabled() && (! empty($mimefile) && empty($this->finfo))) { + ErrorHandler::start(E_NOTICE | E_WARNING); + $this->finfo = finfo_open(FILEINFO_MIME_TYPE, $mimefile); + ErrorHandler::stop(); + } + + if (empty($this->finfo)) { + ErrorHandler::start(E_NOTICE | E_WARNING); + $this->finfo = finfo_open(FILEINFO_MIME_TYPE); + ErrorHandler::stop(); + } + + $this->type = null; + if (! empty($this->finfo)) { + $this->type = finfo_file($this->finfo, $fileInfo['file']); + unset($this->finfo); + } + } + + if (empty($this->type) && $this->getHeaderCheck()) { + $this->type = $fileInfo['filetype']; + } + + if (empty($this->type)) { + $this->error(static::NOT_DETECTED); + return false; + } + + $mimetype = $this->getMimeType(true); + if (in_array($this->type, $mimetype)) { + return true; + } + + $types = explode('/', $this->type); + $types = array_merge($types, explode('-', $this->type)); + $types = array_merge($types, explode(';', $this->type)); + foreach ($mimetype as $mime) { + if (in_array($mime, $types)) { + return true; + } + } + + $this->error(static::FALSE_TYPE); + return false; + } +} diff --git a/lib/laminas/laminas-validator/src/File/NotExists.php b/lib/laminas/laminas-validator/src/File/NotExists.php new file mode 100644 index 000000000..7e4d36f42 --- /dev/null +++ b/lib/laminas/laminas-validator/src/File/NotExists.php @@ -0,0 +1,72 @@ + 'File exists', + ]; + + /** + * Returns true if and only if the file does not exist in the set destinations + * + * @param string|array $value Real file to check for existence + * @param array $file File data from \Laminas\File\Transfer\Transfer (optional) + * @return bool + */ + public function isValid($value, $file = null) + { + $fileInfo = $this->getFileInfo($value, $file, false, true); + + $this->setValue($fileInfo['filename']); + + $check = false; + $directories = $this->getDirectory(true); + if (! isset($directories)) { + $check = true; + if (file_exists($fileInfo['file'])) { + $this->error(self::DOES_EXIST); + return false; + } + } else { + foreach ($directories as $directory) { + if (! isset($directory) || '' === $directory) { + continue; + } + + $check = true; + if (file_exists($directory . DIRECTORY_SEPARATOR . $fileInfo['basename'])) { + $this->error(self::DOES_EXIST); + return false; + } + } + } + + if (! $check) { + $this->error(self::DOES_EXIST); + return false; + } + + return true; + } +} diff --git a/lib/laminas/laminas-validator/src/File/Sha1.php b/lib/laminas/laminas-validator/src/File/Sha1.php new file mode 100644 index 000000000..4bd62f1c1 --- /dev/null +++ b/lib/laminas/laminas-validator/src/File/Sha1.php @@ -0,0 +1,113 @@ + 'File does not match the given sha1 hashes', + self::NOT_DETECTED => 'A sha1 hash could not be evaluated for the given file', + self::NOT_FOUND => 'File is not readable or does not exist', + ]; + + /** + * Options for this validator + * + * @var string + */ + protected $options = [ + 'algorithm' => 'sha1', + 'hash' => null, + ]; + + /** + * Returns all set sha1 hashes + * + * @return array + */ + public function getSha1() + { + return $this->getHash(); + } + + /** + * Sets the sha1 hash for one or multiple files + * + * @param string|array $options + * @return Hash Provides a fluent interface + */ + public function setSha1($options) + { + $this->setHash($options); + return $this; + } + + /** + * Adds the sha1 hash for one or multiple files + * + * @param string|array $options + * @return Hash Provides a fluent interface + */ + public function addSha1($options) + { + $this->addHash($options); + return $this; + } + + /** + * Returns true if and only if the given file confirms the set hash + * + * @param string $value|array Filename to check for hash + * @param array $file File data from \Laminas\File\Transfer\Transfer (optional) + * @return bool + */ + public function isValid($value, $file = null) + { + $fileInfo = $this->getFileInfo($value, $file); + + $this->setValue($fileInfo['filename']); + + // Is file readable ? + if (empty($fileInfo['file']) || false === is_readable($fileInfo['file'])) { + $this->error(self::NOT_FOUND); + return false; + } + + $hashes = array_unique(array_keys($this->getHash())); + $filehash = hash_file('sha1', $fileInfo['file']); + if ($filehash === false) { + $this->error(self::NOT_DETECTED); + return false; + } + + foreach ($hashes as $hash) { + if ($filehash === $hash) { + return true; + } + } + + $this->error(self::DOES_NOT_MATCH); + return false; + } +} diff --git a/lib/laminas/laminas-validator/src/File/Size.php b/lib/laminas/laminas-validator/src/File/Size.php new file mode 100644 index 000000000..5f89df6e7 --- /dev/null +++ b/lib/laminas/laminas-validator/src/File/Size.php @@ -0,0 +1,355 @@ + "Maximum allowed size for file is '%max%' but '%size%' detected", + self::TOO_SMALL => "Minimum expected size for file is '%min%' but '%size%' detected", + self::NOT_FOUND => 'File is not readable or does not exist', + ]; + + /** + * @var array Error message template variables + */ + protected $messageVariables = [ + 'min' => ['options' => 'min'], + 'max' => ['options' => 'max'], + 'size' => 'size', + ]; + + /** + * Detected size + * + * @var int + */ + protected $size; + + /** + * Options for this validator + * + * @var array + */ + protected $options = [ + 'min' => null, // Minimum file size, if null there is no minimum + 'max' => null, // Maximum file size, if null there is no maximum + 'useByteString' => true, // Use byte string? + ]; + + /** + * Sets validator options + * + * If $options is an integer, it will be used as maximum file size + * As Array is accepts the following keys: + * 'min': Minimum file size + * 'max': Maximum file size + * 'useByteString': Use bytestring or real size for messages + * + * @param int|array|\Traversable $options Options for the adapter + */ + public function __construct($options = null) + { + if (is_string($options) || is_numeric($options)) { + $options = ['max' => $options]; + } + + if (1 < func_num_args()) { + $argv = func_get_args(); + array_shift($argv); + $options['max'] = array_shift($argv); + if (! empty($argv)) { + $options['useByteString'] = array_shift($argv); + } + } + + parent::__construct($options); + } + + /** + * Should messages return bytes as integer or as string in SI notation + * + * @param bool $byteString Use bytestring ? + * @return int + */ + public function useByteString($byteString = true) + { + $this->options['useByteString'] = (bool) $byteString; + return $this; + } + + /** + * Will bytestring be used? + * + * @return bool + */ + public function getByteString() + { + return $this->options['useByteString']; + } + + /** + * Returns the minimum file size + * + * @param bool $raw Whether or not to force return of the raw value (defaults off) + * @return int|string + */ + public function getMin($raw = false) + { + $min = $this->options['min']; + if (! $raw && $this->getByteString()) { + $min = $this->toByteString($min); + } + + return $min; + } + + /** + * Sets the minimum file size + * + * File size can be an integer or a byte string + * This includes 'B', 'kB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB' + * For example: 2000, 2MB, 0.2GB + * + * @param int|string $min The minimum file size + * @throws Exception\InvalidArgumentException When min is greater than max + * @return $this Provides a fluent interface + */ + public function setMin($min) + { + if (! is_string($min) && ! is_numeric($min)) { + throw new Exception\InvalidArgumentException('Invalid options to validator provided'); + } + + $min = (int) $this->fromByteString($min); + $max = $this->getMax(true); + if (($max !== null) && ($min > $max)) { + throw new Exception\InvalidArgumentException( + "The minimum must be less than or equal to the maximum file size, but $min > $max" + ); + } + + $this->options['min'] = $min; + return $this; + } + + /** + * Returns the maximum file size + * + * @param bool $raw Whether or not to force return of the raw value (defaults off) + * @return int|string + */ + public function getMax($raw = false) + { + $max = $this->options['max']; + if (! $raw && $this->getByteString()) { + $max = $this->toByteString($max); + } + + return $max; + } + + /** + * Sets the maximum file size + * + * File size can be an integer or a byte string + * This includes 'B', 'kB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB' + * For example: 2000, 2MB, 0.2GB + * + * @param int|string $max The maximum file size + * @throws Exception\InvalidArgumentException When max is smaller than min + * @return $this Provides a fluent interface + */ + public function setMax($max) + { + if (! is_string($max) && ! is_numeric($max)) { + throw new Exception\InvalidArgumentException('Invalid options to validator provided'); + } + + $max = (int) $this->fromByteString($max); + $min = $this->getMin(true); + if (($min !== null) && ($max < $min)) { + throw new Exception\InvalidArgumentException( + "The maximum must be greater than or equal to the minimum file size, but $max < $min" + ); + } + + $this->options['max'] = $max; + return $this; + } + + /** + * Retrieve current detected file size + * + * @return int + */ + protected function getSize() + { + return $this->size; + } + + /** + * Set current size + * + * @param int $size + * @return $this + */ + protected function setSize($size) + { + $this->size = $size; + return $this; + } + + /** + * Returns true if and only if the file size of $value is at least min and + * not bigger than max (when max is not null). + * + * @param string|array $value File to check for size + * @param array $file File data from \Laminas\File\Transfer\Transfer (optional) + * @return bool + */ + public function isValid($value, $file = null) + { + $fileInfo = $this->getFileInfo($value, $file); + + $this->setValue($fileInfo['filename']); + + // Is file readable ? + if (empty($fileInfo['file']) || false === is_readable($fileInfo['file'])) { + $this->error(self::NOT_FOUND); + return false; + } + + // limited to 4GB files + ErrorHandler::start(); + $size = sprintf('%u', filesize($fileInfo['file'])); + ErrorHandler::stop(); + $this->size = $size; + + // Check to see if it's smaller than min size + $min = $this->getMin(true); + $max = $this->getMax(true); + if (($min !== null) && ($size < $min)) { + if ($this->getByteString()) { + $this->options['min'] = $this->toByteString($min); + $this->size = $this->toByteString($size); + $this->error(self::TOO_SMALL); + $this->options['min'] = $min; + $this->size = $size; + } else { + $this->error(self::TOO_SMALL); + } + } + + // Check to see if it's larger than max size + if (($max !== null) && ($max < $size)) { + if ($this->getByteString()) { + $this->options['max'] = $this->toByteString($max); + $this->size = $this->toByteString($size); + $this->error(self::TOO_BIG); + $this->options['max'] = $max; + $this->size = $size; + } else { + $this->error(self::TOO_BIG); + } + } + + if ($this->getMessages()) { + return false; + } + + return true; + } + + /** + * Returns the formatted size + * + * @param int $size + * @return string + */ + protected function toByteString($size) + { + $sizes = ['B', 'kB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB']; + for ($i = 0; $size >= 1024 && $i < 9; $i++) { + $size /= 1024; + } + + return round($size, 2) . $sizes[$i]; + } + + /** + * Returns the unformatted size + * + * @param string $size + * @return int + */ + protected function fromByteString($size) + { + if (is_numeric($size)) { + return (int) $size; + } + + $type = trim(substr($size, -2, 1)); + + $value = substr($size, 0, -1); + if (! is_numeric($value)) { + $value = trim(substr($value, 0, -1)); + } + + switch (strtoupper($type)) { + case 'Y': + $value *= 1024 * 1024 * 1024 * 1024 * 1024 * 1024 * 1024 * 1024; + break; + case 'Z': + $value *= 1024 * 1024 * 1024 * 1024 * 1024 * 1024 * 1024; + break; + case 'E': + $value *= 1024 * 1024 * 1024 * 1024 * 1024 * 1024; + break; + case 'P': + $value *= 1024 * 1024 * 1024 * 1024 * 1024; + break; + case 'T': + $value *= 1024 * 1024 * 1024 * 1024; + break; + case 'G': + $value *= 1024 * 1024 * 1024; + break; + case 'M': + $value *= 1024 * 1024; + break; + case 'K': + $value *= 1024; + break; + default: + break; + } + + return $value; + } +} diff --git a/lib/laminas/laminas-validator/src/File/Upload.php b/lib/laminas/laminas-validator/src/File/Upload.php new file mode 100644 index 000000000..aeae255d7 --- /dev/null +++ b/lib/laminas/laminas-validator/src/File/Upload.php @@ -0,0 +1,268 @@ + "File '%value%' exceeds upload_max_filesize directive in php.ini", + self::FORM_SIZE => "File '%value%' exceeds the MAX_FILE_SIZE directive that was " + . 'specified in the HTML form', + self::PARTIAL => "File '%value%' was only partially uploaded", + self::NO_FILE => "File '%value%' was not uploaded", + self::NO_TMP_DIR => "Missing a temporary folder to store '%value%'", + self::CANT_WRITE => "Failed to write file '%value%' to disk", + self::EXTENSION => "A PHP extension stopped uploading the file '%value%'", + self::ATTACK => "File '%value%' was illegally uploaded. This could be a possible attack", + self::FILE_NOT_FOUND => "File '%value%' was not found", + self::UNKNOWN => "Unknown error while uploading file '%value%'", + ]; + + protected $options = [ + 'files' => [], + ]; + + /** + * Sets validator options + * + * The array $files must be given in syntax of Laminas\File\Transfer\Transfer to be checked + * If no files are given the $_FILES array will be used automatically. + * NOTE: This validator will only work with HTTP POST uploads! + * + * @param array|\Traversable $options Array of files in syntax of \Laminas\File\Transfer\Transfer + */ + public function __construct($options = []) + { + if (is_array($options) && ! array_key_exists('files', $options)) { + $options = ['files' => $options]; + } + + parent::__construct($options); + } + + /** + * Returns the array of set files + * + * @param string $file (Optional) The file to return in detail + * @return array + * @throws Exception\InvalidArgumentException If file is not found + */ + public function getFiles($file = null) + { + if ($file !== null) { + $return = []; + foreach ($this->options['files'] as $name => $content) { + if ($name === $file) { + $return[$file] = $this->options['files'][$name]; + } + + if ($content instanceof UploadedFileInterface) { + if ($content->getClientFilename() === $file) { + $return[$name] = $this->options['files'][$name]; + } + } elseif ($content['name'] === $file) { + $return[$name] = $this->options['files'][$name]; + } + } + + if (! $return) { + throw new Exception\InvalidArgumentException("The file '$file' was not found"); + } + + return $return; + } + + return $this->options['files']; + } + + /** + * Sets the files to be checked + * + * @param array $files The files to check in syntax of \Laminas\File\Transfer\Transfer + * @return $this Provides a fluent interface + */ + public function setFiles($files = []) + { + if (null === $files + || ((is_array($files) || $files instanceof Countable) + && count($files) === 0) + ) { + $this->options['files'] = $_FILES; + } else { + $this->options['files'] = $files; + } + + if ($this->options['files'] === null) { + $this->options['files'] = []; + } + + foreach ($this->options['files'] as $file => $content) { + if (! $content instanceof UploadedFileInterface + && ! isset($content['error']) + ) { + unset($this->options['files'][$file]); + } + } + + return $this; + } + + /** + * Returns true if and only if the file was uploaded without errors + * + * @param string $value Single file to check for upload errors, when giving null the $_FILES array + * from initialization will be used + * @param mixed $file + * @return bool + */ + public function isValid($value, $file = null) + { + $files = []; + $this->setValue($value); + if (array_key_exists($value, $this->getFiles())) { + $files = array_merge($files, $this->getFiles($value)); + } else { + foreach ($this->getFiles() as $file => $content) { + if ($content instanceof UploadedFileInterface) { + if ($content->getClientFilename() === $value) { + $files = array_merge($files, $this->getFiles($file)); + } + + // PSR cannot search by tmp_name because it does not have + // a public interface to get it, only user defined name + // from form field. + continue; + } + + if (isset($content['name']) && ($content['name'] === $value)) { + $files = array_merge($files, $this->getFiles($file)); + } + + if (isset($content['tmp_name']) && ($content['tmp_name'] === $value)) { + $files = array_merge($files, $this->getFiles($file)); + } + } + } + + if (empty($files)) { + return $this->throwError($file, self::FILE_NOT_FOUND); + } + + foreach ($files as $file => $content) { + $this->value = $file; + $error = $content instanceof UploadedFileInterface + ? $content->getError() + : $content['error']; + + switch ($error) { + case 0: + if ($content instanceof UploadedFileInterface) { + // done! + break; + } + + // For standard SAPI environments, check that the upload + // was valid + if (! is_uploaded_file($content['tmp_name'])) { + $this->throwError($content, self::ATTACK); + } + break; + + case 1: + $this->throwError($content, self::INI_SIZE); + break; + + case 2: + $this->throwError($content, self::FORM_SIZE); + break; + + case 3: + $this->throwError($content, self::PARTIAL); + break; + + case 4: + $this->throwError($content, self::NO_FILE); + break; + + case 6: + $this->throwError($content, self::NO_TMP_DIR); + break; + + case 7: + $this->throwError($content, self::CANT_WRITE); + break; + + case 8: + $this->throwError($content, self::EXTENSION); + break; + + default: + $this->throwError($content, self::UNKNOWN); + break; + } + } + + if ($this->getMessages()) { + return false; + } + + return true; + } + + /** + * Throws an error of the given type + * + * @param array|string|UploadedFileInterface $file + * @param string $errorType + * @return false + */ + protected function throwError($file, $errorType) + { + if ($file !== null) { + if (is_array($file)) { + if (array_key_exists('name', $file)) { + $this->value = $file['name']; + } + } elseif (is_string($file)) { + $this->value = $file; + } elseif ($file instanceof UploadedFileInterface) { + $this->value = $file->getClientFilename(); + } + } + + $this->error($errorType); + return false; + } +} diff --git a/lib/laminas/laminas-validator/src/File/UploadFile.php b/lib/laminas/laminas-validator/src/File/UploadFile.php new file mode 100644 index 000000000..58f16368f --- /dev/null +++ b/lib/laminas/laminas-validator/src/File/UploadFile.php @@ -0,0 +1,168 @@ + 'The uploaded file exceeds the upload_max_filesize directive in php.ini', + self::FORM_SIZE => 'The uploaded file exceeds the MAX_FILE_SIZE directive that was ' + . 'specified in the HTML form', + self::PARTIAL => 'The uploaded file was only partially uploaded', + self::NO_FILE => 'No file was uploaded', + self::NO_TMP_DIR => 'Missing a temporary folder', + self::CANT_WRITE => 'Failed to write file to disk', + self::EXTENSION => 'A PHP extension stopped the file upload', + self::ATTACK => 'File was illegally uploaded. This could be a possible attack', + self::FILE_NOT_FOUND => 'File was not found', + self::UNKNOWN => 'Unknown error while uploading file', + ]; + + /** + * Returns true if and only if the file was uploaded without errors + * + * @param string|array|UploadedFileInterface $value File to check for upload errors + * @return bool + * @throws Exception\InvalidArgumentException + */ + public function isValid($value) + { + if (is_array($value)) { + if (! isset($value['tmp_name']) || ! isset($value['name']) || ! isset($value['error'])) { + throw new Exception\InvalidArgumentException( + 'Value array must be in $_FILES format' + ); + } + + return $this->validateUploadedFile( + $value['error'], + $value['name'], + $value['tmp_name'] + ); + } + + if ($value instanceof UploadedFileInterface) { + return $this->validatePsr7UploadedFile($value); + } + + if (is_string($value)) { + return $this->validateUploadedFile(0, basename($value), $value); + } + + $this->error(self::UNKNOWN); + return false; + } + + /** + * @param int $error UPLOAD_ERR_* constant value + * @return bool + */ + private function validateFileFromErrorCode($error) + { + switch ($error) { + case UPLOAD_ERR_OK: + return true; + + case UPLOAD_ERR_INI_SIZE: + $this->error(self::INI_SIZE); + return false; + + case UPLOAD_ERR_FORM_SIZE: + $this->error(self::FORM_SIZE); + return false; + + case UPLOAD_ERR_PARTIAL: + $this->error(self::PARTIAL); + return false; + + case UPLOAD_ERR_NO_FILE: + $this->error(self::NO_FILE); + return false; + + case UPLOAD_ERR_NO_TMP_DIR: + $this->error(self::NO_TMP_DIR); + return false; + + case UPLOAD_ERR_CANT_WRITE: + $this->error(self::CANT_WRITE); + return false; + + case UPLOAD_ERR_EXTENSION: + $this->error(self::EXTENSION); + return false; + + default: + $this->error(self::UNKNOWN); + return false; + } + } + + /** + * @param int $error UPLOAD_ERR_* constant + * @param string $filename + * @param string $uploadedFile Name of uploaded file (gen tmp_name) + * @return bool + */ + private function validateUploadedFile($error, $filename, $uploadedFile) + { + $this->setValue($filename); + + // Normal errors can be validated normally + if ($error !== UPLOAD_ERR_OK) { + return $this->validateFileFromErrorCode($error); + } + + // Did we get no name? Is the file missing? + if (empty($uploadedFile) || false === is_file($uploadedFile)) { + $this->error(self::FILE_NOT_FOUND); + return false; + } + + // Do we have an invalid upload? + if (! is_uploaded_file($uploadedFile)) { + $this->error(self::ATTACK); + return false; + } + + return true; + } + + /** + * @return bool + */ + private function validatePsr7UploadedFile(UploadedFileInterface $uploadedFile) + { + $this->setValue($uploadedFile); + return $this->validateFileFromErrorCode($uploadedFile->getError()); + } +} diff --git a/lib/laminas/laminas-validator/src/File/WordCount.php b/lib/laminas/laminas-validator/src/File/WordCount.php new file mode 100644 index 000000000..ed0cb31a7 --- /dev/null +++ b/lib/laminas/laminas-validator/src/File/WordCount.php @@ -0,0 +1,203 @@ + "Too many words, maximum '%max%' are allowed but '%count%' were counted", + self::TOO_LESS => "Too few words, minimum '%min%' are expected but '%count%' were counted", + self::NOT_FOUND => 'File is not readable or does not exist', + ]; + + /** + * @var array Error message template variables + */ + protected $messageVariables = [ + 'min' => ['options' => 'min'], + 'max' => ['options' => 'max'], + 'count' => 'count', + ]; + + /** + * Word count + * + * @var int + */ + protected $count; + + /** + * Options for this validator + * + * @var array + */ + protected $options = [ + 'min' => null, // Minimum word count, if null there is no minimum word count + 'max' => null, // Maximum word count, if null there is no maximum word count + ]; + + /** + * Sets validator options + * + * Min limits the word count, when used with max=null it is the maximum word count + * It also accepts an array with the keys 'min' and 'max' + * + * If $options is an integer, it will be used as maximum word count + * As Array is accepts the following keys: + * 'min': Minimum word count + * 'max': Maximum word count + * + * @param int|array|\Traversable $options Options for the adapter + */ + public function __construct($options = null) + { + if (1 < func_num_args()) { + $args = func_get_args(); + $options = [ + 'min' => array_shift($args), + 'max' => array_shift($args), + ]; + } + + if (is_string($options) || is_numeric($options)) { + $options = ['max' => $options]; + } + + parent::__construct($options); + } + + /** + * Returns the minimum word count + * + * @return int + */ + public function getMin() + { + return $this->options['min']; + } + + /** + * Sets the minimum word count + * + * @param int|array $min The minimum word count + * @throws Exception\InvalidArgumentException When min is greater than max + * @return $this Provides a fluent interface + */ + public function setMin($min) + { + if (is_array($min) and isset($min['min'])) { + $min = $min['min']; + } + + if (! is_numeric($min)) { + throw new Exception\InvalidArgumentException('Invalid options to validator provided'); + } + + $min = (int) $min; + if (($this->getMax() !== null) && ($min > $this->getMax())) { + throw new Exception\InvalidArgumentException( + "The minimum must be less than or equal to the maximum word count, but $min > {$this->getMax()}" + ); + } + + $this->options['min'] = $min; + return $this; + } + + /** + * Returns the maximum word count + * + * @return int + */ + public function getMax() + { + return $this->options['max']; + } + + /** + * Sets the maximum file count + * + * @param int|array $max The maximum word count + * @throws Exception\InvalidArgumentException When max is smaller than min + * @return $this Provides a fluent interface + */ + public function setMax($max) + { + if (is_array($max) and isset($max['max'])) { + $max = $max['max']; + } + + if (! is_numeric($max)) { + throw new Exception\InvalidArgumentException('Invalid options to validator provided'); + } + + $max = (int) $max; + if (($this->getMin() !== null) && ($max < $this->getMin())) { + throw new Exception\InvalidArgumentException( + "The maximum must be greater than or equal to the minimum word count, but $max < {$this->getMin()}" + ); + } + + $this->options['max'] = $max; + return $this; + } + + /** + * Returns true if and only if the counted words are at least min and + * not bigger than max (when max is not null). + * + * @param string|array $value Filename to check for word count + * @param array $file File data from \Laminas\File\Transfer\Transfer (optional) + * @return bool + */ + public function isValid($value, $file = null) + { + $fileInfo = $this->getFileInfo($value, $file); + + $this->setValue($fileInfo['filename']); + + // Is file readable ? + if (empty($fileInfo['file']) || false === is_readable($fileInfo['file'])) { + $this->error(self::NOT_FOUND); + return false; + } + + $content = file_get_contents($fileInfo['file']); + $this->count = str_word_count($content); + if (($this->getMax() !== null) && ($this->count > $this->getMax())) { + $this->error(self::TOO_MUCH); + return false; + } + + if (($this->getMin() !== null) && ($this->count < $this->getMin())) { + $this->error(self::TOO_LESS); + return false; + } + + return true; + } +} diff --git a/lib/laminas/laminas-validator/src/GpsPoint.php b/lib/laminas/laminas-validator/src/GpsPoint.php new file mode 100644 index 000000000..b2ba9b960 --- /dev/null +++ b/lib/laminas/laminas-validator/src/GpsPoint.php @@ -0,0 +1,129 @@ + '%value% is out of Bounds.', + 'gpsPointConvertError' => '%value% can not converted into a Decimal Degree Value.', + 'gpsPointIncompleteCoordinate' => '%value% did not provided a complete Coordinate', + ]; + + /** + * Returns true if and only if $value meets the validation requirements + * + * If $value fails validation, then this method returns false, and + * getMessages() will return an array of messages that explain why the + * validation failed. + * + * @param mixed $value + * @return bool + * @throws Exception\RuntimeException If validation of $value is impossible + */ + public function isValid($value) + { + if (strpos($value, ',') === false) { + $this->error(GpsPoint::INCOMPLETE_COORDINATE, $value); + return false; + } + + list($lat, $long) = explode(',', $value); + + if ($this->isValidCoordinate($lat, 90.0000) && $this->isValidCoordinate($long, 180.000)) { + return true; + } + + return false; + } + + /** + * @param string $value + * @param $maxBoundary + * @return bool + */ + private function isValidCoordinate($value, $maxBoundary) + { + $this->value = $value; + + $value = $this->removeWhiteSpace($value); + if ($this->isDMSValue($value)) { + $value = $this->convertValue($value); + } else { + $value = $this->removeDegreeSign($value); + } + + if ($value === false || $value === null) { + $this->error(self::CONVERT_ERROR); + return false; + } + + $doubleLatitude = (double)$value; + + if ($doubleLatitude <= $maxBoundary && $doubleLatitude >= $maxBoundary * -1) { + return true; + } + + $this->error(self::OUT_OF_BOUNDS); + return false; + } + + /** + * Determines if the give value is a Degrees Minutes Second Definition + * + * @param $value + * @return bool + */ + private function isDMSValue($value) + { + return preg_match('/([°\'"]+[NESW])/', $value) > 0; + } + + /** + * @param string $value + * @return bool|string + */ + private function convertValue($value) + { + $matches = []; + $result = preg_match_all('/(\d{1,3})°(\d{1,2})\'(\d{1,2}[\.\d]{0,6})"[NESW]/i', $value, $matches); + + if ($result === false || $result === 0) { + return false; + } + + return $matches[1][0] + $matches[2][0] / 60 + ((double)$matches[3][0]) / 3600; + } + + /** + * @param string $value + * @return string + */ + private function removeWhiteSpace($value) + { + return preg_replace('/\s/', '', $value); + } + + /** + * @param string $value + * @return string + */ + private function removeDegreeSign($value) + { + return str_replace('°', '', $value); + } +} diff --git a/lib/laminas/laminas-validator/src/GreaterThan.php b/lib/laminas/laminas-validator/src/GreaterThan.php new file mode 100644 index 000000000..d0eb13a08 --- /dev/null +++ b/lib/laminas/laminas-validator/src/GreaterThan.php @@ -0,0 +1,157 @@ + "The input is not greater than '%min%'", + self::NOT_GREATER_INCLUSIVE => "The input is not greater than or equal to '%min%'", + ]; + + /** + * @var array + */ + protected $messageVariables = [ + 'min' => 'min', + ]; + + /** + * Minimum value + * + * @var mixed + */ + protected $min; + + /** + * Whether to do inclusive comparisons, allowing equivalence to max + * + * If false, then strict comparisons are done, and the value may equal + * the min option + * + * @var bool + */ + protected $inclusive; + + /** + * Sets validator options + * + * @param array|Traversable $options + * @throws Exception\InvalidArgumentException + */ + public function __construct($options = null) + { + if ($options instanceof Traversable) { + $options = ArrayUtils::iteratorToArray($options); + } + if (! is_array($options)) { + $options = func_get_args(); + $temp['min'] = array_shift($options); + + if (! empty($options)) { + $temp['inclusive'] = array_shift($options); + } + + $options = $temp; + } + + if (! array_key_exists('min', $options)) { + throw new Exception\InvalidArgumentException("Missing option 'min'"); + } + + if (! array_key_exists('inclusive', $options)) { + $options['inclusive'] = false; + } + + $this->setMin($options['min']) + ->setInclusive($options['inclusive']); + + parent::__construct($options); + } + + /** + * Returns the min option + * + * @return mixed + */ + public function getMin() + { + return $this->min; + } + + /** + * Sets the min option + * + * @param mixed $min + * @return $this Provides a fluent interface + */ + public function setMin($min) + { + $this->min = $min; + return $this; + } + + /** + * Returns the inclusive option + * + * @return bool + */ + public function getInclusive() + { + return $this->inclusive; + } + + /** + * Sets the inclusive option + * + * @param bool $inclusive + * @return $this Provides a fluent interface + */ + public function setInclusive($inclusive) + { + $this->inclusive = $inclusive; + return $this; + } + + /** + * Returns true if and only if $value is greater than min option + * + * @param mixed $value + * @return bool + */ + public function isValid($value) + { + $this->setValue($value); + + if ($this->inclusive) { + if ($this->min > $value) { + $this->error(self::NOT_GREATER_INCLUSIVE); + return false; + } + } else { + if ($this->min >= $value) { + $this->error(self::NOT_GREATER); + return false; + } + } + + return true; + } +} diff --git a/lib/laminas/laminas-validator/src/Hex.php b/lib/laminas/laminas-validator/src/Hex.php new file mode 100644 index 000000000..68db74112 --- /dev/null +++ b/lib/laminas/laminas-validator/src/Hex.php @@ -0,0 +1,47 @@ + 'Invalid type given. String expected', + self::NOT_HEX => 'The input contains non-hexadecimal characters', + ]; + + /** + * Returns true if and only if $value contains only hexadecimal digit characters + * + * @param string $value + * @return bool + */ + public function isValid($value) + { + if (! is_string($value) && ! is_int($value)) { + $this->error(self::INVALID); + return false; + } + + $this->setValue($value); + if (! ctype_xdigit((string) $value)) { + $this->error(self::NOT_HEX); + return false; + } + + return true; + } +} diff --git a/lib/laminas/laminas-validator/src/Hostname.php b/lib/laminas/laminas-validator/src/Hostname.php new file mode 100644 index 000000000..9a1e167ad --- /dev/null +++ b/lib/laminas/laminas-validator/src/Hostname.php @@ -0,0 +1,2283 @@ + "The input appears to be a DNS hostname but the given punycode notation cannot be decoded", + self::INVALID => "Invalid type given. String expected", + self::INVALID_DASH => "The input appears to be a DNS hostname but contains a dash in an invalid position", + self::INVALID_HOSTNAME => "The input does not match the expected structure for a DNS hostname", + self::INVALID_HOSTNAME_SCHEMA => "The input appears to be a DNS hostname but cannot match against hostname schema for TLD '%tld%'", + self::INVALID_LOCAL_NAME => "The input does not appear to be a valid local network name", + self::INVALID_URI => "The input does not appear to be a valid URI hostname", + self::IP_ADDRESS_NOT_ALLOWED => "The input appears to be an IP address, but IP addresses are not allowed", + self::LOCAL_NAME_NOT_ALLOWED => "The input appears to be a local network name but local network names are not allowed", + self::UNDECIPHERABLE_TLD => "The input appears to be a DNS hostname but cannot extract TLD part", + self::UNKNOWN_TLD => "The input appears to be a DNS hostname but cannot match TLD against known list", + ]; + // @codingStandardsIgnoreEnd + + /** + * @var array + */ + protected $messageVariables = [ + 'tld' => 'tld', + ]; + + const ALLOW_DNS = 1; // Allows Internet domain names (e.g., example.com) + const ALLOW_IP = 2; // Allows IP addresses + const ALLOW_LOCAL = 4; // Allows local network names (e.g., localhost, www.localdomain) + const ALLOW_URI = 8; // Allows URI hostnames + const ALLOW_ALL = 15; // Allows all types of hostnames + + /** + * Array of valid top-level-domains + * IanaVersion 2020033100 + * + * @see ftp://data.iana.org/TLD/tlds-alpha-by-domain.txt List of all TLDs by domain + * @see http://www.iana.org/domains/root/db/ Official list of supported TLDs + * @var array + */ + protected $validTlds = [ + 'aaa', + 'aarp', + 'abarth', + 'abb', + 'abbott', + 'abbvie', + 'abc', + 'able', + 'abogado', + 'abudhabi', + 'ac', + 'academy', + 'accenture', + 'accountant', + 'accountants', + 'aco', + 'actor', + 'ad', + 'adac', + 'ads', + 'adult', + 'ae', + 'aeg', + 'aero', + 'aetna', + 'af', + 'afamilycompany', + 'afl', + 'africa', + 'ag', + 'agakhan', + 'agency', + 'ai', + 'aig', + 'aigo', + 'airbus', + 'airforce', + 'airtel', + 'akdn', + 'al', + 'alfaromeo', + 'alibaba', + 'alipay', + 'allfinanz', + 'allstate', + 'ally', + 'alsace', + 'alstom', + 'am', + 'americanexpress', + 'americanfamily', + 'amex', + 'amfam', + 'amica', + 'amsterdam', + 'analytics', + 'android', + 'anquan', + 'anz', + 'ao', + 'aol', + 'apartments', + 'app', + 'apple', + 'aq', + 'aquarelle', + 'ar', + 'arab', + 'aramco', + 'archi', + 'army', + 'arpa', + 'art', + 'arte', + 'as', + 'asda', + 'asia', + 'associates', + 'at', + 'athleta', + 'attorney', + 'au', + 'auction', + 'audi', + 'audible', + 'audio', + 'auspost', + 'author', + 'auto', + 'autos', + 'avianca', + 'aw', + 'aws', + 'ax', + 'axa', + 'az', + 'azure', + 'ba', + 'baby', + 'baidu', + 'banamex', + 'bananarepublic', + 'band', + 'bank', + 'bar', + 'barcelona', + 'barclaycard', + 'barclays', + 'barefoot', + 'bargains', + 'baseball', + 'basketball', + 'bauhaus', + 'bayern', + 'bb', + 'bbc', + 'bbt', + 'bbva', + 'bcg', + 'bcn', + 'bd', + 'be', + 'beats', + 'beauty', + 'beer', + 'bentley', + 'berlin', + 'best', + 'bestbuy', + 'bet', + 'bf', + 'bg', + 'bh', + 'bharti', + 'bi', + 'bible', + 'bid', + 'bike', + 'bing', + 'bingo', + 'bio', + 'biz', + 'bj', + 'black', + 'blackfriday', + 'blockbuster', + 'blog', + 'bloomberg', + 'blue', + 'bm', + 'bms', + 'bmw', + 'bn', + 'bnpparibas', + 'bo', + 'boats', + 'boehringer', + 'bofa', + 'bom', + 'bond', + 'boo', + 'book', + 'booking', + 'bosch', + 'bostik', + 'boston', + 'bot', + 'boutique', + 'box', + 'br', + 'bradesco', + 'bridgestone', + 'broadway', + 'broker', + 'brother', + 'brussels', + 'bs', + 'bt', + 'budapest', + 'bugatti', + 'build', + 'builders', + 'business', + 'buy', + 'buzz', + 'bv', + 'bw', + 'by', + 'bz', + 'bzh', + 'ca', + 'cab', + 'cafe', + 'cal', + 'call', + 'calvinklein', + 'cam', + 'camera', + 'camp', + 'cancerresearch', + 'canon', + 'capetown', + 'capital', + 'capitalone', + 'car', + 'caravan', + 'cards', + 'care', + 'career', + 'careers', + 'cars', + 'casa', + 'case', + 'caseih', + 'cash', + 'casino', + 'cat', + 'catering', + 'catholic', + 'cba', + 'cbn', + 'cbre', + 'cbs', + 'cc', + 'cd', + 'ceb', + 'center', + 'ceo', + 'cern', + 'cf', + 'cfa', + 'cfd', + 'cg', + 'ch', + 'chanel', + 'channel', + 'charity', + 'chase', + 'chat', + 'cheap', + 'chintai', + 'christmas', + 'chrome', + 'church', + 'ci', + 'cipriani', + 'circle', + 'cisco', + 'citadel', + 'citi', + 'citic', + 'city', + 'cityeats', + 'ck', + 'cl', + 'claims', + 'cleaning', + 'click', + 'clinic', + 'clinique', + 'clothing', + 'cloud', + 'club', + 'clubmed', + 'cm', + 'cn', + 'co', + 'coach', + 'codes', + 'coffee', + 'college', + 'cologne', + 'com', + 'comcast', + 'commbank', + 'community', + 'company', + 'compare', + 'computer', + 'comsec', + 'condos', + 'construction', + 'consulting', + 'contact', + 'contractors', + 'cooking', + 'cookingchannel', + 'cool', + 'coop', + 'corsica', + 'country', + 'coupon', + 'coupons', + 'courses', + 'cpa', + 'cr', + 'credit', + 'creditcard', + 'creditunion', + 'cricket', + 'crown', + 'crs', + 'cruise', + 'cruises', + 'csc', + 'cu', + 'cuisinella', + 'cv', + 'cw', + 'cx', + 'cy', + 'cymru', + 'cyou', + 'cz', + 'dabur', + 'dad', + 'dance', + 'data', + 'date', + 'dating', + 'datsun', + 'day', + 'dclk', + 'dds', + 'de', + 'deal', + 'dealer', + 'deals', + 'degree', + 'delivery', + 'dell', + 'deloitte', + 'delta', + 'democrat', + 'dental', + 'dentist', + 'desi', + 'design', + 'dev', + 'dhl', + 'diamonds', + 'diet', + 'digital', + 'direct', + 'directory', + 'discount', + 'discover', + 'dish', + 'diy', + 'dj', + 'dk', + 'dm', + 'dnp', + 'do', + 'docs', + 'doctor', + 'dog', + 'domains', + 'dot', + 'download', + 'drive', + 'dtv', + 'dubai', + 'duck', + 'dunlop', + 'dupont', + 'durban', + 'dvag', + 'dvr', + 'dz', + 'earth', + 'eat', + 'ec', + 'eco', + 'edeka', + 'edu', + 'education', + 'ee', + 'eg', + 'email', + 'emerck', + 'energy', + 'engineer', + 'engineering', + 'enterprises', + 'epson', + 'equipment', + 'er', + 'ericsson', + 'erni', + 'es', + 'esq', + 'estate', + 'esurance', + 'et', + 'etisalat', + 'eu', + 'eurovision', + 'eus', + 'events', + 'exchange', + 'expert', + 'exposed', + 'express', + 'extraspace', + 'fage', + 'fail', + 'fairwinds', + 'faith', + 'family', + 'fan', + 'fans', + 'farm', + 'farmers', + 'fashion', + 'fast', + 'fedex', + 'feedback', + 'ferrari', + 'ferrero', + 'fi', + 'fiat', + 'fidelity', + 'fido', + 'film', + 'final', + 'finance', + 'financial', + 'fire', + 'firestone', + 'firmdale', + 'fish', + 'fishing', + 'fit', + 'fitness', + 'fj', + 'fk', + 'flickr', + 'flights', + 'flir', + 'florist', + 'flowers', + 'fly', + 'fm', + 'fo', + 'foo', + 'food', + 'foodnetwork', + 'football', + 'ford', + 'forex', + 'forsale', + 'forum', + 'foundation', + 'fox', + 'fr', + 'free', + 'fresenius', + 'frl', + 'frogans', + 'frontdoor', + 'frontier', + 'ftr', + 'fujitsu', + 'fujixerox', + 'fun', + 'fund', + 'furniture', + 'futbol', + 'fyi', + 'ga', + 'gal', + 'gallery', + 'gallo', + 'gallup', + 'game', + 'games', + 'gap', + 'garden', + 'gay', + 'gb', + 'gbiz', + 'gd', + 'gdn', + 'ge', + 'gea', + 'gent', + 'genting', + 'george', + 'gf', + 'gg', + 'ggee', + 'gh', + 'gi', + 'gift', + 'gifts', + 'gives', + 'giving', + 'gl', + 'glade', + 'glass', + 'gle', + 'global', + 'globo', + 'gm', + 'gmail', + 'gmbh', + 'gmo', + 'gmx', + 'gn', + 'godaddy', + 'gold', + 'goldpoint', + 'golf', + 'goo', + 'goodyear', + 'goog', + 'google', + 'gop', + 'got', + 'gov', + 'gp', + 'gq', + 'gr', + 'grainger', + 'graphics', + 'gratis', + 'green', + 'gripe', + 'grocery', + 'group', + 'gs', + 'gt', + 'gu', + 'guardian', + 'gucci', + 'guge', + 'guide', + 'guitars', + 'guru', + 'gw', + 'gy', + 'hair', + 'hamburg', + 'hangout', + 'haus', + 'hbo', + 'hdfc', + 'hdfcbank', + 'health', + 'healthcare', + 'help', + 'helsinki', + 'here', + 'hermes', + 'hgtv', + 'hiphop', + 'hisamitsu', + 'hitachi', + 'hiv', + 'hk', + 'hkt', + 'hm', + 'hn', + 'hockey', + 'holdings', + 'holiday', + 'homedepot', + 'homegoods', + 'homes', + 'homesense', + 'honda', + 'horse', + 'hospital', + 'host', + 'hosting', + 'hot', + 'hoteles', + 'hotels', + 'hotmail', + 'house', + 'how', + 'hr', + 'hsbc', + 'ht', + 'hu', + 'hughes', + 'hyatt', + 'hyundai', + 'ibm', + 'icbc', + 'ice', + 'icu', + 'id', + 'ie', + 'ieee', + 'ifm', + 'ikano', + 'il', + 'im', + 'imamat', + 'imdb', + 'immo', + 'immobilien', + 'in', + 'inc', + 'industries', + 'infiniti', + 'info', + 'ing', + 'ink', + 'institute', + 'insurance', + 'insure', + 'int', + 'intel', + 'international', + 'intuit', + 'investments', + 'io', + 'ipiranga', + 'iq', + 'ir', + 'irish', + 'is', + 'ismaili', + 'ist', + 'istanbul', + 'it', + 'itau', + 'itv', + 'iveco', + 'jaguar', + 'java', + 'jcb', + 'jcp', + 'je', + 'jeep', + 'jetzt', + 'jewelry', + 'jio', + 'jll', + 'jm', + 'jmp', + 'jnj', + 'jo', + 'jobs', + 'joburg', + 'jot', + 'joy', + 'jp', + 'jpmorgan', + 'jprs', + 'juegos', + 'juniper', + 'kaufen', + 'kddi', + 'ke', + 'kerryhotels', + 'kerrylogistics', + 'kerryproperties', + 'kfh', + 'kg', + 'kh', + 'ki', + 'kia', + 'kim', + 'kinder', + 'kindle', + 'kitchen', + 'kiwi', + 'km', + 'kn', + 'koeln', + 'komatsu', + 'kosher', + 'kp', + 'kpmg', + 'kpn', + 'kr', + 'krd', + 'kred', + 'kuokgroup', + 'kw', + 'ky', + 'kyoto', + 'kz', + 'la', + 'lacaixa', + 'lamborghini', + 'lamer', + 'lancaster', + 'lancia', + 'land', + 'landrover', + 'lanxess', + 'lasalle', + 'lat', + 'latino', + 'latrobe', + 'law', + 'lawyer', + 'lb', + 'lc', + 'lds', + 'lease', + 'leclerc', + 'lefrak', + 'legal', + 'lego', + 'lexus', + 'lgbt', + 'li', + 'lidl', + 'life', + 'lifeinsurance', + 'lifestyle', + 'lighting', + 'like', + 'lilly', + 'limited', + 'limo', + 'lincoln', + 'linde', + 'link', + 'lipsy', + 'live', + 'living', + 'lixil', + 'lk', + 'llc', + 'llp', + 'loan', + 'loans', + 'locker', + 'locus', + 'loft', + 'lol', + 'london', + 'lotte', + 'lotto', + 'love', + 'lpl', + 'lplfinancial', + 'lr', + 'ls', + 'lt', + 'ltd', + 'ltda', + 'lu', + 'lundbeck', + 'lupin', + 'luxe', + 'luxury', + 'lv', + 'ly', + 'ma', + 'macys', + 'madrid', + 'maif', + 'maison', + 'makeup', + 'man', + 'management', + 'mango', + 'map', + 'market', + 'marketing', + 'markets', + 'marriott', + 'marshalls', + 'maserati', + 'mattel', + 'mba', + 'mc', + 'mckinsey', + 'md', + 'me', + 'med', + 'media', + 'meet', + 'melbourne', + 'meme', + 'memorial', + 'men', + 'menu', + 'merckmsd', + 'metlife', + 'mg', + 'mh', + 'miami', + 'microsoft', + 'mil', + 'mini', + 'mint', + 'mit', + 'mitsubishi', + 'mk', + 'ml', + 'mlb', + 'mls', + 'mm', + 'mma', + 'mn', + 'mo', + 'mobi', + 'mobile', + 'moda', + 'moe', + 'moi', + 'mom', + 'monash', + 'money', + 'monster', + 'mormon', + 'mortgage', + 'moscow', + 'moto', + 'motorcycles', + 'mov', + 'movie', + 'mp', + 'mq', + 'mr', + 'ms', + 'msd', + 'mt', + 'mtn', + 'mtr', + 'mu', + 'museum', + 'mutual', + 'mv', + 'mw', + 'mx', + 'my', + 'mz', + 'na', + 'nab', + 'nagoya', + 'name', + 'nationwide', + 'natura', + 'navy', + 'nba', + 'nc', + 'ne', + 'nec', + 'net', + 'netbank', + 'netflix', + 'network', + 'neustar', + 'new', + 'newholland', + 'news', + 'next', + 'nextdirect', + 'nexus', + 'nf', + 'nfl', + 'ng', + 'ngo', + 'nhk', + 'ni', + 'nico', + 'nike', + 'nikon', + 'ninja', + 'nissan', + 'nissay', + 'nl', + 'no', + 'nokia', + 'northwesternmutual', + 'norton', + 'now', + 'nowruz', + 'nowtv', + 'np', + 'nr', + 'nra', + 'nrw', + 'ntt', + 'nu', + 'nyc', + 'nz', + 'obi', + 'observer', + 'off', + 'office', + 'okinawa', + 'olayan', + 'olayangroup', + 'oldnavy', + 'ollo', + 'om', + 'omega', + 'one', + 'ong', + 'onl', + 'online', + 'onyourside', + 'ooo', + 'open', + 'oracle', + 'orange', + 'org', + 'organic', + 'origins', + 'osaka', + 'otsuka', + 'ott', + 'ovh', + 'pa', + 'page', + 'panasonic', + 'paris', + 'pars', + 'partners', + 'parts', + 'party', + 'passagens', + 'pay', + 'pccw', + 'pe', + 'pet', + 'pf', + 'pfizer', + 'pg', + 'ph', + 'pharmacy', + 'phd', + 'philips', + 'phone', + 'photo', + 'photography', + 'photos', + 'physio', + 'pics', + 'pictet', + 'pictures', + 'pid', + 'pin', + 'ping', + 'pink', + 'pioneer', + 'pizza', + 'pk', + 'pl', + 'place', + 'play', + 'playstation', + 'plumbing', + 'plus', + 'pm', + 'pn', + 'pnc', + 'pohl', + 'poker', + 'politie', + 'porn', + 'post', + 'pr', + 'pramerica', + 'praxi', + 'press', + 'prime', + 'pro', + 'prod', + 'productions', + 'prof', + 'progressive', + 'promo', + 'properties', + 'property', + 'protection', + 'pru', + 'prudential', + 'ps', + 'pt', + 'pub', + 'pw', + 'pwc', + 'py', + 'qa', + 'qpon', + 'quebec', + 'quest', + 'qvc', + 'racing', + 'radio', + 'raid', + 're', + 'read', + 'realestate', + 'realtor', + 'realty', + 'recipes', + 'red', + 'redstone', + 'redumbrella', + 'rehab', + 'reise', + 'reisen', + 'reit', + 'reliance', + 'ren', + 'rent', + 'rentals', + 'repair', + 'report', + 'republican', + 'rest', + 'restaurant', + 'review', + 'reviews', + 'rexroth', + 'rich', + 'richardli', + 'ricoh', + 'rightathome', + 'ril', + 'rio', + 'rip', + 'rmit', + 'ro', + 'rocher', + 'rocks', + 'rodeo', + 'rogers', + 'room', + 'rs', + 'rsvp', + 'ru', + 'rugby', + 'ruhr', + 'run', + 'rw', + 'rwe', + 'ryukyu', + 'sa', + 'saarland', + 'safe', + 'safety', + 'sakura', + 'sale', + 'salon', + 'samsclub', + 'samsung', + 'sandvik', + 'sandvikcoromant', + 'sanofi', + 'sap', + 'sarl', + 'sas', + 'save', + 'saxo', + 'sb', + 'sbi', + 'sbs', + 'sc', + 'sca', + 'scb', + 'schaeffler', + 'schmidt', + 'scholarships', + 'school', + 'schule', + 'schwarz', + 'science', + 'scjohnson', + 'scor', + 'scot', + 'sd', + 'se', + 'search', + 'seat', + 'secure', + 'security', + 'seek', + 'select', + 'sener', + 'services', + 'ses', + 'seven', + 'sew', + 'sex', + 'sexy', + 'sfr', + 'sg', + 'sh', + 'shangrila', + 'sharp', + 'shaw', + 'shell', + 'shia', + 'shiksha', + 'shoes', + 'shop', + 'shopping', + 'shouji', + 'show', + 'showtime', + 'shriram', + 'si', + 'silk', + 'sina', + 'singles', + 'site', + 'sj', + 'sk', + 'ski', + 'skin', + 'sky', + 'skype', + 'sl', + 'sling', + 'sm', + 'smart', + 'smile', + 'sn', + 'sncf', + 'so', + 'soccer', + 'social', + 'softbank', + 'software', + 'sohu', + 'solar', + 'solutions', + 'song', + 'sony', + 'soy', + 'space', + 'sport', + 'spot', + 'spreadbetting', + 'sr', + 'srl', + 'ss', + 'st', + 'stada', + 'staples', + 'star', + 'statebank', + 'statefarm', + 'stc', + 'stcgroup', + 'stockholm', + 'storage', + 'store', + 'stream', + 'studio', + 'study', + 'style', + 'su', + 'sucks', + 'supplies', + 'supply', + 'support', + 'surf', + 'surgery', + 'suzuki', + 'sv', + 'swatch', + 'swiftcover', + 'swiss', + 'sx', + 'sy', + 'sydney', + 'symantec', + 'systems', + 'sz', + 'tab', + 'taipei', + 'talk', + 'taobao', + 'target', + 'tatamotors', + 'tatar', + 'tattoo', + 'tax', + 'taxi', + 'tc', + 'tci', + 'td', + 'tdk', + 'team', + 'tech', + 'technology', + 'tel', + 'temasek', + 'tennis', + 'teva', + 'tf', + 'tg', + 'th', + 'thd', + 'theater', + 'theatre', + 'tiaa', + 'tickets', + 'tienda', + 'tiffany', + 'tips', + 'tires', + 'tirol', + 'tj', + 'tjmaxx', + 'tjx', + 'tk', + 'tkmaxx', + 'tl', + 'tm', + 'tmall', + 'tn', + 'to', + 'today', + 'tokyo', + 'tools', + 'top', + 'toray', + 'toshiba', + 'total', + 'tours', + 'town', + 'toyota', + 'toys', + 'tr', + 'trade', + 'trading', + 'training', + 'travel', + 'travelchannel', + 'travelers', + 'travelersinsurance', + 'trust', + 'trv', + 'tt', + 'tube', + 'tui', + 'tunes', + 'tushu', + 'tv', + 'tvs', + 'tw', + 'tz', + 'ua', + 'ubank', + 'ubs', + 'ug', + 'uk', + 'unicom', + 'university', + 'uno', + 'uol', + 'ups', + 'us', + 'uy', + 'uz', + 'va', + 'vacations', + 'vana', + 'vanguard', + 'vc', + 've', + 'vegas', + 'ventures', + 'verisign', + 'versicherung', + 'vet', + 'vg', + 'vi', + 'viajes', + 'video', + 'vig', + 'viking', + 'villas', + 'vin', + 'vip', + 'virgin', + 'visa', + 'vision', + 'viva', + 'vivo', + 'vlaanderen', + 'vn', + 'vodka', + 'volkswagen', + 'volvo', + 'vote', + 'voting', + 'voto', + 'voyage', + 'vu', + 'vuelos', + 'wales', + 'walmart', + 'walter', + 'wang', + 'wanggou', + 'watch', + 'watches', + 'weather', + 'weatherchannel', + 'webcam', + 'weber', + 'website', + 'wed', + 'wedding', + 'weibo', + 'weir', + 'wf', + 'whoswho', + 'wien', + 'wiki', + 'williamhill', + 'win', + 'windows', + 'wine', + 'winners', + 'wme', + 'wolterskluwer', + 'woodside', + 'work', + 'works', + 'world', + 'wow', + 'ws', + 'wtc', + 'wtf', + 'xbox', + 'xerox', + 'xfinity', + 'xihuan', + 'xin', + 'कॉम', + 'セール', + '佛山', + 'ಭಾರತ', + '慈善', + '集团', + '在线', + '한국', + 'ଭାରତ', + '大众汽车', + '点看', + 'คอม', + 'ভাৰত', + 'ভারত', + '八卦', + 'موقع', + 'বাংলা', + '公益', + '公司', + '香格里拉', + '网站', + '移动', + '我爱你', + 'москва', + 'қаз', + 'католик', + 'онлайн', + 'сайт', + '联通', + 'срб', + 'бг', + 'бел', + 'קום', + '时尚', + '微博', + '淡马锡', + 'ファッション', + 'орг', + 'नेट', + 'ストア', + '삼성', + 'சிங்கப்பூர்', + '商标', + '商店', + '商城', + 'дети', + 'мкд', + 'ею', + 'ポイント', + '新闻', + '工行', + '家電', + 'كوم', + '中文网', + '中信', + '中国', + '中國', + '娱乐', + '谷歌', + 'భారత్', + 'ලංකා', + '電訊盈科', + '购物', + 'クラウド', + 'ભારત', + '通販', + 'भारतम्', + 'भारत', + 'भारोत', + '网店', + 'संगठन', + '餐厅', + '网络', + 'ком', + 'укр', + '香港', + '诺基亚', + '食品', + '飞利浦', + '台湾', + '台灣', + '手表', + '手机', + 'мон', + 'الجزائر', + 'عمان', + 'ارامكو', + 'ایران', + 'العليان', + 'اتصالات', + 'امارات', + 'بازار', + 'موريتانيا', + 'پاکستان', + 'الاردن', + 'بارت', + 'بھارت', + 'المغرب', + 'ابوظبي', + 'البحرين', + 'السعودية', + 'ڀارت', + 'كاثوليك', + 'سودان', + 'همراه', + 'عراق', + 'مليسيا', + '澳門', + '닷컴', + '政府', + 'شبكة', + 'بيتك', + 'عرب', + 'გე', + '机构', + '组织机构', + '健康', + 'ไทย', + 'سورية', + '招聘', + 'рус', + 'рф', + '珠宝', + 'تونس', + '大拿', + 'ລາວ', + 'みんな', + 'グーグル', + 'ευ', + 'ελ', + '世界', + '書籍', + 'ഭാരതം', + 'ਭਾਰਤ', + '网址', + '닷넷', + 'コム', + '天主教', + '游戏', + 'vermögensberater', + 'vermögensberatung', + '企业', + '信息', + '嘉里大酒店', + '嘉里', + 'مصر', + 'قطر', + '广东', + 'இலங்கை', + 'இந்தியா', + 'հայ', + '新加坡', + 'فلسطين', + '政务', + 'xxx', + 'xyz', + 'yachts', + 'yahoo', + 'yamaxun', + 'yandex', + 'ye', + 'yodobashi', + 'yoga', + 'yokohama', + 'you', + 'youtube', + 'yt', + 'yun', + 'za', + 'zappos', + 'zara', + 'zero', + 'zip', + 'zm', + 'zone', + 'zuerich', + 'zw', + ]; + + // @codingStandardsIgnoreStart + /** + * Array for valid Idns + * @see http://www.iana.org/domains/idn-tables/ Official list of supported IDN Chars + * (.AC) Ascension Island http://www.nic.ac/pdf/AC-IDN-Policy.pdf + * (.AR) Argentina http://www.nic.ar/faqidn.html + * (.AS) American Samoa http://www.nic.as/idn/chars.cfm + * (.AT) Austria http://www.nic.at/en/service/technical_information/idn/charset_converter/ + * (.BIZ) International http://www.iana.org/domains/idn-tables/ + * (.BR) Brazil http://registro.br/faq/faq6.html + * (.BV) Bouvett Island http://www.norid.no/domeneregistrering/idn/idn_nyetegn.en.html + * (.CAT) Catalan http://www.iana.org/domains/idn-tables/tables/cat_ca_1.0.html + * (.CH) Switzerland https://nic.switch.ch/reg/ocView.action?res=EF6GW2JBPVTG67DLNIQXU234MN6SC33JNQQGI7L6#anhang1 + * (.CL) Chile http://www.iana.org/domains/idn-tables/tables/cl_latn_1.0.html + * (.COM) International http://www.verisign.com/information-services/naming-services/internationalized-domain-names/index.html + * (.DE) Germany https://www.denic.de/en/know-how/idn-domains/idn-character-list/ + * (.DK) Danmark http://www.dk-hostmaster.dk/index.php?id=151 + * (.EE) Estonia https://www.iana.org/domains/idn-tables/tables/pl_et-pl_1.0.html + * (.ES) Spain https://www.nic.es/media/2008-05/1210147705287.pdf + * (.FI) Finland http://www.ficora.fi/en/index/palvelut/fiverkkotunnukset/aakkostenkaytto.html + * (.GR) Greece https://grweb.ics.forth.gr/CharacterTable1_en.jsp + * (.HR) Croatia https://www.dns.hr/en/portal/files/Odluka-1,2alfanum-dijak.pdf + * (.HU) Hungary http://www.domain.hu/domain/English/szabalyzat/szabalyzat.html + * (.IL) Israel http://www.isoc.org.il/domains/il-domain-rules.html + * (.INFO) International http://www.nic.info/info/idn + * (.IO) British Indian Ocean Territory http://www.nic.io/IO-IDN-Policy.pdf + * (.IR) Iran http://www.nic.ir/Allowable_Characters_dot-iran + * (.IS) Iceland https://www.isnic.is/en/domain/rules#2 + * (.KR) Korea http://www.iana.org/domains/idn-tables/tables/kr_ko-kr_1.0.html + * (.LI) Liechtenstein https://nic.switch.ch/reg/ocView.action?res=EF6GW2JBPVTG67DLNIQXU234MN6SC33JNQQGI7L6#anhang1 + * (.LT) Lithuania http://www.domreg.lt/static/doc/public/idn_symbols-en.pdf + * (.MD) Moldova http://www.register.md/ + * (.MUSEUM) International http://www.iana.org/domains/idn-tables/tables/museum_latn_1.0.html + * (.NET) International http://www.verisign.com/information-services/naming-services/internationalized-domain-names/index.html + * (.NO) Norway http://www.norid.no/domeneregistrering/idn/idn_nyetegn.en.html + * (.NU) Niue http://www.worldnames.net/ + * (.ORG) International http://www.pir.org/index.php?db=content/FAQs&tbl=FAQs_Registrant&id=2 + * (.PE) Peru https://www.nic.pe/nuevas_politicas_faq_2.php + * (.PL) Poland http://www.dns.pl/IDN/allowed_character_sets.pdf + * (.PR) Puerto Rico http://www.nic.pr/idn_rules.asp + * (.PT) Portugal https://online.dns.pt/dns_2008/do?com=DS;8216320233;111;+PAGE(4000058)+K-CAT-CODIGO(C.125)+RCNT(100); + * (.RU) Russia http://www.iana.org/domains/idn-tables/tables/ru_ru-ru_1.0.html + * (.SA) Saudi Arabia http://www.iana.org/domains/idn-tables/tables/sa_ar_1.0.html + * (.SE) Sweden http://www.iis.se/english/IDN_campaignsite.shtml?lang=en + * (.SH) Saint Helena http://www.nic.sh/SH-IDN-Policy.pdf + * (.SJ) Svalbard and Jan Mayen http://www.norid.no/domeneregistrering/idn/idn_nyetegn.en.html + * (.TH) Thailand http://www.iana.org/domains/idn-tables/tables/th_th-th_1.0.html + * (.TM) Turkmenistan http://www.nic.tm/TM-IDN-Policy.pdf + * (.TR) Turkey https://www.nic.tr/index.php + * (.UA) Ukraine http://www.iana.org/domains/idn-tables/tables/ua_cyrl_1.2.html + * (.VE) Venice http://www.iana.org/domains/idn-tables/tables/ve_es_1.0.html + * (.VN) Vietnam http://www.vnnic.vn/english/5-6-300-2-2-04-20071115.htm#1.%20Introduction + * + * @var array + */ + protected $validIdns = [ + 'AC' => [1 => '/^[\x{002d}0-9a-zà-öø-ÿāăąćĉċčďđēėęěĝġģĥħīįĵķĺļľŀłńņňŋőœŕŗřśŝşšţťŧūŭůűųŵŷźżž]{1,63}$/iu'], + 'AR' => [1 => '/^[\x{002d}0-9a-zà-ãç-êìíñ-õü]{1,63}$/iu'], + 'AS' => [1 => '/^[\x{002d}0-9a-zà-öø-ÿāăąćĉċčďđēĕėęěĝğġģĥħĩīĭįıĵķĸĺļľłńņňŋōŏőœŕŗřśŝşšţťŧũūŭůűųŵŷźż]{1,63}$/iu'], + 'AT' => [1 => '/^[\x{002d}0-9a-zà-öø-ÿœšž]{1,63}$/iu'], + 'BIZ' => 'Hostname/Biz.php', + 'BR' => [1 => '/^[\x{002d}0-9a-zà-ãçéíó-õúü]{1,63}$/iu'], + 'BV' => [1 => '/^[\x{002d}0-9a-zàáä-éêñ-ôöøüčđńŋšŧž]{1,63}$/iu'], + 'CAT' => [1 => '/^[\x{002d}0-9a-z·àç-éíïòóúü]{1,63}$/iu'], + 'CH' => [1 => '/^[\x{002d}0-9a-zà-öø-ÿœ]{1,63}$/iu'], + 'CL' => [1 => '/^[\x{002d}0-9a-záéíñóúü]{1,63}$/iu'], + 'CN' => 'Hostname/Cn.php', + 'COM' => 'Hostname/Com.php', + 'DE' => [1 => '/^[\x{002d}0-9a-záàăâåäãąāæćĉčċçďđéèĕêěëėęēğĝġģĥħíìĭîïĩįīıĵķĺľļłńňñņŋóòŏôöőõøōœĸŕřŗśŝšşßťţŧúùŭûůüűũųūŵýŷÿźžżðþ]{1,63}$/iu'], + 'DK' => [1 => '/^[\x{002d}0-9a-zäåæéöøü]{1,63}$/iu'], + 'EE' => [1 => '/^[\x{002d}0-9a-zäõöüšž]{1,63}$/iu'], + 'ES' => [1 => '/^[\x{002d}0-9a-zàáçèéíïñòóúü·]{1,63}$/iu'], + 'EU' => [1 => '/^[\x{002d}0-9a-zà-öø-ÿ]{1,63}$/iu', + 2 => '/^[\x{002d}0-9a-zāăąćĉċčďđēĕėęěĝğġģĥħĩīĭįıĵķĺļľŀłńņňʼnŋōŏőœŕŗřśŝšťŧũūŭůűųŵŷźżž]{1,63}$/iu', + 3 => '/^[\x{002d}0-9a-zșț]{1,63}$/iu', + 4 => '/^[\x{002d}0-9a-zΐάέήίΰαβγδεζηθικλμνξοπρςστυφχψωϊϋόύώ]{1,63}$/iu', + 5 => '/^[\x{002d}0-9a-zабвгдежзийклмнопрстуфхцчшщъыьэюя]{1,63}$/iu', + 6 => '/^[\x{002d}0-9a-zἀ-ἇἐ-ἕἠ-ἧἰ-ἷὀ-ὅὐ-ὗὠ-ὧὰ-ὼώᾀ-ᾇᾐ-ᾗᾠ-ᾧᾰ-ᾴᾶᾷῂῃῄῆῇῐ-ῒΐῖῗῠ-ῧῲῳῴῶῷ]{1,63}$/iu'], + 'FI' => [1 => '/^[\x{002d}0-9a-zäåö]{1,63}$/iu'], + 'GR' => [1 => '/^[\x{002d}0-9a-zΆΈΉΊΌΎ-ΡΣ-ώἀ-ἕἘ-Ἕἠ-ὅὈ-Ὅὐ-ὗὙὛὝὟ-ώᾀ-ᾴᾶ-ᾼῂῃῄῆ-ῌῐ-ΐῖ-Ίῠ-Ῥῲῳῴῶ-ῼ]{1,63}$/iu'], + 'HK' => 'Hostname/Cn.php', + 'HR' => [1 => '/^[\x{002d}0-9a-zžćčđš]{1,63}$/iu'], + 'HU' => [1 => '/^[\x{002d}0-9a-záéíóöúüőű]{1,63}$/iu'], + 'IL' => [1 => '/^[\x{002d}0-9\x{05D0}-\x{05EA}]{1,63}$/iu', + 2 => '/^[\x{002d}0-9a-z]{1,63}$/i'], + 'INFO' => [1 => '/^[\x{002d}0-9a-zäåæéöøü]{1,63}$/iu', + 2 => '/^[\x{002d}0-9a-záéíóöúüőű]{1,63}$/iu', + 3 => '/^[\x{002d}0-9a-záæéíðóöúýþ]{1,63}$/iu', + 4 => '/^[\x{AC00}-\x{D7A3}]{1,17}$/iu', + 5 => '/^[\x{002d}0-9a-zāčēģīķļņōŗšūž]{1,63}$/iu', + 6 => '/^[\x{002d}0-9a-ząčėęįšūųž]{1,63}$/iu', + 7 => '/^[\x{002d}0-9a-zóąćęłńśźż]{1,63}$/iu', + 8 => '/^[\x{002d}0-9a-záéíñóúü]{1,63}$/iu'], + 'IO' => [1 => '/^[\x{002d}0-9a-zà-öø-ÿăąāćĉčċďđĕěėęēğĝġģĥħĭĩįīıĵķĺľļłńňņŋŏőōœĸŕřŗśŝšşťţŧŭůűũųūŵŷźžż]{1,63}$/iu'], + 'IS' => [1 => '/^[\x{002d}0-9a-záéýúíóþæöð]{1,63}$/iu'], + 'IT' => [1 => '/^[\x{002d}0-9a-zàâäèéêëìîïòôöùûüæœçÿß-]{1,63}$/iu'], + 'JP' => 'Hostname/Jp.php', + 'KR' => [1 => '/^[\x{AC00}-\x{D7A3}]{1,17}$/iu'], + 'LI' => [1 => '/^[\x{002d}0-9a-zà-öø-ÿœ]{1,63}$/iu'], + 'LT' => [1 => '/^[\x{002d}0-9ąčęėįšųūž]{1,63}$/iu'], + 'MD' => [1 => '/^[\x{002d}0-9ăâîşţ]{1,63}$/iu'], + 'MUSEUM' => [1 => '/^[\x{002d}0-9a-zà-öø-ÿāăąćċčďđēėęěğġģħīįıķĺļľłńņňŋōőœŕŗřśşšţťŧūůűųŵŷźżžǎǐǒǔ\x{01E5}\x{01E7}\x{01E9}\x{01EF}ə\x{0292}ẁẃẅỳ]{1,63}$/iu'], + 'NET' => 'Hostname/Com.php', + 'NO' => [1 => '/^[\x{002d}0-9a-zàáä-éêñ-ôöøüčđńŋšŧž]{1,63}$/iu'], + 'NU' => 'Hostname/Com.php', + 'ORG' => [1 => '/^[\x{002d}0-9a-záéíñóúü]{1,63}$/iu', + 2 => '/^[\x{002d}0-9a-zóąćęłńśźż]{1,63}$/iu', + 3 => '/^[\x{002d}0-9a-záäåæéëíðóöøúüýþ]{1,63}$/iu', + 4 => '/^[\x{002d}0-9a-záéíóöúüőű]{1,63}$/iu', + 5 => '/^[\x{002d}0-9a-ząčėęįšūųž]{1,63}$/iu', + 6 => '/^[\x{AC00}-\x{D7A3}]{1,17}$/iu', + 7 => '/^[\x{002d}0-9a-zāčēģīķļņōŗšūž]{1,63}$/iu'], + 'PE' => [1 => '/^[\x{002d}0-9a-zñáéíóúü]{1,63}$/iu'], + 'PL' => [1 => '/^[\x{002d}0-9a-zāčēģīķļņōŗšūž]{1,63}$/iu', + 2 => '/^[\x{002d}а-ик-ш\x{0450}ѓѕјљњќџ]{1,63}$/iu', + 3 => '/^[\x{002d}0-9a-zâîăşţ]{1,63}$/iu', + 4 => '/^[\x{002d}0-9а-яё\x{04C2}]{1,63}$/iu', + 5 => '/^[\x{002d}0-9a-zàáâèéêìíîòóôùúûċġħż]{1,63}$/iu', + 6 => '/^[\x{002d}0-9a-zàäåæéêòóôöøü]{1,63}$/iu', + 7 => '/^[\x{002d}0-9a-zóąćęłńśźż]{1,63}$/iu', + 8 => '/^[\x{002d}0-9a-zàáâãçéêíòóôõúü]{1,63}$/iu', + 9 => '/^[\x{002d}0-9a-zâîăşţ]{1,63}$/iu', + 10 => '/^[\x{002d}0-9a-záäéíóôúýčďĺľňŕšťž]{1,63}$/iu', + 11 => '/^[\x{002d}0-9a-zçë]{1,63}$/iu', + 12 => '/^[\x{002d}0-9а-ик-шђјљњћџ]{1,63}$/iu', + 13 => '/^[\x{002d}0-9a-zćčđšž]{1,63}$/iu', + 14 => '/^[\x{002d}0-9a-zâçöûüğış]{1,63}$/iu', + 15 => '/^[\x{002d}0-9a-záéíñóúü]{1,63}$/iu', + 16 => '/^[\x{002d}0-9a-zäõöüšž]{1,63}$/iu', + 17 => '/^[\x{002d}0-9a-zĉĝĥĵŝŭ]{1,63}$/iu', + 18 => '/^[\x{002d}0-9a-zâäéëîô]{1,63}$/iu', + 19 => '/^[\x{002d}0-9a-zàáâäåæçèéêëìíîïðñòôöøùúûüýćčłńřśš]{1,63}$/iu', + 20 => '/^[\x{002d}0-9a-zäåæõöøüšž]{1,63}$/iu', + 21 => '/^[\x{002d}0-9a-zàáçèéìíòóùú]{1,63}$/iu', + 22 => '/^[\x{002d}0-9a-zàáéíóöúüőű]{1,63}$/iu', + 23 => '/^[\x{002d}0-9ΐά-ώ]{1,63}$/iu', + 24 => '/^[\x{002d}0-9a-zàáâåæçèéêëðóôöøüþœ]{1,63}$/iu', + 25 => '/^[\x{002d}0-9a-záäéíóöúüýčďěňřšťůž]{1,63}$/iu', + 26 => '/^[\x{002d}0-9a-z·àçèéíïòóúü]{1,63}$/iu', + 27 => '/^[\x{002d}0-9а-ъьюя\x{0450}\x{045D}]{1,63}$/iu', + 28 => '/^[\x{002d}0-9а-яёіў]{1,63}$/iu', + 29 => '/^[\x{002d}0-9a-ząčėęįšūųž]{1,63}$/iu', + 30 => '/^[\x{002d}0-9a-záäåæéëíðóöøúüýþ]{1,63}$/iu', + 31 => '/^[\x{002d}0-9a-zàâæçèéêëîïñôùûüÿœ]{1,63}$/iu', + 32 => '/^[\x{002d}0-9а-щъыьэюяёєіїґ]{1,63}$/iu', + 33 => '/^[\x{002d}0-9א-ת]{1,63}$/iu'], + 'PR' => [1 => '/^[\x{002d}0-9a-záéíóúñäëïüöâêîôûàèùæçœãõ]{1,63}$/iu'], + 'PT' => [1 => '/^[\x{002d}0-9a-záàâãçéêíóôõú]{1,63}$/iu'], + 'RS' => [1 => '/^[\x{002d}0-9a-zßáâäçéëíîóôöúüýăąćčďđęěĺľłńňőŕřśşšţťůűźżž]{1,63}$/iu'], + 'RU' => [1 => '/^[\x{002d}0-9а-яё]{1,63}$/iu'], + 'SA' => [1 => '/^[\x{002d}.0-9\x{0621}-\x{063A}\x{0641}-\x{064A}\x{0660}-\x{0669}]{1,63}$/iu'], + 'SE' => [1 => '/^[\x{002d}0-9a-zäåéöü]{1,63}$/iu'], + 'SH' => [1 => '/^[\x{002d}0-9a-zà-öø-ÿăąāćĉčċďđĕěėęēğĝġģĥħĭĩįīıĵķĺľļłńňņŋŏőōœĸŕřŗśŝšşťţŧŭůűũųūŵŷźžż]{1,63}$/iu'], + 'SI' => [ + 1 => '/^[\x{002d}0-9a-zà-öø-ÿ]{1,63}$/iu', + 2 => '/^[\x{002d}0-9a-zāăąćĉċčďđēĕėęěĝğġģĥħĩīĭįıĵķĺļľŀłńņňʼnŋōŏőœŕŗřśŝšťŧũūŭůűųŵŷźżž]{1,63}$/iu', + 3 => '/^[\x{002d}0-9a-zșț]{1,63}$/iu'], + 'SJ' => [1 => '/^[\x{002d}0-9a-zàáä-éêñ-ôöøüčđńŋšŧž]{1,63}$/iu'], + 'TH' => [1 => '/^[\x{002d}0-9a-z\x{0E01}-\x{0E3A}\x{0E40}-\x{0E4D}\x{0E50}-\x{0E59}]{1,63}$/iu'], + 'TM' => [1 => '/^[\x{002d}0-9a-zà-öø-ÿāăąćĉċčďđēėęěĝġģĥħīįĵķĺļľŀłńņňŋőœŕŗřśŝşšţťŧūŭůűųŵŷźżž]{1,63}$/iu'], + 'TW' => 'Hostname/Cn.php', + 'TR' => [1 => '/^[\x{002d}0-9a-zğıüşöç]{1,63}$/iu'], + 'UA' => [1 => '/^[\x{002d}0-9a-zабвгдежзийклмнопрстуфхцчшщъыьэюяѐёђѓєѕіїјљњћќѝўџґӂʼ]{1,63}$/iu'], + 'VE' => [1 => '/^[\x{002d}0-9a-záéíóúüñ]{1,63}$/iu'], + 'VN' => [1 => '/^[ÀÁÂÃÈÉÊÌÍÒÓÔÕÙÚÝàáâãèéêìíòóôõùúýĂăĐđĨĩŨũƠơƯư\x{1EA0}-\x{1EF9}]{1,63}$/iu'], + 'мон' => [1 => '/^[\x{002d}0-9\x{0430}-\x{044F}]{1,63}$/iu'], + 'срб' => [1 => '/^[\x{002d}0-9а-ик-шђјљњћџ]{1,63}$/iu'], + 'сайт' => [1 => '/^[\x{002d}0-9а-яёіїѝйўґг]{1,63}$/iu'], + 'онлайн' => [1 => '/^[\x{002d}0-9а-яёіїѝйўґг]{1,63}$/iu'], + '中国' => 'Hostname/Cn.php', + '中國' => 'Hostname/Cn.php', + 'ලංකා' => [1 => '/^[\x{0d80}-\x{0dff}]{1,63}$/iu'], + '香港' => 'Hostname/Cn.php', + '台湾' => 'Hostname/Cn.php', + '台灣' => 'Hostname/Cn.php', + 'امارات' => [1 => '/^[\x{0621}-\x{0624}\x{0626}-\x{063A}\x{0641}\x{0642}\x{0644}-\x{0648}\x{067E}\x{0686}\x{0698}\x{06A9}\x{06AF}\x{06CC}\x{06F0}-\x{06F9}]{1,30}$/iu'], + 'الاردن' => [1 => '/^[\x{0621}-\x{0624}\x{0626}-\x{063A}\x{0641}\x{0642}\x{0644}-\x{0648}\x{067E}\x{0686}\x{0698}\x{06A9}\x{06AF}\x{06CC}\x{06F0}-\x{06F9}]{1,30}$/iu'], + 'السعودية' => [1 => '/^[\x{0621}-\x{0624}\x{0626}-\x{063A}\x{0641}\x{0642}\x{0644}-\x{0648}\x{067E}\x{0686}\x{0698}\x{06A9}\x{06AF}\x{06CC}\x{06F0}-\x{06F9}]{1,30}$/iu'], + 'ไทย' => [1 => '/^[\x{002d}0-9a-z\x{0E01}-\x{0E3A}\x{0E40}-\x{0E4D}\x{0E50}-\x{0E59}]{1,63}$/iu'], + 'рф' => [1 => '/^[\x{002d}0-9а-яё]{1,63}$/iu'], + 'تونس' => [1 => '/^[\x{0621}-\x{0624}\x{0626}-\x{063A}\x{0641}\x{0642}\x{0644}-\x{0648}\x{067E}\x{0686}\x{0698}\x{06A9}\x{06AF}\x{06CC}\x{06F0}-\x{06F9}]{1,30}$/iu'], + 'مصر' => [1 => '/^[\x{0621}-\x{0624}\x{0626}-\x{063A}\x{0641}\x{0642}\x{0644}-\x{0648}\x{067E}\x{0686}\x{0698}\x{06A9}\x{06AF}\x{06CC}\x{06F0}-\x{06F9}]{1,30}$/iu'], + 'இலங்கை' => [1 => '/^[\x{0b80}-\x{0bff}]{1,63}$/iu'], + 'فلسطين' => [1 => '/^[\x{0621}-\x{0624}\x{0626}-\x{063A}\x{0641}\x{0642}\x{0644}-\x{0648}\x{067E}\x{0686}\x{0698}\x{06A9}\x{06AF}\x{06CC}\x{06F0}-\x{06F9}]{1,30}$/iu'], + 'شبكة' => [1 => '/^[\x{0621}-\x{0624}\x{0626}-\x{063A}\x{0641}\x{0642}\x{0644}-\x{0648}\x{067E}\x{0686}\x{0698}\x{06A9}\x{06AF}\x{06CC}\x{06F0}-\x{06F9}]{1,30}$/iu'], + ]; + // @codingStandardsIgnoreEnd + + protected $idnLength = [ + 'BIZ' => [5 => 17, 11 => 15, 12 => 20], + 'CN' => [1 => 20], + 'COM' => [3 => 17, 5 => 20], + 'HK' => [1 => 15], + 'INFO' => [4 => 17], + 'KR' => [1 => 17], + 'NET' => [3 => 17, 5 => 20], + 'ORG' => [6 => 17], + 'TW' => [1 => 20], + 'امارات' => [1 => 30], + 'الاردن' => [1 => 30], + 'السعودية' => [1 => 30], + 'تونس' => [1 => 30], + 'مصر' => [1 => 30], + 'فلسطين' => [1 => 30], + 'شبكة' => [1 => 30], + '中国' => [1 => 20], + '中國' => [1 => 20], + '香港' => [1 => 20], + '台湾' => [1 => 20], + '台灣' => [1 => 20], + ]; + + protected $tld; + + /** + * Options for the hostname validator + * + * @var array + */ + protected $options = [ + 'allow' => self::ALLOW_DNS, // Allow these hostnames + 'useIdnCheck' => true, // Check IDN domains + 'useTldCheck' => true, // Check TLD elements + 'ipValidator' => null, // IP validator to use + ]; + + /** + * Sets validator options. + * + * @param int $allow OPTIONAL Set what types of hostname to allow (default ALLOW_DNS) + * @param bool $useIdnCheck OPTIONAL Set whether IDN domains are validated (default true) + * @param bool $useTldCheck Set whether the TLD element of a hostname is validated (default true) + * @param Ip $ipValidator OPTIONAL + * @see http://www.iana.org/cctld/specifications-policies-cctlds-01apr02.htm Technical Specifications for ccTLDs + */ + public function __construct($options = []) + { + if (! is_array($options)) { + $options = func_get_args(); + $temp['allow'] = array_shift($options); + if (! empty($options)) { + $temp['useIdnCheck'] = array_shift($options); + } + + if (! empty($options)) { + $temp['useTldCheck'] = array_shift($options); + } + + if (! empty($options)) { + $temp['ipValidator'] = array_shift($options); + } + + $options = $temp; + } + + if (! array_key_exists('ipValidator', $options)) { + $options['ipValidator'] = null; + } + + parent::__construct($options); + } + + /** + * Returns the set ip validator + * + * @return Ip + */ + public function getIpValidator() + { + return $this->options['ipValidator']; + } + + /** + * + * @param Ip $ipValidator OPTIONAL + * @return Hostname; + */ + public function setIpValidator(Ip $ipValidator = null) + { + if ($ipValidator === null) { + $ipValidator = new Ip(); + } + + $this->options['ipValidator'] = $ipValidator; + return $this; + } + + /** + * Returns the allow option + * + * @return int + */ + public function getAllow() + { + return $this->options['allow']; + } + + /** + * Sets the allow option + * + * @param int $allow + * @return $this Provides a fluent interface + */ + public function setAllow($allow) + { + $this->options['allow'] = $allow; + return $this; + } + + /** + * Returns the set idn option + * + * @return bool + */ + public function getIdnCheck() + { + return $this->options['useIdnCheck']; + } + + /** + * Set whether IDN domains are validated + * + * This only applies when DNS hostnames are validated + * + * @param bool $useIdnCheck Set to true to validate IDN domains + * @return $this + */ + public function useIdnCheck($useIdnCheck) + { + $this->options['useIdnCheck'] = (bool) $useIdnCheck; + return $this; + } + + /** + * Returns the set tld option + * + * @return bool + */ + public function getTldCheck() + { + return $this->options['useTldCheck']; + } + + /** + * Set whether the TLD element of a hostname is validated + * + * This only applies when DNS hostnames are validated + * + * @param bool $useTldCheck Set to true to validate TLD elements + * @return $this + */ + public function useTldCheck($useTldCheck) + { + $this->options['useTldCheck'] = (bool) $useTldCheck; + return $this; + } + + /** + * Defined by Interface + * + * Returns true if and only if the $value is a valid hostname with respect to the current allow option + * + * @param string $value + * @return bool + */ + public function isValid($value) + { + if (! is_string($value)) { + $this->error(self::INVALID); + return false; + } + + $this->setValue($value); + // Check input against IP address schema + if (((preg_match('/^[0-9.]*$/', $value) && strpos($value, '.') !== false) + || (preg_match('/^[0-9a-f:.]*$/i', $value) && strpos($value, ':') !== false)) + && $this->getIpValidator()->setTranslator($this->getTranslator())->isValid($value) + ) { + if (! ($this->getAllow() & self::ALLOW_IP)) { + $this->error(self::IP_ADDRESS_NOT_ALLOWED); + return false; + } + + return true; + } + + // Handle Regex compilation failure that may happen on .biz domain with has @ character, eg: tapi4457@hsoqvf.biz + // Technically, hostname with '@' character is invalid, so mark as invalid immediately + // @see https://github.com/laminas/laminas-validator/issues/8 + if (strpos($value, '@') !== false) { + $this->error(self::INVALID_HOSTNAME); + return false; + } + + // Local hostnames are allowed to be partial (ending '.') + if ($this->getAllow() & self::ALLOW_LOCAL) { + if (substr($value, -1) === '.') { + $value = substr($value, 0, -1); + if (substr($value, -1) === '.') { + // Empty hostnames (ending '..') are not allowed + $this->error(self::INVALID_LOCAL_NAME); + return false; + } + } + } + + $domainParts = explode('.', $value); + + // Prevent partial IP V4 addresses (ending '.') + if (count($domainParts) == 4 && preg_match('/^[0-9.a-e:.]*$/i', $value) + && $this->getIpValidator()->setTranslator($this->getTranslator())->isValid($value) + ) { + $this->error(self::INVALID_LOCAL_NAME); + } + + $utf8StrWrapper = StringUtils::getWrapper('UTF-8'); + + // Check input against DNS hostname schema + if (count($domainParts) > 1 + && $utf8StrWrapper->strlen($value) >= 4 + && $utf8StrWrapper->strlen($value) <= 254 + ) { + $status = false; + + do { + // First check TLD + $matches = []; + if (preg_match('/([^.]{2,63})$/u', end($domainParts), $matches) + || (array_key_exists(end($domainParts), $this->validIdns)) + ) { + reset($domainParts); + + // Hostname characters are: *(label dot)(label dot label); max 254 chars + // label: id-prefix [*ldh{61} id-prefix]; max 63 chars + // id-prefix: alpha / digit + // ldh: alpha / digit / dash + + $this->tld = $matches[1]; + // Decode Punycode TLD to IDN + if (strpos($this->tld, 'xn--') === 0) { + $this->tld = $this->decodePunycode(substr($this->tld, 4)); + if ($this->tld === false) { + return false; + } + } else { + $this->tld = strtoupper($this->tld); + } + + // Match TLD against known list + $removedTld = false; + if ($this->getTldCheck()) { + if (! in_array(strtolower($this->tld), $this->validTlds) + && ! in_array($this->tld, $this->validTlds)) { + $this->error(self::UNKNOWN_TLD); + $status = false; + break; + } + // We have already validated that the TLD is fine. We don't want it to go through the below + // checks as new UTF-8 TLDs will incorrectly fail if there is no IDN regex for it. + array_pop($domainParts); + $removedTld = true; + } + + /** + * Match against IDN hostnames + * Note: Keep label regex short to avoid issues with long patterns when matching IDN hostnames + * + * @see Hostname\Interface + */ + $regexChars = [0 => '/^[a-z0-9\x2d]{1,63}$/i']; + if ($this->getIdnCheck() && isset($this->validIdns[$this->tld])) { + if (is_string($this->validIdns[$this->tld])) { + $regexChars += include __DIR__ . '/' . $this->validIdns[$this->tld]; + } else { + $regexChars += $this->validIdns[$this->tld]; + } + } + + // Check each hostname part + $check = 0; + $lastDomainPart = end($domainParts); + if (! $removedTld) { + $lastDomainPart = prev($domainParts); + } + foreach ($domainParts as $domainPart) { + // Decode Punycode domain names to IDN + if (strpos($domainPart, 'xn--') === 0) { + $domainPart = $this->decodePunycode(substr($domainPart, 4)); + if ($domainPart === false) { + return false; + } + } + + // Skip following checks if domain part is empty, as it definitely is not a valid hostname then + if ($domainPart === '') { + $this->error(self::INVALID_HOSTNAME); + $status = false; + break 2; + } + + // Check dash (-) does not start, end or appear in 3rd and 4th positions + if ($utf8StrWrapper->strpos($domainPart, '-') === 0 + || ($utf8StrWrapper->strlen($domainPart) > 2 + && $utf8StrWrapper->strpos($domainPart, '-', 2) == 2 + && $utf8StrWrapper->strpos($domainPart, '-', 3) == 3 + ) + || $utf8StrWrapper->substr($domainPart, -1) === '-' + ) { + $this->error(self::INVALID_DASH); + $status = false; + break 2; + } + + // Check each domain part + $checked = false; + $isSubDomain = $domainPart != $lastDomainPart; + $partRegexChars = $isSubDomain ? ['/^[a-z0-9_\x2d]{1,63}$/i'] + $regexChars : $regexChars; + foreach ($partRegexChars as $regexKey => $regexChar) { + $status = preg_match($regexChar, $domainPart); + if ($status > 0) { + $length = 63; + if (array_key_exists($this->tld, $this->idnLength) + && array_key_exists($regexKey, $this->idnLength[$this->tld]) + ) { + $length = $this->idnLength[$this->tld]; + } + + if ($utf8StrWrapper->strlen($domainPart) > $length) { + $this->error(self::INVALID_HOSTNAME); + $status = false; + } else { + $checked = true; + break; + } + } + } + + if ($checked) { + ++$check; + } + } + + // If one of the labels doesn't match, the hostname is invalid + if ($check !== count($domainParts)) { + $this->error(self::INVALID_HOSTNAME_SCHEMA); + $status = false; + } + } else { + // Hostname not long enough + $this->error(self::UNDECIPHERABLE_TLD); + $status = false; + } + } while (false); + + // If the input passes as an Internet domain name, and domain names are allowed, then the hostname + // passes validation + if ($status && ($this->getAllow() & self::ALLOW_DNS)) { + return true; + } + } elseif ($this->getAllow() & self::ALLOW_DNS) { + $this->error(self::INVALID_HOSTNAME); + } + + // Check for URI Syntax (RFC3986) + if ($this->getAllow() & self::ALLOW_URI) { + if (preg_match("/^([a-zA-Z0-9-._~!$&\'()*+,;=]|%[[:xdigit:]]{2}){1,254}$/i", $value)) { + return true; + } + + $this->error(self::INVALID_URI); + } + + // Check input against local network name schema; last chance to pass validation + $regexLocal = '/^(([a-zA-Z0-9\x2d]{1,63}\x2e)*[a-zA-Z0-9\x2d]{1,63}[\x2e]{0,1}){1,254}$/'; + $status = preg_match($regexLocal, $value); + + // If the input passes as a local network name, and local network names are allowed, then the + // hostname passes validation + $allowLocal = $this->getAllow() & self::ALLOW_LOCAL; + if ($status && $allowLocal) { + return true; + } + + // If the input does not pass as a local network name, add a message + if (! $status) { + $this->error(self::INVALID_LOCAL_NAME); + } + + // If local network names are not allowed, add a message + if ($status && ! $allowLocal) { + $this->error(self::LOCAL_NAME_NOT_ALLOWED); + } + + return false; + } + + /** + * Decodes a punycode encoded string to it's original utf8 string + * Returns false in case of a decoding failure. + * + * @param string $encoded Punycode encoded string to decode + * @return string|false + */ + protected function decodePunycode($encoded) + { + if (! preg_match('/^[a-z0-9-]+$/i', $encoded)) { + // no punycode encoded string + $this->error(self::CANNOT_DECODE_PUNYCODE); + return false; + } + + $decoded = []; + $separator = strrpos($encoded, '-'); + if ($separator > 0) { + for ($x = 0; $x < $separator; ++$x) { + // prepare decoding matrix + $decoded[] = ord($encoded[$x]); + } + } + + $lengthd = count($decoded); + $lengthe = strlen($encoded); + + // decoding + $init = true; + $base = 72; + $index = 0; + $char = 0x80; + + for ($indexe = ($separator) ? ($separator + 1) : 0; $indexe < $lengthe; ++$lengthd) { + for ($oldIndex = $index, $pos = 1, $key = 36; 1; $key += 36) { + $hex = ord($encoded[$indexe++]); + $digit = ($hex - 48 < 10) ? $hex - 22 + : (($hex - 65 < 26) ? $hex - 65 + : (($hex - 97 < 26) ? $hex - 97 + : 36)); + + $index += $digit * $pos; + $tag = ($key <= $base) ? 1 : (($key >= $base + 26) ? 26 : ($key - $base)); + if ($digit < $tag) { + break; + } + + $pos = (int) ($pos * (36 - $tag)); + } + + $delta = intval($init ? (($index - $oldIndex) / 700) : (($index - $oldIndex) / 2)); + $delta += intval($delta / ($lengthd + 1)); + for ($key = 0; $delta > 910 / 2; $key += 36) { + $delta = intval($delta / 35); + } + + $base = intval($key + 36 * $delta / ($delta + 38)); + $init = false; + $char += (int) ($index / ($lengthd + 1)); + $index %= ($lengthd + 1); + if ($lengthd > 0) { + for ($i = $lengthd; $i > $index; $i--) { + $decoded[$i] = $decoded[($i - 1)]; + } + } + + $decoded[$index++] = $char; + } + + // convert decoded ucs4 to utf8 string + foreach ($decoded as $key => $value) { + if ($value < 128) { + $decoded[$key] = chr($value); + } elseif ($value < (1 << 11)) { + $decoded[$key] = chr(192 + ($value >> 6)); + $decoded[$key] .= chr(128 + ($value & 63)); + } elseif ($value < (1 << 16)) { + $decoded[$key] = chr(224 + ($value >> 12)); + $decoded[$key] .= chr(128 + (($value >> 6) & 63)); + $decoded[$key] .= chr(128 + ($value & 63)); + } elseif ($value < (1 << 21)) { + $decoded[$key] = chr(240 + ($value >> 18)); + $decoded[$key] .= chr(128 + (($value >> 12) & 63)); + $decoded[$key] .= chr(128 + (($value >> 6) & 63)); + $decoded[$key] .= chr(128 + ($value & 63)); + } else { + $this->error(self::CANNOT_DECODE_PUNYCODE); + return false; + } + } + + return implode($decoded); + } +} diff --git a/lib/laminas/laminas-validator/src/Hostname/Biz.php b/lib/laminas/laminas-validator/src/Hostname/Biz.php new file mode 100644 index 000000000..2dfaaf7b5 --- /dev/null +++ b/lib/laminas/laminas-validator/src/Hostname/Biz.php @@ -0,0 +1,2902 @@ + '/^[\x{002d}0-9a-zäåæéöøü]{1,63}$/iu', + 2 => '/^[\x{002d}0-9a-záéíñóúü]{1,63}$/iu', + 3 => '/^[\x{002d}0-9a-záéíóöúüőű]{1,63}$/iu', + 4 => '/^[\x{002d}0-9a-záæéíðóöúýþ]{1,63}$/iu', + 5 => '/^[\x{AC00}-\x{D7A3}]{1,17}$/iu', + 6 => '/^[\x{002d}0-9a-ząčėęįšūųž]{1,63}$/iu', + 7 => '/^[\x{002d}0-9a-zāčēģīķļņōŗšūž]{1,63}$/iu', + 8 => '/^[\x{002d}0-9a-zàáä-éêñ-ôöøüčđńŋšŧž]{1,63}$/iu', + 9 => '/^[\x{002d}0-9a-zóąćęłńśźż]{1,63}$/iu', + 10 => '/^[\x{002d}0-9a-záàâãçéêíóôõú]{1,63}$/iu', + 11 => '/^[\x{002d}0-9a-z\x{3005}-\x{3007}\x{3041}-\x{3093}\x{309D}\x{309E}\x{30A1}-\x{30F6}\x{30FC}' . + '\x{30FD}\x{30FE}\x{4E00}\x{4E01}\x{4E03}\x{4E07}\x{4E08}\x{4E09}\x{4E0A}' . + '\x{4E0B}\x{4E0D}\x{4E0E}\x{4E10}\x{4E11}\x{4E14}\x{4E15}\x{4E16}\x{4E17}' . + '\x{4E18}\x{4E19}\x{4E1E}\x{4E21}\x{4E26}\x{4E2A}\x{4E2D}\x{4E31}\x{4E32}' . + '\x{4E36}\x{4E38}\x{4E39}\x{4E3B}\x{4E3C}\x{4E3F}\x{4E42}\x{4E43}\x{4E45}' . + '\x{4E4B}\x{4E4D}\x{4E4E}\x{4E4F}\x{4E55}\x{4E56}\x{4E57}\x{4E58}\x{4E59}' . + '\x{4E5D}\x{4E5E}\x{4E5F}\x{4E62}\x{4E71}\x{4E73}\x{4E7E}\x{4E80}\x{4E82}' . + '\x{4E85}\x{4E86}\x{4E88}\x{4E89}\x{4E8A}\x{4E8B}\x{4E8C}\x{4E8E}\x{4E91}' . + '\x{4E92}\x{4E94}\x{4E95}\x{4E98}\x{4E99}\x{4E9B}\x{4E9C}\x{4E9E}\x{4E9F}' . + '\x{4EA0}\x{4EA1}\x{4EA2}\x{4EA4}\x{4EA5}\x{4EA6}\x{4EA8}\x{4EAB}\x{4EAC}' . + '\x{4EAD}\x{4EAE}\x{4EB0}\x{4EB3}\x{4EB6}\x{4EBA}\x{4EC0}\x{4EC1}\x{4EC2}' . + '\x{4EC4}\x{4EC6}\x{4EC7}\x{4ECA}\x{4ECB}\x{4ECD}\x{4ECE}\x{4ECF}\x{4ED4}' . + '\x{4ED5}\x{4ED6}\x{4ED7}\x{4ED8}\x{4ED9}\x{4EDD}\x{4EDE}\x{4EDF}\x{4EE3}' . + '\x{4EE4}\x{4EE5}\x{4EED}\x{4EEE}\x{4EF0}\x{4EF2}\x{4EF6}\x{4EF7}\x{4EFB}' . + '\x{4F01}\x{4F09}\x{4F0A}\x{4F0D}\x{4F0E}\x{4F0F}\x{4F10}\x{4F11}\x{4F1A}' . + '\x{4F1C}\x{4F1D}\x{4F2F}\x{4F30}\x{4F34}\x{4F36}\x{4F38}\x{4F3A}\x{4F3C}' . + '\x{4F3D}\x{4F43}\x{4F46}\x{4F47}\x{4F4D}\x{4F4E}\x{4F4F}\x{4F50}\x{4F51}' . + '\x{4F53}\x{4F55}\x{4F57}\x{4F59}\x{4F5A}\x{4F5B}\x{4F5C}\x{4F5D}\x{4F5E}' . + '\x{4F69}\x{4F6F}\x{4F70}\x{4F73}\x{4F75}\x{4F76}\x{4F7B}\x{4F7C}\x{4F7F}' . + '\x{4F83}\x{4F86}\x{4F88}\x{4F8B}\x{4F8D}\x{4F8F}\x{4F91}\x{4F96}\x{4F98}' . + '\x{4F9B}\x{4F9D}\x{4FA0}\x{4FA1}\x{4FAB}\x{4FAD}\x{4FAE}\x{4FAF}\x{4FB5}' . + '\x{4FB6}\x{4FBF}\x{4FC2}\x{4FC3}\x{4FC4}\x{4FCA}\x{4FCE}\x{4FD0}\x{4FD1}' . + '\x{4FD4}\x{4FD7}\x{4FD8}\x{4FDA}\x{4FDB}\x{4FDD}\x{4FDF}\x{4FE1}\x{4FE3}' . + '\x{4FE4}\x{4FE5}\x{4FEE}\x{4FEF}\x{4FF3}\x{4FF5}\x{4FF6}\x{4FF8}\x{4FFA}' . + '\x{4FFE}\x{5005}\x{5006}\x{5009}\x{500B}\x{500D}\x{500F}\x{5011}\x{5012}' . + '\x{5014}\x{5016}\x{5019}\x{501A}\x{501F}\x{5021}\x{5023}\x{5024}\x{5025}' . + '\x{5026}\x{5028}\x{5029}\x{502A}\x{502B}\x{502C}\x{502D}\x{5036}\x{5039}' . + '\x{5043}\x{5047}\x{5048}\x{5049}\x{504F}\x{5050}\x{5055}\x{5056}\x{505A}' . + '\x{505C}\x{5065}\x{506C}\x{5072}\x{5074}\x{5075}\x{5076}\x{5078}\x{507D}' . + '\x{5080}\x{5085}\x{508D}\x{5091}\x{5098}\x{5099}\x{509A}\x{50AC}\x{50AD}' . + '\x{50B2}\x{50B3}\x{50B4}\x{50B5}\x{50B7}\x{50BE}\x{50C2}\x{50C5}\x{50C9}' . + '\x{50CA}\x{50CD}\x{50CF}\x{50D1}\x{50D5}\x{50D6}\x{50DA}\x{50DE}\x{50E3}' . + '\x{50E5}\x{50E7}\x{50ED}\x{50EE}\x{50F5}\x{50F9}\x{50FB}\x{5100}\x{5101}' . + '\x{5102}\x{5104}\x{5109}\x{5112}\x{5114}\x{5115}\x{5116}\x{5118}\x{511A}' . + '\x{511F}\x{5121}\x{512A}\x{5132}\x{5137}\x{513A}\x{513B}\x{513C}\x{513F}' . + '\x{5140}\x{5141}\x{5143}\x{5144}\x{5145}\x{5146}\x{5147}\x{5148}\x{5149}' . + '\x{514B}\x{514C}\x{514D}\x{514E}\x{5150}\x{5152}\x{5154}\x{515A}\x{515C}' . + '\x{5162}\x{5165}\x{5168}\x{5169}\x{516A}\x{516B}\x{516C}\x{516D}\x{516E}' . + '\x{5171}\x{5175}\x{5176}\x{5177}\x{5178}\x{517C}\x{5180}\x{5182}\x{5185}' . + '\x{5186}\x{5189}\x{518A}\x{518C}\x{518D}\x{518F}\x{5190}\x{5191}\x{5192}' . + '\x{5193}\x{5195}\x{5196}\x{5197}\x{5199}\x{51A0}\x{51A2}\x{51A4}\x{51A5}' . + '\x{51A6}\x{51A8}\x{51A9}\x{51AA}\x{51AB}\x{51AC}\x{51B0}\x{51B1}\x{51B2}' . + '\x{51B3}\x{51B4}\x{51B5}\x{51B6}\x{51B7}\x{51BD}\x{51C4}\x{51C5}\x{51C6}' . + '\x{51C9}\x{51CB}\x{51CC}\x{51CD}\x{51D6}\x{51DB}\x{51DC}\x{51DD}\x{51E0}' . + '\x{51E1}\x{51E6}\x{51E7}\x{51E9}\x{51EA}\x{51ED}\x{51F0}\x{51F1}\x{51F5}' . + '\x{51F6}\x{51F8}\x{51F9}\x{51FA}\x{51FD}\x{51FE}\x{5200}\x{5203}\x{5204}' . + '\x{5206}\x{5207}\x{5208}\x{520A}\x{520B}\x{520E}\x{5211}\x{5214}\x{5217}' . + '\x{521D}\x{5224}\x{5225}\x{5227}\x{5229}\x{522A}\x{522E}\x{5230}\x{5233}' . + '\x{5236}\x{5237}\x{5238}\x{5239}\x{523A}\x{523B}\x{5243}\x{5244}\x{5247}' . + '\x{524A}\x{524B}\x{524C}\x{524D}\x{524F}\x{5254}\x{5256}\x{525B}\x{525E}' . + '\x{5263}\x{5264}\x{5265}\x{5269}\x{526A}\x{526F}\x{5270}\x{5271}\x{5272}' . + '\x{5273}\x{5274}\x{5275}\x{527D}\x{527F}\x{5283}\x{5287}\x{5288}\x{5289}' . + '\x{528D}\x{5291}\x{5292}\x{5294}\x{529B}\x{529F}\x{52A0}\x{52A3}\x{52A9}' . + '\x{52AA}\x{52AB}\x{52AC}\x{52AD}\x{52B1}\x{52B4}\x{52B5}\x{52B9}\x{52BC}' . + '\x{52BE}\x{52C1}\x{52C3}\x{52C5}\x{52C7}\x{52C9}\x{52CD}\x{52D2}\x{52D5}' . + '\x{52D7}\x{52D8}\x{52D9}\x{52DD}\x{52DE}\x{52DF}\x{52E0}\x{52E2}\x{52E3}' . + '\x{52E4}\x{52E6}\x{52E7}\x{52F2}\x{52F3}\x{52F5}\x{52F8}\x{52F9}\x{52FA}' . + '\x{52FE}\x{52FF}\x{5301}\x{5302}\x{5305}\x{5306}\x{5308}\x{530D}\x{530F}' . + '\x{5310}\x{5315}\x{5316}\x{5317}\x{5319}\x{531A}\x{531D}\x{5320}\x{5321}' . + '\x{5323}\x{532A}\x{532F}\x{5331}\x{5333}\x{5338}\x{5339}\x{533A}\x{533B}' . + '\x{533F}\x{5340}\x{5341}\x{5343}\x{5345}\x{5346}\x{5347}\x{5348}\x{5349}' . + '\x{534A}\x{534D}\x{5351}\x{5352}\x{5353}\x{5354}\x{5357}\x{5358}\x{535A}' . + '\x{535C}\x{535E}\x{5360}\x{5366}\x{5369}\x{536E}\x{536F}\x{5370}\x{5371}' . + '\x{5373}\x{5374}\x{5375}\x{5377}\x{5378}\x{537B}\x{537F}\x{5382}\x{5384}' . + '\x{5396}\x{5398}\x{539A}\x{539F}\x{53A0}\x{53A5}\x{53A6}\x{53A8}\x{53A9}' . + '\x{53AD}\x{53AE}\x{53B0}\x{53B3}\x{53B6}\x{53BB}\x{53C2}\x{53C3}\x{53C8}' . + '\x{53C9}\x{53CA}\x{53CB}\x{53CC}\x{53CD}\x{53CE}\x{53D4}\x{53D6}\x{53D7}' . + '\x{53D9}\x{53DB}\x{53DF}\x{53E1}\x{53E2}\x{53E3}\x{53E4}\x{53E5}\x{53E8}' . + '\x{53E9}\x{53EA}\x{53EB}\x{53EC}\x{53ED}\x{53EE}\x{53EF}\x{53F0}\x{53F1}' . + '\x{53F2}\x{53F3}\x{53F6}\x{53F7}\x{53F8}\x{53FA}\x{5401}\x{5403}\x{5404}' . + '\x{5408}\x{5409}\x{540A}\x{540B}\x{540C}\x{540D}\x{540E}\x{540F}\x{5410}' . + '\x{5411}\x{541B}\x{541D}\x{541F}\x{5420}\x{5426}\x{5429}\x{542B}\x{542C}' . + '\x{542D}\x{542E}\x{5436}\x{5438}\x{5439}\x{543B}\x{543C}\x{543D}\x{543E}' . + '\x{5440}\x{5442}\x{5446}\x{5448}\x{5449}\x{544A}\x{544E}\x{5451}\x{545F}' . + '\x{5468}\x{546A}\x{5470}\x{5471}\x{5473}\x{5475}\x{5476}\x{5477}\x{547B}' . + '\x{547C}\x{547D}\x{5480}\x{5484}\x{5486}\x{548B}\x{548C}\x{548E}\x{548F}' . + '\x{5490}\x{5492}\x{54A2}\x{54A4}\x{54A5}\x{54A8}\x{54AB}\x{54AC}\x{54AF}' . + '\x{54B2}\x{54B3}\x{54B8}\x{54BC}\x{54BD}\x{54BE}\x{54C0}\x{54C1}\x{54C2}' . + '\x{54C4}\x{54C7}\x{54C8}\x{54C9}\x{54D8}\x{54E1}\x{54E2}\x{54E5}\x{54E6}' . + '\x{54E8}\x{54E9}\x{54ED}\x{54EE}\x{54F2}\x{54FA}\x{54FD}\x{5504}\x{5506}' . + '\x{5507}\x{550F}\x{5510}\x{5514}\x{5516}\x{552E}\x{552F}\x{5531}\x{5533}' . + '\x{5538}\x{5539}\x{553E}\x{5540}\x{5544}\x{5545}\x{5546}\x{554C}\x{554F}' . + '\x{5553}\x{5556}\x{5557}\x{555C}\x{555D}\x{5563}\x{557B}\x{557C}\x{557E}' . + '\x{5580}\x{5583}\x{5584}\x{5587}\x{5589}\x{558A}\x{558B}\x{5598}\x{5599}' . + '\x{559A}\x{559C}\x{559D}\x{559E}\x{559F}\x{55A7}\x{55A8}\x{55A9}\x{55AA}' . + '\x{55AB}\x{55AC}\x{55AE}\x{55B0}\x{55B6}\x{55C4}\x{55C5}\x{55C7}\x{55D4}' . + '\x{55DA}\x{55DC}\x{55DF}\x{55E3}\x{55E4}\x{55F7}\x{55F9}\x{55FD}\x{55FE}' . + '\x{5606}\x{5609}\x{5614}\x{5616}\x{5617}\x{5618}\x{561B}\x{5629}\x{562F}' . + '\x{5631}\x{5632}\x{5634}\x{5636}\x{5638}\x{5642}\x{564C}\x{564E}\x{5650}' . + '\x{565B}\x{5664}\x{5668}\x{566A}\x{566B}\x{566C}\x{5674}\x{5678}\x{567A}' . + '\x{5680}\x{5686}\x{5687}\x{568A}\x{568F}\x{5694}\x{56A0}\x{56A2}\x{56A5}' . + '\x{56AE}\x{56B4}\x{56B6}\x{56BC}\x{56C0}\x{56C1}\x{56C2}\x{56C3}\x{56C8}' . + '\x{56CE}\x{56D1}\x{56D3}\x{56D7}\x{56D8}\x{56DA}\x{56DB}\x{56DE}\x{56E0}' . + '\x{56E3}\x{56EE}\x{56F0}\x{56F2}\x{56F3}\x{56F9}\x{56FA}\x{56FD}\x{56FF}' . + '\x{5700}\x{5703}\x{5704}\x{5708}\x{5709}\x{570B}\x{570D}\x{570F}\x{5712}' . + '\x{5713}\x{5716}\x{5718}\x{571C}\x{571F}\x{5726}\x{5727}\x{5728}\x{572D}' . + '\x{5730}\x{5737}\x{5738}\x{573B}\x{5740}\x{5742}\x{5747}\x{574A}\x{574E}' . + '\x{574F}\x{5750}\x{5751}\x{5761}\x{5764}\x{5766}\x{5769}\x{576A}\x{577F}' . + '\x{5782}\x{5788}\x{5789}\x{578B}\x{5793}\x{57A0}\x{57A2}\x{57A3}\x{57A4}' . + '\x{57AA}\x{57B0}\x{57B3}\x{57C0}\x{57C3}\x{57C6}\x{57CB}\x{57CE}\x{57D2}' . + '\x{57D3}\x{57D4}\x{57D6}\x{57DC}\x{57DF}\x{57E0}\x{57E3}\x{57F4}\x{57F7}' . + '\x{57F9}\x{57FA}\x{57FC}\x{5800}\x{5802}\x{5805}\x{5806}\x{580A}\x{580B}' . + '\x{5815}\x{5819}\x{581D}\x{5821}\x{5824}\x{582A}\x{582F}\x{5830}\x{5831}' . + '\x{5834}\x{5835}\x{583A}\x{583D}\x{5840}\x{5841}\x{584A}\x{584B}\x{5851}' . + '\x{5852}\x{5854}\x{5857}\x{5858}\x{5859}\x{585A}\x{585E}\x{5862}\x{5869}' . + '\x{586B}\x{5870}\x{5872}\x{5875}\x{5879}\x{587E}\x{5883}\x{5885}\x{5893}' . + '\x{5897}\x{589C}\x{589F}\x{58A8}\x{58AB}\x{58AE}\x{58B3}\x{58B8}\x{58B9}' . + '\x{58BA}\x{58BB}\x{58BE}\x{58C1}\x{58C5}\x{58C7}\x{58CA}\x{58CC}\x{58D1}' . + '\x{58D3}\x{58D5}\x{58D7}\x{58D8}\x{58D9}\x{58DC}\x{58DE}\x{58DF}\x{58E4}' . + '\x{58E5}\x{58EB}\x{58EC}\x{58EE}\x{58EF}\x{58F0}\x{58F1}\x{58F2}\x{58F7}' . + '\x{58F9}\x{58FA}\x{58FB}\x{58FC}\x{58FD}\x{5902}\x{5909}\x{590A}\x{590F}' . + '\x{5910}\x{5915}\x{5916}\x{5918}\x{5919}\x{591A}\x{591B}\x{591C}\x{5922}' . + '\x{5925}\x{5927}\x{5929}\x{592A}\x{592B}\x{592C}\x{592D}\x{592E}\x{5931}' . + '\x{5932}\x{5937}\x{5938}\x{593E}\x{5944}\x{5947}\x{5948}\x{5949}\x{594E}' . + '\x{594F}\x{5950}\x{5951}\x{5954}\x{5955}\x{5957}\x{5958}\x{595A}\x{5960}' . + '\x{5962}\x{5965}\x{5967}\x{5968}\x{5969}\x{596A}\x{596C}\x{596E}\x{5973}' . + '\x{5974}\x{5978}\x{597D}\x{5981}\x{5982}\x{5983}\x{5984}\x{598A}\x{598D}' . + '\x{5993}\x{5996}\x{5999}\x{599B}\x{599D}\x{59A3}\x{59A5}\x{59A8}\x{59AC}' . + '\x{59B2}\x{59B9}\x{59BB}\x{59BE}\x{59C6}\x{59C9}\x{59CB}\x{59D0}\x{59D1}' . + '\x{59D3}\x{59D4}\x{59D9}\x{59DA}\x{59DC}\x{59E5}\x{59E6}\x{59E8}\x{59EA}' . + '\x{59EB}\x{59F6}\x{59FB}\x{59FF}\x{5A01}\x{5A03}\x{5A09}\x{5A11}\x{5A18}' . + '\x{5A1A}\x{5A1C}\x{5A1F}\x{5A20}\x{5A25}\x{5A29}\x{5A2F}\x{5A35}\x{5A36}' . + '\x{5A3C}\x{5A40}\x{5A41}\x{5A46}\x{5A49}\x{5A5A}\x{5A62}\x{5A66}\x{5A6A}' . + '\x{5A6C}\x{5A7F}\x{5A92}\x{5A9A}\x{5A9B}\x{5ABC}\x{5ABD}\x{5ABE}\x{5AC1}' . + '\x{5AC2}\x{5AC9}\x{5ACB}\x{5ACC}\x{5AD0}\x{5AD6}\x{5AD7}\x{5AE1}\x{5AE3}' . + '\x{5AE6}\x{5AE9}\x{5AFA}\x{5AFB}\x{5B09}\x{5B0B}\x{5B0C}\x{5B16}\x{5B22}' . + '\x{5B2A}\x{5B2C}\x{5B30}\x{5B32}\x{5B36}\x{5B3E}\x{5B40}\x{5B43}\x{5B45}' . + '\x{5B50}\x{5B51}\x{5B54}\x{5B55}\x{5B57}\x{5B58}\x{5B5A}\x{5B5B}\x{5B5C}' . + '\x{5B5D}\x{5B5F}\x{5B63}\x{5B64}\x{5B65}\x{5B66}\x{5B69}\x{5B6B}\x{5B70}' . + '\x{5B71}\x{5B73}\x{5B75}\x{5B78}\x{5B7A}\x{5B80}\x{5B83}\x{5B85}\x{5B87}' . + '\x{5B88}\x{5B89}\x{5B8B}\x{5B8C}\x{5B8D}\x{5B8F}\x{5B95}\x{5B97}\x{5B98}' . + '\x{5B99}\x{5B9A}\x{5B9B}\x{5B9C}\x{5B9D}\x{5B9F}\x{5BA2}\x{5BA3}\x{5BA4}' . + '\x{5BA5}\x{5BA6}\x{5BAE}\x{5BB0}\x{5BB3}\x{5BB4}\x{5BB5}\x{5BB6}\x{5BB8}' . + '\x{5BB9}\x{5BBF}\x{5BC2}\x{5BC3}\x{5BC4}\x{5BC5}\x{5BC6}\x{5BC7}\x{5BC9}' . + '\x{5BCC}\x{5BD0}\x{5BD2}\x{5BD3}\x{5BD4}\x{5BDB}\x{5BDD}\x{5BDE}\x{5BDF}' . + '\x{5BE1}\x{5BE2}\x{5BE4}\x{5BE5}\x{5BE6}\x{5BE7}\x{5BE8}\x{5BE9}\x{5BEB}' . + '\x{5BEE}\x{5BF0}\x{5BF3}\x{5BF5}\x{5BF6}\x{5BF8}\x{5BFA}\x{5BFE}\x{5BFF}' . + '\x{5C01}\x{5C02}\x{5C04}\x{5C05}\x{5C06}\x{5C07}\x{5C08}\x{5C09}\x{5C0A}' . + '\x{5C0B}\x{5C0D}\x{5C0E}\x{5C0F}\x{5C11}\x{5C13}\x{5C16}\x{5C1A}\x{5C20}' . + '\x{5C22}\x{5C24}\x{5C28}\x{5C2D}\x{5C31}\x{5C38}\x{5C39}\x{5C3A}\x{5C3B}' . + '\x{5C3C}\x{5C3D}\x{5C3E}\x{5C3F}\x{5C40}\x{5C41}\x{5C45}\x{5C46}\x{5C48}' . + '\x{5C4A}\x{5C4B}\x{5C4D}\x{5C4E}\x{5C4F}\x{5C50}\x{5C51}\x{5C53}\x{5C55}' . + '\x{5C5E}\x{5C60}\x{5C61}\x{5C64}\x{5C65}\x{5C6C}\x{5C6E}\x{5C6F}\x{5C71}' . + '\x{5C76}\x{5C79}\x{5C8C}\x{5C90}\x{5C91}\x{5C94}\x{5CA1}\x{5CA8}\x{5CA9}' . + '\x{5CAB}\x{5CAC}\x{5CB1}\x{5CB3}\x{5CB6}\x{5CB7}\x{5CB8}\x{5CBB}\x{5CBC}' . + '\x{5CBE}\x{5CC5}\x{5CC7}\x{5CD9}\x{5CE0}\x{5CE1}\x{5CE8}\x{5CE9}\x{5CEA}' . + '\x{5CED}\x{5CEF}\x{5CF0}\x{5CF6}\x{5CFA}\x{5CFB}\x{5CFD}\x{5D07}\x{5D0B}' . + '\x{5D0E}\x{5D11}\x{5D14}\x{5D15}\x{5D16}\x{5D17}\x{5D18}\x{5D19}\x{5D1A}' . + '\x{5D1B}\x{5D1F}\x{5D22}\x{5D29}\x{5D4B}\x{5D4C}\x{5D4E}\x{5D50}\x{5D52}' . + '\x{5D5C}\x{5D69}\x{5D6C}\x{5D6F}\x{5D73}\x{5D76}\x{5D82}\x{5D84}\x{5D87}' . + '\x{5D8B}\x{5D8C}\x{5D90}\x{5D9D}\x{5DA2}\x{5DAC}\x{5DAE}\x{5DB7}\x{5DBA}' . + '\x{5DBC}\x{5DBD}\x{5DC9}\x{5DCC}\x{5DCD}\x{5DD2}\x{5DD3}\x{5DD6}\x{5DDB}' . + '\x{5DDD}\x{5DDE}\x{5DE1}\x{5DE3}\x{5DE5}\x{5DE6}\x{5DE7}\x{5DE8}\x{5DEB}' . + '\x{5DEE}\x{5DF1}\x{5DF2}\x{5DF3}\x{5DF4}\x{5DF5}\x{5DF7}\x{5DFB}\x{5DFD}' . + '\x{5DFE}\x{5E02}\x{5E03}\x{5E06}\x{5E0B}\x{5E0C}\x{5E11}\x{5E16}\x{5E19}' . + '\x{5E1A}\x{5E1B}\x{5E1D}\x{5E25}\x{5E2B}\x{5E2D}\x{5E2F}\x{5E30}\x{5E33}' . + '\x{5E36}\x{5E37}\x{5E38}\x{5E3D}\x{5E40}\x{5E43}\x{5E44}\x{5E45}\x{5E47}' . + '\x{5E4C}\x{5E4E}\x{5E54}\x{5E55}\x{5E57}\x{5E5F}\x{5E61}\x{5E62}\x{5E63}' . + '\x{5E64}\x{5E72}\x{5E73}\x{5E74}\x{5E75}\x{5E76}\x{5E78}\x{5E79}\x{5E7A}' . + '\x{5E7B}\x{5E7C}\x{5E7D}\x{5E7E}\x{5E7F}\x{5E81}\x{5E83}\x{5E84}\x{5E87}' . + '\x{5E8A}\x{5E8F}\x{5E95}\x{5E96}\x{5E97}\x{5E9A}\x{5E9C}\x{5EA0}\x{5EA6}' . + '\x{5EA7}\x{5EAB}\x{5EAD}\x{5EB5}\x{5EB6}\x{5EB7}\x{5EB8}\x{5EC1}\x{5EC2}' . + '\x{5EC3}\x{5EC8}\x{5EC9}\x{5ECA}\x{5ECF}\x{5ED0}\x{5ED3}\x{5ED6}\x{5EDA}' . + '\x{5EDB}\x{5EDD}\x{5EDF}\x{5EE0}\x{5EE1}\x{5EE2}\x{5EE3}\x{5EE8}\x{5EE9}' . + '\x{5EEC}\x{5EF0}\x{5EF1}\x{5EF3}\x{5EF4}\x{5EF6}\x{5EF7}\x{5EF8}\x{5EFA}' . + '\x{5EFB}\x{5EFC}\x{5EFE}\x{5EFF}\x{5F01}\x{5F03}\x{5F04}\x{5F09}\x{5F0A}' . + '\x{5F0B}\x{5F0C}\x{5F0D}\x{5F0F}\x{5F10}\x{5F11}\x{5F13}\x{5F14}\x{5F15}' . + '\x{5F16}\x{5F17}\x{5F18}\x{5F1B}\x{5F1F}\x{5F25}\x{5F26}\x{5F27}\x{5F29}' . + '\x{5F2D}\x{5F2F}\x{5F31}\x{5F35}\x{5F37}\x{5F38}\x{5F3C}\x{5F3E}\x{5F41}' . + '\x{5F48}\x{5F4A}\x{5F4C}\x{5F4E}\x{5F51}\x{5F53}\x{5F56}\x{5F57}\x{5F59}' . + '\x{5F5C}\x{5F5D}\x{5F61}\x{5F62}\x{5F66}\x{5F69}\x{5F6A}\x{5F6B}\x{5F6C}' . + '\x{5F6D}\x{5F70}\x{5F71}\x{5F73}\x{5F77}\x{5F79}\x{5F7C}\x{5F7F}\x{5F80}' . + '\x{5F81}\x{5F82}\x{5F83}\x{5F84}\x{5F85}\x{5F87}\x{5F88}\x{5F8A}\x{5F8B}' . + '\x{5F8C}\x{5F90}\x{5F91}\x{5F92}\x{5F93}\x{5F97}\x{5F98}\x{5F99}\x{5F9E}' . + '\x{5FA0}\x{5FA1}\x{5FA8}\x{5FA9}\x{5FAA}\x{5FAD}\x{5FAE}\x{5FB3}\x{5FB4}' . + '\x{5FB9}\x{5FBC}\x{5FBD}\x{5FC3}\x{5FC5}\x{5FCC}\x{5FCD}\x{5FD6}\x{5FD7}' . + '\x{5FD8}\x{5FD9}\x{5FDC}\x{5FDD}\x{5FE0}\x{5FE4}\x{5FEB}\x{5FF0}\x{5FF1}' . + '\x{5FF5}\x{5FF8}\x{5FFB}\x{5FFD}\x{5FFF}\x{600E}\x{600F}\x{6010}\x{6012}' . + '\x{6015}\x{6016}\x{6019}\x{601B}\x{601C}\x{601D}\x{6020}\x{6021}\x{6025}' . + '\x{6026}\x{6027}\x{6028}\x{6029}\x{602A}\x{602B}\x{602F}\x{6031}\x{603A}' . + '\x{6041}\x{6042}\x{6043}\x{6046}\x{604A}\x{604B}\x{604D}\x{6050}\x{6052}' . + '\x{6055}\x{6059}\x{605A}\x{605F}\x{6060}\x{6062}\x{6063}\x{6064}\x{6065}' . + '\x{6068}\x{6069}\x{606A}\x{606B}\x{606C}\x{606D}\x{606F}\x{6070}\x{6075}' . + '\x{6077}\x{6081}\x{6083}\x{6084}\x{6089}\x{608B}\x{608C}\x{608D}\x{6092}' . + '\x{6094}\x{6096}\x{6097}\x{609A}\x{609B}\x{609F}\x{60A0}\x{60A3}\x{60A6}' . + '\x{60A7}\x{60A9}\x{60AA}\x{60B2}\x{60B3}\x{60B4}\x{60B5}\x{60B6}\x{60B8}' . + '\x{60BC}\x{60BD}\x{60C5}\x{60C6}\x{60C7}\x{60D1}\x{60D3}\x{60D8}\x{60DA}' . + '\x{60DC}\x{60DF}\x{60E0}\x{60E1}\x{60E3}\x{60E7}\x{60E8}\x{60F0}\x{60F1}' . + '\x{60F3}\x{60F4}\x{60F6}\x{60F7}\x{60F9}\x{60FA}\x{60FB}\x{6100}\x{6101}' . + '\x{6103}\x{6106}\x{6108}\x{6109}\x{610D}\x{610E}\x{610F}\x{6115}\x{611A}' . + '\x{611B}\x{611F}\x{6121}\x{6127}\x{6128}\x{612C}\x{6134}\x{613C}\x{613D}' . + '\x{613E}\x{613F}\x{6142}\x{6144}\x{6147}\x{6148}\x{614A}\x{614B}\x{614C}' . + '\x{614D}\x{614E}\x{6153}\x{6155}\x{6158}\x{6159}\x{615A}\x{615D}\x{615F}' . + '\x{6162}\x{6163}\x{6165}\x{6167}\x{6168}\x{616B}\x{616E}\x{616F}\x{6170}' . + '\x{6171}\x{6173}\x{6174}\x{6175}\x{6176}\x{6177}\x{617E}\x{6182}\x{6187}' . + '\x{618A}\x{618E}\x{6190}\x{6191}\x{6194}\x{6196}\x{6199}\x{619A}\x{61A4}' . + '\x{61A7}\x{61A9}\x{61AB}\x{61AC}\x{61AE}\x{61B2}\x{61B6}\x{61BA}\x{61BE}' . + '\x{61C3}\x{61C6}\x{61C7}\x{61C8}\x{61C9}\x{61CA}\x{61CB}\x{61CC}\x{61CD}' . + '\x{61D0}\x{61E3}\x{61E6}\x{61F2}\x{61F4}\x{61F6}\x{61F7}\x{61F8}\x{61FA}' . + '\x{61FC}\x{61FD}\x{61FE}\x{61FF}\x{6200}\x{6208}\x{6209}\x{620A}\x{620C}' . + '\x{620D}\x{620E}\x{6210}\x{6211}\x{6212}\x{6214}\x{6216}\x{621A}\x{621B}' . + '\x{621D}\x{621E}\x{621F}\x{6221}\x{6226}\x{622A}\x{622E}\x{622F}\x{6230}' . + '\x{6232}\x{6233}\x{6234}\x{6238}\x{623B}\x{623F}\x{6240}\x{6241}\x{6247}' . + '\x{6248}\x{6249}\x{624B}\x{624D}\x{624E}\x{6253}\x{6255}\x{6258}\x{625B}' . + '\x{625E}\x{6260}\x{6263}\x{6268}\x{626E}\x{6271}\x{6276}\x{6279}\x{627C}' . + '\x{627E}\x{627F}\x{6280}\x{6282}\x{6283}\x{6284}\x{6289}\x{628A}\x{6291}' . + '\x{6292}\x{6293}\x{6294}\x{6295}\x{6296}\x{6297}\x{6298}\x{629B}\x{629C}' . + '\x{629E}\x{62AB}\x{62AC}\x{62B1}\x{62B5}\x{62B9}\x{62BB}\x{62BC}\x{62BD}' . + '\x{62C2}\x{62C5}\x{62C6}\x{62C7}\x{62C8}\x{62C9}\x{62CA}\x{62CC}\x{62CD}' . + '\x{62CF}\x{62D0}\x{62D1}\x{62D2}\x{62D3}\x{62D4}\x{62D7}\x{62D8}\x{62D9}' . + '\x{62DB}\x{62DC}\x{62DD}\x{62E0}\x{62E1}\x{62EC}\x{62ED}\x{62EE}\x{62EF}' . + '\x{62F1}\x{62F3}\x{62F5}\x{62F6}\x{62F7}\x{62FE}\x{62FF}\x{6301}\x{6302}' . + '\x{6307}\x{6308}\x{6309}\x{630C}\x{6311}\x{6319}\x{631F}\x{6327}\x{6328}' . + '\x{632B}\x{632F}\x{633A}\x{633D}\x{633E}\x{633F}\x{6349}\x{634C}\x{634D}' . + '\x{634F}\x{6350}\x{6355}\x{6357}\x{635C}\x{6367}\x{6368}\x{6369}\x{636B}' . + '\x{636E}\x{6372}\x{6376}\x{6377}\x{637A}\x{637B}\x{6380}\x{6383}\x{6388}' . + '\x{6389}\x{638C}\x{638E}\x{638F}\x{6392}\x{6396}\x{6398}\x{639B}\x{639F}' . + '\x{63A0}\x{63A1}\x{63A2}\x{63A3}\x{63A5}\x{63A7}\x{63A8}\x{63A9}\x{63AA}' . + '\x{63AB}\x{63AC}\x{63B2}\x{63B4}\x{63B5}\x{63BB}\x{63BE}\x{63C0}\x{63C3}' . + '\x{63C4}\x{63C6}\x{63C9}\x{63CF}\x{63D0}\x{63D2}\x{63D6}\x{63DA}\x{63DB}' . + '\x{63E1}\x{63E3}\x{63E9}\x{63EE}\x{63F4}\x{63F6}\x{63FA}\x{6406}\x{640D}' . + '\x{640F}\x{6413}\x{6416}\x{6417}\x{641C}\x{6426}\x{6428}\x{642C}\x{642D}' . + '\x{6434}\x{6436}\x{643A}\x{643E}\x{6442}\x{644E}\x{6458}\x{6467}\x{6469}' . + '\x{646F}\x{6476}\x{6478}\x{647A}\x{6483}\x{6488}\x{6492}\x{6493}\x{6495}' . + '\x{649A}\x{649E}\x{64A4}\x{64A5}\x{64A9}\x{64AB}\x{64AD}\x{64AE}\x{64B0}' . + '\x{64B2}\x{64B9}\x{64BB}\x{64BC}\x{64C1}\x{64C2}\x{64C5}\x{64C7}\x{64CD}' . + '\x{64D2}\x{64D4}\x{64D8}\x{64DA}\x{64E0}\x{64E1}\x{64E2}\x{64E3}\x{64E6}' . + '\x{64E7}\x{64EC}\x{64EF}\x{64F1}\x{64F2}\x{64F4}\x{64F6}\x{64FA}\x{64FD}' . + '\x{64FE}\x{6500}\x{6505}\x{6518}\x{651C}\x{651D}\x{6523}\x{6524}\x{652A}' . + '\x{652B}\x{652C}\x{652F}\x{6534}\x{6535}\x{6536}\x{6537}\x{6538}\x{6539}' . + '\x{653B}\x{653E}\x{653F}\x{6545}\x{6548}\x{654D}\x{654F}\x{6551}\x{6555}' . + '\x{6556}\x{6557}\x{6558}\x{6559}\x{655D}\x{655E}\x{6562}\x{6563}\x{6566}' . + '\x{656C}\x{6570}\x{6572}\x{6574}\x{6575}\x{6577}\x{6578}\x{6582}\x{6583}' . + '\x{6587}\x{6588}\x{6589}\x{658C}\x{658E}\x{6590}\x{6591}\x{6597}\x{6599}' . + '\x{659B}\x{659C}\x{659F}\x{65A1}\x{65A4}\x{65A5}\x{65A7}\x{65AB}\x{65AC}' . + '\x{65AD}\x{65AF}\x{65B0}\x{65B7}\x{65B9}\x{65BC}\x{65BD}\x{65C1}\x{65C3}' . + '\x{65C4}\x{65C5}\x{65C6}\x{65CB}\x{65CC}\x{65CF}\x{65D2}\x{65D7}\x{65D9}' . + '\x{65DB}\x{65E0}\x{65E1}\x{65E2}\x{65E5}\x{65E6}\x{65E7}\x{65E8}\x{65E9}' . + '\x{65EC}\x{65ED}\x{65F1}\x{65FA}\x{65FB}\x{6602}\x{6603}\x{6606}\x{6607}' . + '\x{660A}\x{660C}\x{660E}\x{660F}\x{6613}\x{6614}\x{661C}\x{661F}\x{6620}' . + '\x{6625}\x{6627}\x{6628}\x{662D}\x{662F}\x{6634}\x{6635}\x{6636}\x{663C}' . + '\x{663F}\x{6641}\x{6642}\x{6643}\x{6644}\x{6649}\x{664B}\x{664F}\x{6652}' . + '\x{665D}\x{665E}\x{665F}\x{6662}\x{6664}\x{6666}\x{6667}\x{6668}\x{6669}' . + '\x{666E}\x{666F}\x{6670}\x{6674}\x{6676}\x{667A}\x{6681}\x{6683}\x{6684}' . + '\x{6687}\x{6688}\x{6689}\x{668E}\x{6691}\x{6696}\x{6697}\x{6698}\x{669D}' . + '\x{66A2}\x{66A6}\x{66AB}\x{66AE}\x{66B4}\x{66B8}\x{66B9}\x{66BC}\x{66BE}' . + '\x{66C1}\x{66C4}\x{66C7}\x{66C9}\x{66D6}\x{66D9}\x{66DA}\x{66DC}\x{66DD}' . + '\x{66E0}\x{66E6}\x{66E9}\x{66F0}\x{66F2}\x{66F3}\x{66F4}\x{66F5}\x{66F7}' . + '\x{66F8}\x{66F9}\x{66FC}\x{66FD}\x{66FE}\x{66FF}\x{6700}\x{6703}\x{6708}' . + '\x{6709}\x{670B}\x{670D}\x{670F}\x{6714}\x{6715}\x{6716}\x{6717}\x{671B}' . + '\x{671D}\x{671E}\x{671F}\x{6726}\x{6727}\x{6728}\x{672A}\x{672B}\x{672C}' . + '\x{672D}\x{672E}\x{6731}\x{6734}\x{6736}\x{6737}\x{6738}\x{673A}\x{673D}' . + '\x{673F}\x{6741}\x{6746}\x{6749}\x{674E}\x{674F}\x{6750}\x{6751}\x{6753}' . + '\x{6756}\x{6759}\x{675C}\x{675E}\x{675F}\x{6760}\x{6761}\x{6762}\x{6763}' . + '\x{6764}\x{6765}\x{676A}\x{676D}\x{676F}\x{6770}\x{6771}\x{6772}\x{6773}' . + '\x{6775}\x{6777}\x{677C}\x{677E}\x{677F}\x{6785}\x{6787}\x{6789}\x{678B}' . + '\x{678C}\x{6790}\x{6795}\x{6797}\x{679A}\x{679C}\x{679D}\x{67A0}\x{67A1}' . + '\x{67A2}\x{67A6}\x{67A9}\x{67AF}\x{67B3}\x{67B4}\x{67B6}\x{67B7}\x{67B8}' . + '\x{67B9}\x{67C1}\x{67C4}\x{67C6}\x{67CA}\x{67CE}\x{67CF}\x{67D0}\x{67D1}' . + '\x{67D3}\x{67D4}\x{67D8}\x{67DA}\x{67DD}\x{67DE}\x{67E2}\x{67E4}\x{67E7}' . + '\x{67E9}\x{67EC}\x{67EE}\x{67EF}\x{67F1}\x{67F3}\x{67F4}\x{67F5}\x{67FB}' . + '\x{67FE}\x{67FF}\x{6802}\x{6803}\x{6804}\x{6813}\x{6816}\x{6817}\x{681E}' . + '\x{6821}\x{6822}\x{6829}\x{682A}\x{682B}\x{6832}\x{6834}\x{6838}\x{6839}' . + '\x{683C}\x{683D}\x{6840}\x{6841}\x{6842}\x{6843}\x{6846}\x{6848}\x{684D}' . + '\x{684E}\x{6850}\x{6851}\x{6853}\x{6854}\x{6859}\x{685C}\x{685D}\x{685F}' . + '\x{6863}\x{6867}\x{6874}\x{6876}\x{6877}\x{687E}\x{687F}\x{6881}\x{6883}' . + '\x{6885}\x{688D}\x{688F}\x{6893}\x{6894}\x{6897}\x{689B}\x{689D}\x{689F}' . + '\x{68A0}\x{68A2}\x{68A6}\x{68A7}\x{68A8}\x{68AD}\x{68AF}\x{68B0}\x{68B1}' . + '\x{68B3}\x{68B5}\x{68B6}\x{68B9}\x{68BA}\x{68BC}\x{68C4}\x{68C6}\x{68C9}' . + '\x{68CA}\x{68CB}\x{68CD}\x{68D2}\x{68D4}\x{68D5}\x{68D7}\x{68D8}\x{68DA}' . + '\x{68DF}\x{68E0}\x{68E1}\x{68E3}\x{68E7}\x{68EE}\x{68EF}\x{68F2}\x{68F9}' . + '\x{68FA}\x{6900}\x{6901}\x{6904}\x{6905}\x{6908}\x{690B}\x{690C}\x{690D}' . + '\x{690E}\x{690F}\x{6912}\x{6919}\x{691A}\x{691B}\x{691C}\x{6921}\x{6922}' . + '\x{6923}\x{6925}\x{6926}\x{6928}\x{692A}\x{6930}\x{6934}\x{6936}\x{6939}' . + '\x{693D}\x{693F}\x{694A}\x{6953}\x{6954}\x{6955}\x{6959}\x{695A}\x{695C}' . + '\x{695D}\x{695E}\x{6960}\x{6961}\x{6962}\x{696A}\x{696B}\x{696D}\x{696E}' . + '\x{696F}\x{6973}\x{6974}\x{6975}\x{6977}\x{6978}\x{6979}\x{697C}\x{697D}' . + '\x{697E}\x{6981}\x{6982}\x{698A}\x{698E}\x{6991}\x{6994}\x{6995}\x{699B}' . + '\x{699C}\x{69A0}\x{69A7}\x{69AE}\x{69B1}\x{69B2}\x{69B4}\x{69BB}\x{69BE}' . + '\x{69BF}\x{69C1}\x{69C3}\x{69C7}\x{69CA}\x{69CB}\x{69CC}\x{69CD}\x{69CE}' . + '\x{69D0}\x{69D3}\x{69D8}\x{69D9}\x{69DD}\x{69DE}\x{69E7}\x{69E8}\x{69EB}' . + '\x{69ED}\x{69F2}\x{69F9}\x{69FB}\x{69FD}\x{69FF}\x{6A02}\x{6A05}\x{6A0A}' . + '\x{6A0B}\x{6A0C}\x{6A12}\x{6A13}\x{6A14}\x{6A17}\x{6A19}\x{6A1B}\x{6A1E}' . + '\x{6A1F}\x{6A21}\x{6A22}\x{6A23}\x{6A29}\x{6A2A}\x{6A2B}\x{6A2E}\x{6A35}' . + '\x{6A36}\x{6A38}\x{6A39}\x{6A3A}\x{6A3D}\x{6A44}\x{6A47}\x{6A48}\x{6A4B}' . + '\x{6A58}\x{6A59}\x{6A5F}\x{6A61}\x{6A62}\x{6A66}\x{6A72}\x{6A78}\x{6A7F}' . + '\x{6A80}\x{6A84}\x{6A8D}\x{6A8E}\x{6A90}\x{6A97}\x{6A9C}\x{6AA0}\x{6AA2}' . + '\x{6AA3}\x{6AAA}\x{6AAC}\x{6AAE}\x{6AB3}\x{6AB8}\x{6ABB}\x{6AC1}\x{6AC2}' . + '\x{6AC3}\x{6AD1}\x{6AD3}\x{6ADA}\x{6ADB}\x{6ADE}\x{6ADF}\x{6AE8}\x{6AEA}' . + '\x{6AFA}\x{6AFB}\x{6B04}\x{6B05}\x{6B0A}\x{6B12}\x{6B16}\x{6B1D}\x{6B1F}' . + '\x{6B20}\x{6B21}\x{6B23}\x{6B27}\x{6B32}\x{6B37}\x{6B38}\x{6B39}\x{6B3A}' . + '\x{6B3D}\x{6B3E}\x{6B43}\x{6B47}\x{6B49}\x{6B4C}\x{6B4E}\x{6B50}\x{6B53}' . + '\x{6B54}\x{6B59}\x{6B5B}\x{6B5F}\x{6B61}\x{6B62}\x{6B63}\x{6B64}\x{6B66}' . + '\x{6B69}\x{6B6A}\x{6B6F}\x{6B73}\x{6B74}\x{6B78}\x{6B79}\x{6B7B}\x{6B7F}' . + '\x{6B80}\x{6B83}\x{6B84}\x{6B86}\x{6B89}\x{6B8A}\x{6B8B}\x{6B8D}\x{6B95}' . + '\x{6B96}\x{6B98}\x{6B9E}\x{6BA4}\x{6BAA}\x{6BAB}\x{6BAF}\x{6BB1}\x{6BB2}' . + '\x{6BB3}\x{6BB4}\x{6BB5}\x{6BB7}\x{6BBA}\x{6BBB}\x{6BBC}\x{6BBF}\x{6BC0}' . + '\x{6BC5}\x{6BC6}\x{6BCB}\x{6BCD}\x{6BCE}\x{6BD2}\x{6BD3}\x{6BD4}\x{6BD8}' . + '\x{6BDB}\x{6BDF}\x{6BEB}\x{6BEC}\x{6BEF}\x{6BF3}\x{6C08}\x{6C0F}\x{6C11}' . + '\x{6C13}\x{6C14}\x{6C17}\x{6C1B}\x{6C23}\x{6C24}\x{6C34}\x{6C37}\x{6C38}' . + '\x{6C3E}\x{6C40}\x{6C41}\x{6C42}\x{6C4E}\x{6C50}\x{6C55}\x{6C57}\x{6C5A}' . + '\x{6C5D}\x{6C5E}\x{6C5F}\x{6C60}\x{6C62}\x{6C68}\x{6C6A}\x{6C70}\x{6C72}' . + '\x{6C73}\x{6C7A}\x{6C7D}\x{6C7E}\x{6C81}\x{6C82}\x{6C83}\x{6C88}\x{6C8C}' . + '\x{6C8D}\x{6C90}\x{6C92}\x{6C93}\x{6C96}\x{6C99}\x{6C9A}\x{6C9B}\x{6CA1}' . + '\x{6CA2}\x{6CAB}\x{6CAE}\x{6CB1}\x{6CB3}\x{6CB8}\x{6CB9}\x{6CBA}\x{6CBB}' . + '\x{6CBC}\x{6CBD}\x{6CBE}\x{6CBF}\x{6CC1}\x{6CC4}\x{6CC5}\x{6CC9}\x{6CCA}' . + '\x{6CCC}\x{6CD3}\x{6CD5}\x{6CD7}\x{6CD9}\x{6CDB}\x{6CDD}\x{6CE1}\x{6CE2}' . + '\x{6CE3}\x{6CE5}\x{6CE8}\x{6CEA}\x{6CEF}\x{6CF0}\x{6CF1}\x{6CF3}\x{6D0B}' . + '\x{6D0C}\x{6D12}\x{6D17}\x{6D19}\x{6D1B}\x{6D1E}\x{6D1F}\x{6D25}\x{6D29}' . + '\x{6D2A}\x{6D2B}\x{6D32}\x{6D33}\x{6D35}\x{6D36}\x{6D38}\x{6D3B}\x{6D3D}' . + '\x{6D3E}\x{6D41}\x{6D44}\x{6D45}\x{6D59}\x{6D5A}\x{6D5C}\x{6D63}\x{6D64}' . + '\x{6D66}\x{6D69}\x{6D6A}\x{6D6C}\x{6D6E}\x{6D74}\x{6D77}\x{6D78}\x{6D79}' . + '\x{6D85}\x{6D88}\x{6D8C}\x{6D8E}\x{6D93}\x{6D95}\x{6D99}\x{6D9B}\x{6D9C}' . + '\x{6DAF}\x{6DB2}\x{6DB5}\x{6DB8}\x{6DBC}\x{6DC0}\x{6DC5}\x{6DC6}\x{6DC7}' . + '\x{6DCB}\x{6DCC}\x{6DD1}\x{6DD2}\x{6DD5}\x{6DD8}\x{6DD9}\x{6DDE}\x{6DE1}' . + '\x{6DE4}\x{6DE6}\x{6DE8}\x{6DEA}\x{6DEB}\x{6DEC}\x{6DEE}\x{6DF1}\x{6DF3}' . + '\x{6DF5}\x{6DF7}\x{6DF9}\x{6DFA}\x{6DFB}\x{6E05}\x{6E07}\x{6E08}\x{6E09}' . + '\x{6E0A}\x{6E0B}\x{6E13}\x{6E15}\x{6E19}\x{6E1A}\x{6E1B}\x{6E1D}\x{6E1F}' . + '\x{6E20}\x{6E21}\x{6E23}\x{6E24}\x{6E25}\x{6E26}\x{6E29}\x{6E2B}\x{6E2C}' . + '\x{6E2D}\x{6E2E}\x{6E2F}\x{6E38}\x{6E3A}\x{6E3E}\x{6E43}\x{6E4A}\x{6E4D}' . + '\x{6E4E}\x{6E56}\x{6E58}\x{6E5B}\x{6E5F}\x{6E67}\x{6E6B}\x{6E6E}\x{6E6F}' . + '\x{6E72}\x{6E76}\x{6E7E}\x{6E7F}\x{6E80}\x{6E82}\x{6E8C}\x{6E8F}\x{6E90}' . + '\x{6E96}\x{6E98}\x{6E9C}\x{6E9D}\x{6E9F}\x{6EA2}\x{6EA5}\x{6EAA}\x{6EAF}' . + '\x{6EB2}\x{6EB6}\x{6EB7}\x{6EBA}\x{6EBD}\x{6EC2}\x{6EC4}\x{6EC5}\x{6EC9}' . + '\x{6ECB}\x{6ECC}\x{6ED1}\x{6ED3}\x{6ED4}\x{6ED5}\x{6EDD}\x{6EDE}\x{6EEC}' . + '\x{6EEF}\x{6EF2}\x{6EF4}\x{6EF7}\x{6EF8}\x{6EFE}\x{6EFF}\x{6F01}\x{6F02}' . + '\x{6F06}\x{6F09}\x{6F0F}\x{6F11}\x{6F13}\x{6F14}\x{6F15}\x{6F20}\x{6F22}' . + '\x{6F23}\x{6F2B}\x{6F2C}\x{6F31}\x{6F32}\x{6F38}\x{6F3E}\x{6F3F}\x{6F41}' . + '\x{6F45}\x{6F54}\x{6F58}\x{6F5B}\x{6F5C}\x{6F5F}\x{6F64}\x{6F66}\x{6F6D}' . + '\x{6F6E}\x{6F6F}\x{6F70}\x{6F74}\x{6F78}\x{6F7A}\x{6F7C}\x{6F80}\x{6F81}' . + '\x{6F82}\x{6F84}\x{6F86}\x{6F8E}\x{6F91}\x{6F97}\x{6FA1}\x{6FA3}\x{6FA4}' . + '\x{6FAA}\x{6FB1}\x{6FB3}\x{6FB9}\x{6FC0}\x{6FC1}\x{6FC2}\x{6FC3}\x{6FC6}' . + '\x{6FD4}\x{6FD5}\x{6FD8}\x{6FDB}\x{6FDF}\x{6FE0}\x{6FE1}\x{6FE4}\x{6FEB}' . + '\x{6FEC}\x{6FEE}\x{6FEF}\x{6FF1}\x{6FF3}\x{6FF6}\x{6FFA}\x{6FFE}\x{7001}' . + '\x{7009}\x{700B}\x{700F}\x{7011}\x{7015}\x{7018}\x{701A}\x{701B}\x{701D}' . + '\x{701E}\x{701F}\x{7026}\x{7027}\x{702C}\x{7030}\x{7032}\x{703E}\x{704C}' . + '\x{7051}\x{7058}\x{7063}\x{706B}\x{706F}\x{7070}\x{7078}\x{707C}\x{707D}' . + '\x{7089}\x{708A}\x{708E}\x{7092}\x{7099}\x{70AC}\x{70AD}\x{70AE}\x{70AF}' . + '\x{70B3}\x{70B8}\x{70B9}\x{70BA}\x{70C8}\x{70CB}\x{70CF}\x{70D9}\x{70DD}' . + '\x{70DF}\x{70F1}\x{70F9}\x{70FD}\x{7109}\x{7114}\x{7119}\x{711A}\x{711C}' . + '\x{7121}\x{7126}\x{7136}\x{713C}\x{7149}\x{714C}\x{714E}\x{7155}\x{7156}' . + '\x{7159}\x{7162}\x{7164}\x{7165}\x{7166}\x{7167}\x{7169}\x{716C}\x{716E}' . + '\x{717D}\x{7184}\x{7188}\x{718A}\x{718F}\x{7194}\x{7195}\x{7199}\x{719F}' . + '\x{71A8}\x{71AC}\x{71B1}\x{71B9}\x{71BE}\x{71C3}\x{71C8}\x{71C9}\x{71CE}' . + '\x{71D0}\x{71D2}\x{71D4}\x{71D5}\x{71D7}\x{71DF}\x{71E0}\x{71E5}\x{71E6}' . + '\x{71E7}\x{71EC}\x{71ED}\x{71EE}\x{71F5}\x{71F9}\x{71FB}\x{71FC}\x{71FF}' . + '\x{7206}\x{720D}\x{7210}\x{721B}\x{7228}\x{722A}\x{722C}\x{722D}\x{7230}' . + '\x{7232}\x{7235}\x{7236}\x{723A}\x{723B}\x{723C}\x{723D}\x{723E}\x{723F}' . + '\x{7240}\x{7246}\x{7247}\x{7248}\x{724B}\x{724C}\x{7252}\x{7258}\x{7259}' . + '\x{725B}\x{725D}\x{725F}\x{7261}\x{7262}\x{7267}\x{7269}\x{7272}\x{7274}' . + '\x{7279}\x{727D}\x{727E}\x{7280}\x{7281}\x{7282}\x{7287}\x{7292}\x{7296}' . + '\x{72A0}\x{72A2}\x{72A7}\x{72AC}\x{72AF}\x{72B2}\x{72B6}\x{72B9}\x{72C2}' . + '\x{72C3}\x{72C4}\x{72C6}\x{72CE}\x{72D0}\x{72D2}\x{72D7}\x{72D9}\x{72DB}' . + '\x{72E0}\x{72E1}\x{72E2}\x{72E9}\x{72EC}\x{72ED}\x{72F7}\x{72F8}\x{72F9}' . + '\x{72FC}\x{72FD}\x{730A}\x{7316}\x{7317}\x{731B}\x{731C}\x{731D}\x{731F}' . + '\x{7325}\x{7329}\x{732A}\x{732B}\x{732E}\x{732F}\x{7334}\x{7336}\x{7337}' . + '\x{733E}\x{733F}\x{7344}\x{7345}\x{734E}\x{734F}\x{7357}\x{7363}\x{7368}' . + '\x{736A}\x{7370}\x{7372}\x{7375}\x{7378}\x{737A}\x{737B}\x{7384}\x{7387}' . + '\x{7389}\x{738B}\x{7396}\x{73A9}\x{73B2}\x{73B3}\x{73BB}\x{73C0}\x{73C2}' . + '\x{73C8}\x{73CA}\x{73CD}\x{73CE}\x{73DE}\x{73E0}\x{73E5}\x{73EA}\x{73ED}' . + '\x{73EE}\x{73F1}\x{73F8}\x{73FE}\x{7403}\x{7405}\x{7406}\x{7409}\x{7422}' . + '\x{7425}\x{7432}\x{7433}\x{7434}\x{7435}\x{7436}\x{743A}\x{743F}\x{7441}' . + '\x{7455}\x{7459}\x{745A}\x{745B}\x{745C}\x{745E}\x{745F}\x{7460}\x{7463}' . + '\x{7464}\x{7469}\x{746A}\x{746F}\x{7470}\x{7473}\x{7476}\x{747E}\x{7483}' . + '\x{748B}\x{749E}\x{74A2}\x{74A7}\x{74B0}\x{74BD}\x{74CA}\x{74CF}\x{74D4}' . + '\x{74DC}\x{74E0}\x{74E2}\x{74E3}\x{74E6}\x{74E7}\x{74E9}\x{74EE}\x{74F0}' . + '\x{74F1}\x{74F2}\x{74F6}\x{74F7}\x{74F8}\x{7503}\x{7504}\x{7505}\x{750C}' . + '\x{750D}\x{750E}\x{7511}\x{7513}\x{7515}\x{7518}\x{751A}\x{751C}\x{751E}' . + '\x{751F}\x{7523}\x{7525}\x{7526}\x{7528}\x{752B}\x{752C}\x{7530}\x{7531}' . + '\x{7532}\x{7533}\x{7537}\x{7538}\x{753A}\x{753B}\x{753C}\x{7544}\x{7546}' . + '\x{7549}\x{754A}\x{754B}\x{754C}\x{754D}\x{754F}\x{7551}\x{7554}\x{7559}' . + '\x{755A}\x{755B}\x{755C}\x{755D}\x{7560}\x{7562}\x{7564}\x{7565}\x{7566}' . + '\x{7567}\x{7569}\x{756A}\x{756B}\x{756D}\x{7570}\x{7573}\x{7574}\x{7576}' . + '\x{7577}\x{7578}\x{757F}\x{7582}\x{7586}\x{7587}\x{7589}\x{758A}\x{758B}' . + '\x{758E}\x{758F}\x{7591}\x{7594}\x{759A}\x{759D}\x{75A3}\x{75A5}\x{75AB}' . + '\x{75B1}\x{75B2}\x{75B3}\x{75B5}\x{75B8}\x{75B9}\x{75BC}\x{75BD}\x{75BE}' . + '\x{75C2}\x{75C3}\x{75C5}\x{75C7}\x{75CA}\x{75CD}\x{75D2}\x{75D4}\x{75D5}' . + '\x{75D8}\x{75D9}\x{75DB}\x{75DE}\x{75E2}\x{75E3}\x{75E9}\x{75F0}\x{75F2}' . + '\x{75F3}\x{75F4}\x{75FA}\x{75FC}\x{75FE}\x{75FF}\x{7601}\x{7609}\x{760B}' . + '\x{760D}\x{761F}\x{7620}\x{7621}\x{7622}\x{7624}\x{7627}\x{7630}\x{7634}' . + '\x{763B}\x{7642}\x{7646}\x{7647}\x{7648}\x{764C}\x{7652}\x{7656}\x{7658}' . + '\x{765C}\x{7661}\x{7662}\x{7667}\x{7668}\x{7669}\x{766A}\x{766C}\x{7670}' . + '\x{7672}\x{7676}\x{7678}\x{767A}\x{767B}\x{767C}\x{767D}\x{767E}\x{7680}' . + '\x{7683}\x{7684}\x{7686}\x{7687}\x{7688}\x{768B}\x{768E}\x{7690}\x{7693}' . + '\x{7696}\x{7699}\x{769A}\x{76AE}\x{76B0}\x{76B4}\x{76B7}\x{76B8}\x{76B9}' . + '\x{76BA}\x{76BF}\x{76C2}\x{76C3}\x{76C6}\x{76C8}\x{76CA}\x{76CD}\x{76D2}' . + '\x{76D6}\x{76D7}\x{76DB}\x{76DC}\x{76DE}\x{76DF}\x{76E1}\x{76E3}\x{76E4}' . + '\x{76E5}\x{76E7}\x{76EA}\x{76EE}\x{76F2}\x{76F4}\x{76F8}\x{76FB}\x{76FE}' . + '\x{7701}\x{7704}\x{7707}\x{7708}\x{7709}\x{770B}\x{770C}\x{771B}\x{771E}' . + '\x{771F}\x{7720}\x{7724}\x{7725}\x{7726}\x{7729}\x{7737}\x{7738}\x{773A}' . + '\x{773C}\x{7740}\x{7747}\x{775A}\x{775B}\x{7761}\x{7763}\x{7765}\x{7766}' . + '\x{7768}\x{776B}\x{7779}\x{777E}\x{777F}\x{778B}\x{778E}\x{7791}\x{779E}' . + '\x{77A0}\x{77A5}\x{77AC}\x{77AD}\x{77B0}\x{77B3}\x{77B6}\x{77B9}\x{77BB}' . + '\x{77BC}\x{77BD}\x{77BF}\x{77C7}\x{77CD}\x{77D7}\x{77DA}\x{77DB}\x{77DC}' . + '\x{77E2}\x{77E3}\x{77E5}\x{77E7}\x{77E9}\x{77ED}\x{77EE}\x{77EF}\x{77F3}' . + '\x{77FC}\x{7802}\x{780C}\x{7812}\x{7814}\x{7815}\x{7820}\x{7825}\x{7826}' . + '\x{7827}\x{7832}\x{7834}\x{783A}\x{783F}\x{7845}\x{785D}\x{786B}\x{786C}' . + '\x{786F}\x{7872}\x{7874}\x{787C}\x{7881}\x{7886}\x{7887}\x{788C}\x{788D}' . + '\x{788E}\x{7891}\x{7893}\x{7895}\x{7897}\x{789A}\x{78A3}\x{78A7}\x{78A9}' . + '\x{78AA}\x{78AF}\x{78B5}\x{78BA}\x{78BC}\x{78BE}\x{78C1}\x{78C5}\x{78C6}' . + '\x{78CA}\x{78CB}\x{78D0}\x{78D1}\x{78D4}\x{78DA}\x{78E7}\x{78E8}\x{78EC}' . + '\x{78EF}\x{78F4}\x{78FD}\x{7901}\x{7907}\x{790E}\x{7911}\x{7912}\x{7919}' . + '\x{7926}\x{792A}\x{792B}\x{792C}\x{793A}\x{793C}\x{793E}\x{7940}\x{7941}' . + '\x{7947}\x{7948}\x{7949}\x{7950}\x{7953}\x{7955}\x{7956}\x{7957}\x{795A}' . + '\x{795D}\x{795E}\x{795F}\x{7960}\x{7962}\x{7965}\x{7968}\x{796D}\x{7977}' . + '\x{797A}\x{797F}\x{7980}\x{7981}\x{7984}\x{7985}\x{798A}\x{798D}\x{798E}' . + '\x{798F}\x{799D}\x{79A6}\x{79A7}\x{79AA}\x{79AE}\x{79B0}\x{79B3}\x{79B9}' . + '\x{79BA}\x{79BD}\x{79BE}\x{79BF}\x{79C0}\x{79C1}\x{79C9}\x{79CB}\x{79D1}' . + '\x{79D2}\x{79D5}\x{79D8}\x{79DF}\x{79E1}\x{79E3}\x{79E4}\x{79E6}\x{79E7}' . + '\x{79E9}\x{79EC}\x{79F0}\x{79FB}\x{7A00}\x{7A08}\x{7A0B}\x{7A0D}\x{7A0E}' . + '\x{7A14}\x{7A17}\x{7A18}\x{7A19}\x{7A1A}\x{7A1C}\x{7A1F}\x{7A20}\x{7A2E}' . + '\x{7A31}\x{7A32}\x{7A37}\x{7A3B}\x{7A3C}\x{7A3D}\x{7A3E}\x{7A3F}\x{7A40}' . + '\x{7A42}\x{7A43}\x{7A46}\x{7A49}\x{7A4D}\x{7A4E}\x{7A4F}\x{7A50}\x{7A57}' . + '\x{7A61}\x{7A62}\x{7A63}\x{7A69}\x{7A6B}\x{7A70}\x{7A74}\x{7A76}\x{7A79}' . + '\x{7A7A}\x{7A7D}\x{7A7F}\x{7A81}\x{7A83}\x{7A84}\x{7A88}\x{7A92}\x{7A93}' . + '\x{7A95}\x{7A96}\x{7A97}\x{7A98}\x{7A9F}\x{7AA9}\x{7AAA}\x{7AAE}\x{7AAF}' . + '\x{7AB0}\x{7AB6}\x{7ABA}\x{7ABF}\x{7AC3}\x{7AC4}\x{7AC5}\x{7AC7}\x{7AC8}' . + '\x{7ACA}\x{7ACB}\x{7ACD}\x{7ACF}\x{7AD2}\x{7AD3}\x{7AD5}\x{7AD9}\x{7ADA}' . + '\x{7ADC}\x{7ADD}\x{7ADF}\x{7AE0}\x{7AE1}\x{7AE2}\x{7AE3}\x{7AE5}\x{7AE6}' . + '\x{7AEA}\x{7AED}\x{7AEF}\x{7AF0}\x{7AF6}\x{7AF8}\x{7AF9}\x{7AFA}\x{7AFF}' . + '\x{7B02}\x{7B04}\x{7B06}\x{7B08}\x{7B0A}\x{7B0B}\x{7B0F}\x{7B11}\x{7B18}' . + '\x{7B19}\x{7B1B}\x{7B1E}\x{7B20}\x{7B25}\x{7B26}\x{7B28}\x{7B2C}\x{7B33}' . + '\x{7B35}\x{7B36}\x{7B39}\x{7B45}\x{7B46}\x{7B48}\x{7B49}\x{7B4B}\x{7B4C}' . + '\x{7B4D}\x{7B4F}\x{7B50}\x{7B51}\x{7B52}\x{7B54}\x{7B56}\x{7B5D}\x{7B65}' . + '\x{7B67}\x{7B6C}\x{7B6E}\x{7B70}\x{7B71}\x{7B74}\x{7B75}\x{7B7A}\x{7B86}' . + '\x{7B87}\x{7B8B}\x{7B8D}\x{7B8F}\x{7B92}\x{7B94}\x{7B95}\x{7B97}\x{7B98}' . + '\x{7B99}\x{7B9A}\x{7B9C}\x{7B9D}\x{7B9F}\x{7BA1}\x{7BAA}\x{7BAD}\x{7BB1}' . + '\x{7BB4}\x{7BB8}\x{7BC0}\x{7BC1}\x{7BC4}\x{7BC6}\x{7BC7}\x{7BC9}\x{7BCB}' . + '\x{7BCC}\x{7BCF}\x{7BDD}\x{7BE0}\x{7BE4}\x{7BE5}\x{7BE6}\x{7BE9}\x{7BED}' . + '\x{7BF3}\x{7BF6}\x{7BF7}\x{7C00}\x{7C07}\x{7C0D}\x{7C11}\x{7C12}\x{7C13}' . + '\x{7C14}\x{7C17}\x{7C1F}\x{7C21}\x{7C23}\x{7C27}\x{7C2A}\x{7C2B}\x{7C37}' . + '\x{7C38}\x{7C3D}\x{7C3E}\x{7C3F}\x{7C40}\x{7C43}\x{7C4C}\x{7C4D}\x{7C4F}' . + '\x{7C50}\x{7C54}\x{7C56}\x{7C58}\x{7C5F}\x{7C60}\x{7C64}\x{7C65}\x{7C6C}' . + '\x{7C73}\x{7C75}\x{7C7E}\x{7C81}\x{7C82}\x{7C83}\x{7C89}\x{7C8B}\x{7C8D}' . + '\x{7C90}\x{7C92}\x{7C95}\x{7C97}\x{7C98}\x{7C9B}\x{7C9F}\x{7CA1}\x{7CA2}' . + '\x{7CA4}\x{7CA5}\x{7CA7}\x{7CA8}\x{7CAB}\x{7CAD}\x{7CAE}\x{7CB1}\x{7CB2}' . + '\x{7CB3}\x{7CB9}\x{7CBD}\x{7CBE}\x{7CC0}\x{7CC2}\x{7CC5}\x{7CCA}\x{7CCE}' . + '\x{7CD2}\x{7CD6}\x{7CD8}\x{7CDC}\x{7CDE}\x{7CDF}\x{7CE0}\x{7CE2}\x{7CE7}' . + '\x{7CEF}\x{7CF2}\x{7CF4}\x{7CF6}\x{7CF8}\x{7CFA}\x{7CFB}\x{7CFE}\x{7D00}' . + '\x{7D02}\x{7D04}\x{7D05}\x{7D06}\x{7D0A}\x{7D0B}\x{7D0D}\x{7D10}\x{7D14}' . + '\x{7D15}\x{7D17}\x{7D18}\x{7D19}\x{7D1A}\x{7D1B}\x{7D1C}\x{7D20}\x{7D21}' . + '\x{7D22}\x{7D2B}\x{7D2C}\x{7D2E}\x{7D2F}\x{7D30}\x{7D32}\x{7D33}\x{7D35}' . + '\x{7D39}\x{7D3A}\x{7D3F}\x{7D42}\x{7D43}\x{7D44}\x{7D45}\x{7D46}\x{7D4B}' . + '\x{7D4C}\x{7D4E}\x{7D4F}\x{7D50}\x{7D56}\x{7D5B}\x{7D5E}\x{7D61}\x{7D62}' . + '\x{7D63}\x{7D66}\x{7D68}\x{7D6E}\x{7D71}\x{7D72}\x{7D73}\x{7D75}\x{7D76}' . + '\x{7D79}\x{7D7D}\x{7D89}\x{7D8F}\x{7D93}\x{7D99}\x{7D9A}\x{7D9B}\x{7D9C}' . + '\x{7D9F}\x{7DA2}\x{7DA3}\x{7DAB}\x{7DAC}\x{7DAD}\x{7DAE}\x{7DAF}\x{7DB0}' . + '\x{7DB1}\x{7DB2}\x{7DB4}\x{7DB5}\x{7DB8}\x{7DBA}\x{7DBB}\x{7DBD}\x{7DBE}' . + '\x{7DBF}\x{7DC7}\x{7DCA}\x{7DCB}\x{7DCF}\x{7DD1}\x{7DD2}\x{7DD5}\x{7DD8}' . + '\x{7DDA}\x{7DDC}\x{7DDD}\x{7DDE}\x{7DE0}\x{7DE1}\x{7DE4}\x{7DE8}\x{7DE9}' . + '\x{7DEC}\x{7DEF}\x{7DF2}\x{7DF4}\x{7DFB}\x{7E01}\x{7E04}\x{7E05}\x{7E09}' . + '\x{7E0A}\x{7E0B}\x{7E12}\x{7E1B}\x{7E1E}\x{7E1F}\x{7E21}\x{7E22}\x{7E23}' . + '\x{7E26}\x{7E2B}\x{7E2E}\x{7E31}\x{7E32}\x{7E35}\x{7E37}\x{7E39}\x{7E3A}' . + '\x{7E3B}\x{7E3D}\x{7E3E}\x{7E41}\x{7E43}\x{7E46}\x{7E4A}\x{7E4B}\x{7E4D}' . + '\x{7E54}\x{7E55}\x{7E56}\x{7E59}\x{7E5A}\x{7E5D}\x{7E5E}\x{7E66}\x{7E67}' . + '\x{7E69}\x{7E6A}\x{7E6D}\x{7E70}\x{7E79}\x{7E7B}\x{7E7C}\x{7E7D}\x{7E7F}' . + '\x{7E82}\x{7E83}\x{7E88}\x{7E89}\x{7E8C}\x{7E8E}\x{7E8F}\x{7E90}\x{7E92}' . + '\x{7E93}\x{7E94}\x{7E96}\x{7E9B}\x{7E9C}\x{7F36}\x{7F38}\x{7F3A}\x{7F45}' . + '\x{7F4C}\x{7F4D}\x{7F4E}\x{7F50}\x{7F51}\x{7F54}\x{7F55}\x{7F58}\x{7F5F}' . + '\x{7F60}\x{7F67}\x{7F68}\x{7F69}\x{7F6A}\x{7F6B}\x{7F6E}\x{7F70}\x{7F72}' . + '\x{7F75}\x{7F77}\x{7F78}\x{7F79}\x{7F82}\x{7F83}\x{7F85}\x{7F86}\x{7F87}' . + '\x{7F88}\x{7F8A}\x{7F8C}\x{7F8E}\x{7F94}\x{7F9A}\x{7F9D}\x{7F9E}\x{7FA3}' . + '\x{7FA4}\x{7FA8}\x{7FA9}\x{7FAE}\x{7FAF}\x{7FB2}\x{7FB6}\x{7FB8}\x{7FB9}' . + '\x{7FBD}\x{7FC1}\x{7FC5}\x{7FC6}\x{7FCA}\x{7FCC}\x{7FD2}\x{7FD4}\x{7FD5}' . + '\x{7FE0}\x{7FE1}\x{7FE6}\x{7FE9}\x{7FEB}\x{7FF0}\x{7FF3}\x{7FF9}\x{7FFB}' . + '\x{7FFC}\x{8000}\x{8001}\x{8003}\x{8004}\x{8005}\x{8006}\x{800B}\x{800C}' . + '\x{8010}\x{8012}\x{8015}\x{8017}\x{8018}\x{8019}\x{801C}\x{8021}\x{8028}' . + '\x{8033}\x{8036}\x{803B}\x{803D}\x{803F}\x{8046}\x{804A}\x{8052}\x{8056}' . + '\x{8058}\x{805A}\x{805E}\x{805F}\x{8061}\x{8062}\x{8068}\x{806F}\x{8070}' . + '\x{8072}\x{8073}\x{8074}\x{8076}\x{8077}\x{8079}\x{807D}\x{807E}\x{807F}' . + '\x{8084}\x{8085}\x{8086}\x{8087}\x{8089}\x{808B}\x{808C}\x{8093}\x{8096}' . + '\x{8098}\x{809A}\x{809B}\x{809D}\x{80A1}\x{80A2}\x{80A5}\x{80A9}\x{80AA}' . + '\x{80AC}\x{80AD}\x{80AF}\x{80B1}\x{80B2}\x{80B4}\x{80BA}\x{80C3}\x{80C4}' . + '\x{80C6}\x{80CC}\x{80CE}\x{80D6}\x{80D9}\x{80DA}\x{80DB}\x{80DD}\x{80DE}' . + '\x{80E1}\x{80E4}\x{80E5}\x{80EF}\x{80F1}\x{80F4}\x{80F8}\x{80FC}\x{80FD}' . + '\x{8102}\x{8105}\x{8106}\x{8107}\x{8108}\x{8109}\x{810A}\x{811A}\x{811B}' . + '\x{8123}\x{8129}\x{812F}\x{8131}\x{8133}\x{8139}\x{813E}\x{8146}\x{814B}' . + '\x{814E}\x{8150}\x{8151}\x{8153}\x{8154}\x{8155}\x{815F}\x{8165}\x{8166}' . + '\x{816B}\x{816E}\x{8170}\x{8171}\x{8174}\x{8178}\x{8179}\x{817A}\x{817F}' . + '\x{8180}\x{8182}\x{8183}\x{8188}\x{818A}\x{818F}\x{8193}\x{8195}\x{819A}' . + '\x{819C}\x{819D}\x{81A0}\x{81A3}\x{81A4}\x{81A8}\x{81A9}\x{81B0}\x{81B3}' . + '\x{81B5}\x{81B8}\x{81BA}\x{81BD}\x{81BE}\x{81BF}\x{81C0}\x{81C2}\x{81C6}' . + '\x{81C8}\x{81C9}\x{81CD}\x{81D1}\x{81D3}\x{81D8}\x{81D9}\x{81DA}\x{81DF}' . + '\x{81E0}\x{81E3}\x{81E5}\x{81E7}\x{81E8}\x{81EA}\x{81ED}\x{81F3}\x{81F4}' . + '\x{81FA}\x{81FB}\x{81FC}\x{81FE}\x{8201}\x{8202}\x{8205}\x{8207}\x{8208}' . + '\x{8209}\x{820A}\x{820C}\x{820D}\x{820E}\x{8210}\x{8212}\x{8216}\x{8217}' . + '\x{8218}\x{821B}\x{821C}\x{821E}\x{821F}\x{8229}\x{822A}\x{822B}\x{822C}' . + '\x{822E}\x{8233}\x{8235}\x{8236}\x{8237}\x{8238}\x{8239}\x{8240}\x{8247}' . + '\x{8258}\x{8259}\x{825A}\x{825D}\x{825F}\x{8262}\x{8264}\x{8266}\x{8268}' . + '\x{826A}\x{826B}\x{826E}\x{826F}\x{8271}\x{8272}\x{8276}\x{8277}\x{8278}' . + '\x{827E}\x{828B}\x{828D}\x{8292}\x{8299}\x{829D}\x{829F}\x{82A5}\x{82A6}' . + '\x{82AB}\x{82AC}\x{82AD}\x{82AF}\x{82B1}\x{82B3}\x{82B8}\x{82B9}\x{82BB}' . + '\x{82BD}\x{82C5}\x{82D1}\x{82D2}\x{82D3}\x{82D4}\x{82D7}\x{82D9}\x{82DB}' . + '\x{82DC}\x{82DE}\x{82DF}\x{82E1}\x{82E3}\x{82E5}\x{82E6}\x{82E7}\x{82EB}' . + '\x{82F1}\x{82F3}\x{82F4}\x{82F9}\x{82FA}\x{82FB}\x{8302}\x{8303}\x{8304}' . + '\x{8305}\x{8306}\x{8309}\x{830E}\x{8316}\x{8317}\x{8318}\x{831C}\x{8323}' . + '\x{8328}\x{832B}\x{832F}\x{8331}\x{8332}\x{8334}\x{8335}\x{8336}\x{8338}' . + '\x{8339}\x{8340}\x{8345}\x{8349}\x{834A}\x{834F}\x{8350}\x{8352}\x{8358}' . + '\x{8373}\x{8375}\x{8377}\x{837B}\x{837C}\x{8385}\x{8387}\x{8389}\x{838A}' . + '\x{838E}\x{8393}\x{8396}\x{839A}\x{839E}\x{839F}\x{83A0}\x{83A2}\x{83A8}' . + '\x{83AA}\x{83AB}\x{83B1}\x{83B5}\x{83BD}\x{83C1}\x{83C5}\x{83CA}\x{83CC}' . + '\x{83CE}\x{83D3}\x{83D6}\x{83D8}\x{83DC}\x{83DF}\x{83E0}\x{83E9}\x{83EB}' . + '\x{83EF}\x{83F0}\x{83F1}\x{83F2}\x{83F4}\x{83F7}\x{83FB}\x{83FD}\x{8403}' . + '\x{8404}\x{8407}\x{840B}\x{840C}\x{840D}\x{840E}\x{8413}\x{8420}\x{8422}' . + '\x{8429}\x{842A}\x{842C}\x{8431}\x{8435}\x{8438}\x{843C}\x{843D}\x{8446}' . + '\x{8449}\x{844E}\x{8457}\x{845B}\x{8461}\x{8462}\x{8463}\x{8466}\x{8469}' . + '\x{846B}\x{846C}\x{846D}\x{846E}\x{846F}\x{8471}\x{8475}\x{8477}\x{8479}' . + '\x{847A}\x{8482}\x{8484}\x{848B}\x{8490}\x{8494}\x{8499}\x{849C}\x{849F}' . + '\x{84A1}\x{84AD}\x{84B2}\x{84B8}\x{84B9}\x{84BB}\x{84BC}\x{84BF}\x{84C1}' . + '\x{84C4}\x{84C6}\x{84C9}\x{84CA}\x{84CB}\x{84CD}\x{84D0}\x{84D1}\x{84D6}' . + '\x{84D9}\x{84DA}\x{84EC}\x{84EE}\x{84F4}\x{84FC}\x{84FF}\x{8500}\x{8506}' . + '\x{8511}\x{8513}\x{8514}\x{8515}\x{8517}\x{8518}\x{851A}\x{851F}\x{8521}' . + '\x{8526}\x{852C}\x{852D}\x{8535}\x{853D}\x{8540}\x{8541}\x{8543}\x{8548}' . + '\x{8549}\x{854A}\x{854B}\x{854E}\x{8555}\x{8557}\x{8558}\x{855A}\x{8563}' . + '\x{8568}\x{8569}\x{856A}\x{856D}\x{8577}\x{857E}\x{8580}\x{8584}\x{8587}' . + '\x{8588}\x{858A}\x{8590}\x{8591}\x{8594}\x{8597}\x{8599}\x{859B}\x{859C}' . + '\x{85A4}\x{85A6}\x{85A8}\x{85A9}\x{85AA}\x{85AB}\x{85AC}\x{85AE}\x{85AF}' . + '\x{85B9}\x{85BA}\x{85C1}\x{85C9}\x{85CD}\x{85CF}\x{85D0}\x{85D5}\x{85DC}' . + '\x{85DD}\x{85E4}\x{85E5}\x{85E9}\x{85EA}\x{85F7}\x{85F9}\x{85FA}\x{85FB}' . + '\x{85FE}\x{8602}\x{8606}\x{8607}\x{860A}\x{860B}\x{8613}\x{8616}\x{8617}' . + '\x{861A}\x{8622}\x{862D}\x{862F}\x{8630}\x{863F}\x{864D}\x{864E}\x{8650}' . + '\x{8654}\x{8655}\x{865A}\x{865C}\x{865E}\x{865F}\x{8667}\x{866B}\x{8671}' . + '\x{8679}\x{867B}\x{868A}\x{868B}\x{868C}\x{8693}\x{8695}\x{86A3}\x{86A4}' . + '\x{86A9}\x{86AA}\x{86AB}\x{86AF}\x{86B0}\x{86B6}\x{86C4}\x{86C6}\x{86C7}' . + '\x{86C9}\x{86CB}\x{86CD}\x{86CE}\x{86D4}\x{86D9}\x{86DB}\x{86DE}\x{86DF}' . + '\x{86E4}\x{86E9}\x{86EC}\x{86ED}\x{86EE}\x{86EF}\x{86F8}\x{86F9}\x{86FB}' . + '\x{86FE}\x{8700}\x{8702}\x{8703}\x{8706}\x{8708}\x{8709}\x{870A}\x{870D}' . + '\x{8711}\x{8712}\x{8718}\x{871A}\x{871C}\x{8725}\x{8729}\x{8734}\x{8737}' . + '\x{873B}\x{873F}\x{8749}\x{874B}\x{874C}\x{874E}\x{8753}\x{8755}\x{8757}' . + '\x{8759}\x{875F}\x{8760}\x{8763}\x{8766}\x{8768}\x{876A}\x{876E}\x{8774}' . + '\x{8776}\x{8778}\x{877F}\x{8782}\x{878D}\x{879F}\x{87A2}\x{87AB}\x{87AF}' . + '\x{87B3}\x{87BA}\x{87BB}\x{87BD}\x{87C0}\x{87C4}\x{87C6}\x{87C7}\x{87CB}' . + '\x{87D0}\x{87D2}\x{87E0}\x{87EF}\x{87F2}\x{87F6}\x{87F7}\x{87F9}\x{87FB}' . + '\x{87FE}\x{8805}\x{880D}\x{880E}\x{880F}\x{8811}\x{8815}\x{8816}\x{8821}' . + '\x{8822}\x{8823}\x{8827}\x{8831}\x{8836}\x{8839}\x{883B}\x{8840}\x{8842}' . + '\x{8844}\x{8846}\x{884C}\x{884D}\x{8852}\x{8853}\x{8857}\x{8859}\x{885B}' . + '\x{885D}\x{885E}\x{8861}\x{8862}\x{8863}\x{8868}\x{886B}\x{8870}\x{8872}' . + '\x{8875}\x{8877}\x{887D}\x{887E}\x{887F}\x{8881}\x{8882}\x{8888}\x{888B}' . + '\x{888D}\x{8892}\x{8896}\x{8897}\x{8899}\x{889E}\x{88A2}\x{88A4}\x{88AB}' . + '\x{88AE}\x{88B0}\x{88B1}\x{88B4}\x{88B5}\x{88B7}\x{88BF}\x{88C1}\x{88C2}' . + '\x{88C3}\x{88C4}\x{88C5}\x{88CF}\x{88D4}\x{88D5}\x{88D8}\x{88D9}\x{88DC}' . + '\x{88DD}\x{88DF}\x{88E1}\x{88E8}\x{88F2}\x{88F3}\x{88F4}\x{88F8}\x{88F9}' . + '\x{88FC}\x{88FD}\x{88FE}\x{8902}\x{8904}\x{8907}\x{890A}\x{890C}\x{8910}' . + '\x{8912}\x{8913}\x{891D}\x{891E}\x{8925}\x{892A}\x{892B}\x{8936}\x{8938}' . + '\x{893B}\x{8941}\x{8943}\x{8944}\x{894C}\x{894D}\x{8956}\x{895E}\x{895F}' . + '\x{8960}\x{8964}\x{8966}\x{896A}\x{896D}\x{896F}\x{8972}\x{8974}\x{8977}' . + '\x{897E}\x{897F}\x{8981}\x{8983}\x{8986}\x{8987}\x{8988}\x{898A}\x{898B}' . + '\x{898F}\x{8993}\x{8996}\x{8997}\x{8998}\x{899A}\x{89A1}\x{89A6}\x{89A7}' . + '\x{89A9}\x{89AA}\x{89AC}\x{89AF}\x{89B2}\x{89B3}\x{89BA}\x{89BD}\x{89BF}' . + '\x{89C0}\x{89D2}\x{89DA}\x{89DC}\x{89DD}\x{89E3}\x{89E6}\x{89E7}\x{89F4}' . + '\x{89F8}\x{8A00}\x{8A02}\x{8A03}\x{8A08}\x{8A0A}\x{8A0C}\x{8A0E}\x{8A10}' . + '\x{8A13}\x{8A16}\x{8A17}\x{8A18}\x{8A1B}\x{8A1D}\x{8A1F}\x{8A23}\x{8A25}' . + '\x{8A2A}\x{8A2D}\x{8A31}\x{8A33}\x{8A34}\x{8A36}\x{8A3A}\x{8A3B}\x{8A3C}' . + '\x{8A41}\x{8A46}\x{8A48}\x{8A50}\x{8A51}\x{8A52}\x{8A54}\x{8A55}\x{8A5B}' . + '\x{8A5E}\x{8A60}\x{8A62}\x{8A63}\x{8A66}\x{8A69}\x{8A6B}\x{8A6C}\x{8A6D}' . + '\x{8A6E}\x{8A70}\x{8A71}\x{8A72}\x{8A73}\x{8A7C}\x{8A82}\x{8A84}\x{8A85}' . + '\x{8A87}\x{8A89}\x{8A8C}\x{8A8D}\x{8A91}\x{8A93}\x{8A95}\x{8A98}\x{8A9A}' . + '\x{8A9E}\x{8AA0}\x{8AA1}\x{8AA3}\x{8AA4}\x{8AA5}\x{8AA6}\x{8AA8}\x{8AAC}' . + '\x{8AAD}\x{8AB0}\x{8AB2}\x{8AB9}\x{8ABC}\x{8ABF}\x{8AC2}\x{8AC4}\x{8AC7}' . + '\x{8ACB}\x{8ACC}\x{8ACD}\x{8ACF}\x{8AD2}\x{8AD6}\x{8ADA}\x{8ADB}\x{8ADC}' . + '\x{8ADE}\x{8AE0}\x{8AE1}\x{8AE2}\x{8AE4}\x{8AE6}\x{8AE7}\x{8AEB}\x{8AED}' . + '\x{8AEE}\x{8AF1}\x{8AF3}\x{8AF7}\x{8AF8}\x{8AFA}\x{8AFE}\x{8B00}\x{8B01}' . + '\x{8B02}\x{8B04}\x{8B07}\x{8B0C}\x{8B0E}\x{8B10}\x{8B14}\x{8B16}\x{8B17}' . + '\x{8B19}\x{8B1A}\x{8B1B}\x{8B1D}\x{8B20}\x{8B21}\x{8B26}\x{8B28}\x{8B2B}' . + '\x{8B2C}\x{8B33}\x{8B39}\x{8B3E}\x{8B41}\x{8B49}\x{8B4C}\x{8B4E}\x{8B4F}' . + '\x{8B56}\x{8B58}\x{8B5A}\x{8B5B}\x{8B5C}\x{8B5F}\x{8B66}\x{8B6B}\x{8B6C}' . + '\x{8B6F}\x{8B70}\x{8B71}\x{8B72}\x{8B74}\x{8B77}\x{8B7D}\x{8B80}\x{8B83}' . + '\x{8B8A}\x{8B8C}\x{8B8E}\x{8B90}\x{8B92}\x{8B93}\x{8B96}\x{8B99}\x{8B9A}' . + '\x{8C37}\x{8C3A}\x{8C3F}\x{8C41}\x{8C46}\x{8C48}\x{8C4A}\x{8C4C}\x{8C4E}' . + '\x{8C50}\x{8C55}\x{8C5A}\x{8C61}\x{8C62}\x{8C6A}\x{8C6B}\x{8C6C}\x{8C78}' . + '\x{8C79}\x{8C7A}\x{8C7C}\x{8C82}\x{8C85}\x{8C89}\x{8C8A}\x{8C8C}\x{8C8D}' . + '\x{8C8E}\x{8C94}\x{8C98}\x{8C9D}\x{8C9E}\x{8CA0}\x{8CA1}\x{8CA2}\x{8CA7}' . + '\x{8CA8}\x{8CA9}\x{8CAA}\x{8CAB}\x{8CAC}\x{8CAD}\x{8CAE}\x{8CAF}\x{8CB0}' . + '\x{8CB2}\x{8CB3}\x{8CB4}\x{8CB6}\x{8CB7}\x{8CB8}\x{8CBB}\x{8CBC}\x{8CBD}' . + '\x{8CBF}\x{8CC0}\x{8CC1}\x{8CC2}\x{8CC3}\x{8CC4}\x{8CC7}\x{8CC8}\x{8CCA}' . + '\x{8CCD}\x{8CCE}\x{8CD1}\x{8CD3}\x{8CDA}\x{8CDB}\x{8CDC}\x{8CDE}\x{8CE0}' . + '\x{8CE2}\x{8CE3}\x{8CE4}\x{8CE6}\x{8CEA}\x{8CED}\x{8CFA}\x{8CFB}\x{8CFC}' . + '\x{8CFD}\x{8D04}\x{8D05}\x{8D07}\x{8D08}\x{8D0A}\x{8D0B}\x{8D0D}\x{8D0F}' . + '\x{8D10}\x{8D13}\x{8D14}\x{8D16}\x{8D64}\x{8D66}\x{8D67}\x{8D6B}\x{8D6D}' . + '\x{8D70}\x{8D71}\x{8D73}\x{8D74}\x{8D77}\x{8D81}\x{8D85}\x{8D8A}\x{8D99}' . + '\x{8DA3}\x{8DA8}\x{8DB3}\x{8DBA}\x{8DBE}\x{8DC2}\x{8DCB}\x{8DCC}\x{8DCF}' . + '\x{8DD6}\x{8DDA}\x{8DDB}\x{8DDD}\x{8DDF}\x{8DE1}\x{8DE3}\x{8DE8}\x{8DEA}' . + '\x{8DEB}\x{8DEF}\x{8DF3}\x{8DF5}\x{8DFC}\x{8DFF}\x{8E08}\x{8E09}\x{8E0A}' . + '\x{8E0F}\x{8E10}\x{8E1D}\x{8E1E}\x{8E1F}\x{8E2A}\x{8E30}\x{8E34}\x{8E35}' . + '\x{8E42}\x{8E44}\x{8E47}\x{8E48}\x{8E49}\x{8E4A}\x{8E4C}\x{8E50}\x{8E55}' . + '\x{8E59}\x{8E5F}\x{8E60}\x{8E63}\x{8E64}\x{8E72}\x{8E74}\x{8E76}\x{8E7C}' . + '\x{8E81}\x{8E84}\x{8E85}\x{8E87}\x{8E8A}\x{8E8B}\x{8E8D}\x{8E91}\x{8E93}' . + '\x{8E94}\x{8E99}\x{8EA1}\x{8EAA}\x{8EAB}\x{8EAC}\x{8EAF}\x{8EB0}\x{8EB1}' . + '\x{8EBE}\x{8EC5}\x{8EC6}\x{8EC8}\x{8ECA}\x{8ECB}\x{8ECC}\x{8ECD}\x{8ED2}' . + '\x{8EDB}\x{8EDF}\x{8EE2}\x{8EE3}\x{8EEB}\x{8EF8}\x{8EFB}\x{8EFC}\x{8EFD}' . + '\x{8EFE}\x{8F03}\x{8F05}\x{8F09}\x{8F0A}\x{8F0C}\x{8F12}\x{8F13}\x{8F14}' . + '\x{8F15}\x{8F19}\x{8F1B}\x{8F1C}\x{8F1D}\x{8F1F}\x{8F26}\x{8F29}\x{8F2A}' . + '\x{8F2F}\x{8F33}\x{8F38}\x{8F39}\x{8F3B}\x{8F3E}\x{8F3F}\x{8F42}\x{8F44}' . + '\x{8F45}\x{8F46}\x{8F49}\x{8F4C}\x{8F4D}\x{8F4E}\x{8F57}\x{8F5C}\x{8F5F}' . + '\x{8F61}\x{8F62}\x{8F63}\x{8F64}\x{8F9B}\x{8F9C}\x{8F9E}\x{8F9F}\x{8FA3}' . + '\x{8FA7}\x{8FA8}\x{8FAD}\x{8FAE}\x{8FAF}\x{8FB0}\x{8FB1}\x{8FB2}\x{8FB7}' . + '\x{8FBA}\x{8FBB}\x{8FBC}\x{8FBF}\x{8FC2}\x{8FC4}\x{8FC5}\x{8FCE}\x{8FD1}' . + '\x{8FD4}\x{8FDA}\x{8FE2}\x{8FE5}\x{8FE6}\x{8FE9}\x{8FEA}\x{8FEB}\x{8FED}' . + '\x{8FEF}\x{8FF0}\x{8FF4}\x{8FF7}\x{8FF8}\x{8FF9}\x{8FFA}\x{8FFD}\x{9000}' . + '\x{9001}\x{9003}\x{9005}\x{9006}\x{900B}\x{900D}\x{900E}\x{900F}\x{9010}' . + '\x{9011}\x{9013}\x{9014}\x{9015}\x{9016}\x{9017}\x{9019}\x{901A}\x{901D}' . + '\x{901E}\x{901F}\x{9020}\x{9021}\x{9022}\x{9023}\x{9027}\x{902E}\x{9031}' . + '\x{9032}\x{9035}\x{9036}\x{9038}\x{9039}\x{903C}\x{903E}\x{9041}\x{9042}' . + '\x{9045}\x{9047}\x{9049}\x{904A}\x{904B}\x{904D}\x{904E}\x{904F}\x{9050}' . + '\x{9051}\x{9052}\x{9053}\x{9054}\x{9055}\x{9056}\x{9058}\x{9059}\x{905C}' . + '\x{905E}\x{9060}\x{9061}\x{9063}\x{9065}\x{9068}\x{9069}\x{906D}\x{906E}' . + '\x{906F}\x{9072}\x{9075}\x{9076}\x{9077}\x{9078}\x{907A}\x{907C}\x{907D}' . + '\x{907F}\x{9080}\x{9081}\x{9082}\x{9083}\x{9084}\x{9087}\x{9089}\x{908A}' . + '\x{908F}\x{9091}\x{90A3}\x{90A6}\x{90A8}\x{90AA}\x{90AF}\x{90B1}\x{90B5}' . + '\x{90B8}\x{90C1}\x{90CA}\x{90CE}\x{90DB}\x{90E1}\x{90E2}\x{90E4}\x{90E8}' . + '\x{90ED}\x{90F5}\x{90F7}\x{90FD}\x{9102}\x{9112}\x{9119}\x{912D}\x{9130}' . + '\x{9132}\x{9149}\x{914A}\x{914B}\x{914C}\x{914D}\x{914E}\x{9152}\x{9154}' . + '\x{9156}\x{9158}\x{9162}\x{9163}\x{9165}\x{9169}\x{916A}\x{916C}\x{9172}' . + '\x{9173}\x{9175}\x{9177}\x{9178}\x{9182}\x{9187}\x{9189}\x{918B}\x{918D}' . + '\x{9190}\x{9192}\x{9197}\x{919C}\x{91A2}\x{91A4}\x{91AA}\x{91AB}\x{91AF}' . + '\x{91B4}\x{91B5}\x{91B8}\x{91BA}\x{91C0}\x{91C1}\x{91C6}\x{91C7}\x{91C8}' . + '\x{91C9}\x{91CB}\x{91CC}\x{91CD}\x{91CE}\x{91CF}\x{91D0}\x{91D1}\x{91D6}' . + '\x{91D8}\x{91DB}\x{91DC}\x{91DD}\x{91DF}\x{91E1}\x{91E3}\x{91E6}\x{91E7}' . + '\x{91F5}\x{91F6}\x{91FC}\x{91FF}\x{920D}\x{920E}\x{9211}\x{9214}\x{9215}' . + '\x{921E}\x{9229}\x{922C}\x{9234}\x{9237}\x{923F}\x{9244}\x{9245}\x{9248}' . + '\x{9249}\x{924B}\x{9250}\x{9257}\x{925A}\x{925B}\x{925E}\x{9262}\x{9264}' . + '\x{9266}\x{9271}\x{927E}\x{9280}\x{9283}\x{9285}\x{9291}\x{9293}\x{9295}' . + '\x{9296}\x{9298}\x{929A}\x{929B}\x{929C}\x{92AD}\x{92B7}\x{92B9}\x{92CF}' . + '\x{92D2}\x{92E4}\x{92E9}\x{92EA}\x{92ED}\x{92F2}\x{92F3}\x{92F8}\x{92FA}' . + '\x{92FC}\x{9306}\x{930F}\x{9310}\x{9318}\x{9319}\x{931A}\x{9320}\x{9322}' . + '\x{9323}\x{9326}\x{9328}\x{932B}\x{932C}\x{932E}\x{932F}\x{9332}\x{9335}' . + '\x{933A}\x{933B}\x{9344}\x{934B}\x{934D}\x{9354}\x{9356}\x{935B}\x{935C}' . + '\x{9360}\x{936C}\x{936E}\x{9375}\x{937C}\x{937E}\x{938C}\x{9394}\x{9396}' . + '\x{9397}\x{939A}\x{93A7}\x{93AC}\x{93AD}\x{93AE}\x{93B0}\x{93B9}\x{93C3}' . + '\x{93C8}\x{93D0}\x{93D1}\x{93D6}\x{93D7}\x{93D8}\x{93DD}\x{93E1}\x{93E4}' . + '\x{93E5}\x{93E8}\x{9403}\x{9407}\x{9410}\x{9413}\x{9414}\x{9418}\x{9419}' . + '\x{941A}\x{9421}\x{942B}\x{9435}\x{9436}\x{9438}\x{943A}\x{9441}\x{9444}' . + '\x{9451}\x{9452}\x{9453}\x{945A}\x{945B}\x{945E}\x{9460}\x{9462}\x{946A}' . + '\x{9470}\x{9475}\x{9477}\x{947C}\x{947D}\x{947E}\x{947F}\x{9481}\x{9577}' . + '\x{9580}\x{9582}\x{9583}\x{9587}\x{9589}\x{958A}\x{958B}\x{958F}\x{9591}' . + '\x{9593}\x{9594}\x{9596}\x{9598}\x{9599}\x{95A0}\x{95A2}\x{95A3}\x{95A4}' . + '\x{95A5}\x{95A7}\x{95A8}\x{95AD}\x{95B2}\x{95B9}\x{95BB}\x{95BC}\x{95BE}' . + '\x{95C3}\x{95C7}\x{95CA}\x{95CC}\x{95CD}\x{95D4}\x{95D5}\x{95D6}\x{95D8}' . + '\x{95DC}\x{95E1}\x{95E2}\x{95E5}\x{961C}\x{9621}\x{9628}\x{962A}\x{962E}' . + '\x{962F}\x{9632}\x{963B}\x{963F}\x{9640}\x{9642}\x{9644}\x{964B}\x{964C}' . + '\x{964D}\x{964F}\x{9650}\x{965B}\x{965C}\x{965D}\x{965E}\x{965F}\x{9662}' . + '\x{9663}\x{9664}\x{9665}\x{9666}\x{966A}\x{966C}\x{9670}\x{9672}\x{9673}' . + '\x{9675}\x{9676}\x{9677}\x{9678}\x{967A}\x{967D}\x{9685}\x{9686}\x{9688}' . + '\x{968A}\x{968B}\x{968D}\x{968E}\x{968F}\x{9694}\x{9695}\x{9697}\x{9698}' . + '\x{9699}\x{969B}\x{969C}\x{96A0}\x{96A3}\x{96A7}\x{96A8}\x{96AA}\x{96B0}' . + '\x{96B1}\x{96B2}\x{96B4}\x{96B6}\x{96B7}\x{96B8}\x{96B9}\x{96BB}\x{96BC}' . + '\x{96C0}\x{96C1}\x{96C4}\x{96C5}\x{96C6}\x{96C7}\x{96C9}\x{96CB}\x{96CC}' . + '\x{96CD}\x{96CE}\x{96D1}\x{96D5}\x{96D6}\x{96D9}\x{96DB}\x{96DC}\x{96E2}' . + '\x{96E3}\x{96E8}\x{96EA}\x{96EB}\x{96F0}\x{96F2}\x{96F6}\x{96F7}\x{96F9}' . + '\x{96FB}\x{9700}\x{9704}\x{9706}\x{9707}\x{9708}\x{970A}\x{970D}\x{970E}' . + '\x{970F}\x{9711}\x{9713}\x{9716}\x{9719}\x{971C}\x{971E}\x{9724}\x{9727}' . + '\x{972A}\x{9730}\x{9732}\x{9738}\x{9739}\x{973D}\x{973E}\x{9742}\x{9744}' . + '\x{9746}\x{9748}\x{9749}\x{9752}\x{9756}\x{9759}\x{975C}\x{975E}\x{9760}' . + '\x{9761}\x{9762}\x{9764}\x{9766}\x{9768}\x{9769}\x{976B}\x{976D}\x{9771}' . + '\x{9774}\x{9779}\x{977A}\x{977C}\x{9781}\x{9784}\x{9785}\x{9786}\x{978B}' . + '\x{978D}\x{978F}\x{9790}\x{9798}\x{979C}\x{97A0}\x{97A3}\x{97A6}\x{97A8}' . + '\x{97AB}\x{97AD}\x{97B3}\x{97B4}\x{97C3}\x{97C6}\x{97C8}\x{97CB}\x{97D3}' . + '\x{97DC}\x{97ED}\x{97EE}\x{97F2}\x{97F3}\x{97F5}\x{97F6}\x{97FB}\x{97FF}' . + '\x{9801}\x{9802}\x{9803}\x{9805}\x{9806}\x{9808}\x{980C}\x{980F}\x{9810}' . + '\x{9811}\x{9812}\x{9813}\x{9817}\x{9818}\x{981A}\x{9821}\x{9824}\x{982C}' . + '\x{982D}\x{9834}\x{9837}\x{9838}\x{983B}\x{983C}\x{983D}\x{9846}\x{984B}' . + '\x{984C}\x{984D}\x{984E}\x{984F}\x{9854}\x{9855}\x{9858}\x{985B}\x{985E}' . + '\x{9867}\x{986B}\x{986F}\x{9870}\x{9871}\x{9873}\x{9874}\x{98A8}\x{98AA}' . + '\x{98AF}\x{98B1}\x{98B6}\x{98C3}\x{98C4}\x{98C6}\x{98DB}\x{98DC}\x{98DF}' . + '\x{98E2}\x{98E9}\x{98EB}\x{98ED}\x{98EE}\x{98EF}\x{98F2}\x{98F4}\x{98FC}' . + '\x{98FD}\x{98FE}\x{9903}\x{9905}\x{9909}\x{990A}\x{990C}\x{9910}\x{9912}' . + '\x{9913}\x{9914}\x{9918}\x{991D}\x{991E}\x{9920}\x{9921}\x{9924}\x{9928}' . + '\x{992C}\x{992E}\x{993D}\x{993E}\x{9942}\x{9945}\x{9949}\x{994B}\x{994C}' . + '\x{9950}\x{9951}\x{9952}\x{9955}\x{9957}\x{9996}\x{9997}\x{9998}\x{9999}' . + '\x{99A5}\x{99A8}\x{99AC}\x{99AD}\x{99AE}\x{99B3}\x{99B4}\x{99BC}\x{99C1}' . + '\x{99C4}\x{99C5}\x{99C6}\x{99C8}\x{99D0}\x{99D1}\x{99D2}\x{99D5}\x{99D8}' . + '\x{99DB}\x{99DD}\x{99DF}\x{99E2}\x{99ED}\x{99EE}\x{99F1}\x{99F2}\x{99F8}' . + '\x{99FB}\x{99FF}\x{9A01}\x{9A05}\x{9A0E}\x{9A0F}\x{9A12}\x{9A13}\x{9A19}' . + '\x{9A28}\x{9A2B}\x{9A30}\x{9A37}\x{9A3E}\x{9A40}\x{9A42}\x{9A43}\x{9A45}' . + '\x{9A4D}\x{9A55}\x{9A57}\x{9A5A}\x{9A5B}\x{9A5F}\x{9A62}\x{9A64}\x{9A65}' . + '\x{9A69}\x{9A6A}\x{9A6B}\x{9AA8}\x{9AAD}\x{9AB0}\x{9AB8}\x{9ABC}\x{9AC0}' . + '\x{9AC4}\x{9ACF}\x{9AD1}\x{9AD3}\x{9AD4}\x{9AD8}\x{9ADE}\x{9ADF}\x{9AE2}' . + '\x{9AE3}\x{9AE6}\x{9AEA}\x{9AEB}\x{9AED}\x{9AEE}\x{9AEF}\x{9AF1}\x{9AF4}' . + '\x{9AF7}\x{9AFB}\x{9B06}\x{9B18}\x{9B1A}\x{9B1F}\x{9B22}\x{9B23}\x{9B25}' . + '\x{9B27}\x{9B28}\x{9B29}\x{9B2A}\x{9B2E}\x{9B2F}\x{9B31}\x{9B32}\x{9B3B}' . + '\x{9B3C}\x{9B41}\x{9B42}\x{9B43}\x{9B44}\x{9B45}\x{9B4D}\x{9B4E}\x{9B4F}' . + '\x{9B51}\x{9B54}\x{9B58}\x{9B5A}\x{9B6F}\x{9B74}\x{9B83}\x{9B8E}\x{9B91}' . + '\x{9B92}\x{9B93}\x{9B96}\x{9B97}\x{9B9F}\x{9BA0}\x{9BA8}\x{9BAA}\x{9BAB}' . + '\x{9BAD}\x{9BAE}\x{9BB4}\x{9BB9}\x{9BC0}\x{9BC6}\x{9BC9}\x{9BCA}\x{9BCF}' . + '\x{9BD1}\x{9BD2}\x{9BD4}\x{9BD6}\x{9BDB}\x{9BE1}\x{9BE2}\x{9BE3}\x{9BE4}' . + '\x{9BE8}\x{9BF0}\x{9BF1}\x{9BF2}\x{9BF5}\x{9C04}\x{9C06}\x{9C08}\x{9C09}' . + '\x{9C0A}\x{9C0C}\x{9C0D}\x{9C10}\x{9C12}\x{9C13}\x{9C14}\x{9C15}\x{9C1B}' . + '\x{9C21}\x{9C24}\x{9C25}\x{9C2D}\x{9C2E}\x{9C2F}\x{9C30}\x{9C32}\x{9C39}' . + '\x{9C3A}\x{9C3B}\x{9C3E}\x{9C46}\x{9C47}\x{9C48}\x{9C52}\x{9C57}\x{9C5A}' . + '\x{9C60}\x{9C67}\x{9C76}\x{9C78}\x{9CE5}\x{9CE7}\x{9CE9}\x{9CEB}\x{9CEC}' . + '\x{9CF0}\x{9CF3}\x{9CF4}\x{9CF6}\x{9D03}\x{9D06}\x{9D07}\x{9D08}\x{9D09}' . + '\x{9D0E}\x{9D12}\x{9D15}\x{9D1B}\x{9D1F}\x{9D23}\x{9D26}\x{9D28}\x{9D2A}' . + '\x{9D2B}\x{9D2C}\x{9D3B}\x{9D3E}\x{9D3F}\x{9D41}\x{9D44}\x{9D46}\x{9D48}' . + '\x{9D50}\x{9D51}\x{9D59}\x{9D5C}\x{9D5D}\x{9D5E}\x{9D60}\x{9D61}\x{9D64}' . + '\x{9D6C}\x{9D6F}\x{9D72}\x{9D7A}\x{9D87}\x{9D89}\x{9D8F}\x{9D9A}\x{9DA4}' . + '\x{9DA9}\x{9DAB}\x{9DAF}\x{9DB2}\x{9DB4}\x{9DB8}\x{9DBA}\x{9DBB}\x{9DC1}' . + '\x{9DC2}\x{9DC4}\x{9DC6}\x{9DCF}\x{9DD3}\x{9DD9}\x{9DE6}\x{9DED}\x{9DEF}' . + '\x{9DF2}\x{9DF8}\x{9DF9}\x{9DFA}\x{9DFD}\x{9E1A}\x{9E1B}\x{9E1E}\x{9E75}' . + '\x{9E78}\x{9E79}\x{9E7D}\x{9E7F}\x{9E81}\x{9E88}\x{9E8B}\x{9E8C}\x{9E91}' . + '\x{9E92}\x{9E93}\x{9E95}\x{9E97}\x{9E9D}\x{9E9F}\x{9EA5}\x{9EA6}\x{9EA9}' . + '\x{9EAA}\x{9EAD}\x{9EB8}\x{9EB9}\x{9EBA}\x{9EBB}\x{9EBC}\x{9EBE}\x{9EBF}' . + '\x{9EC4}\x{9ECC}\x{9ECD}\x{9ECE}\x{9ECF}\x{9ED0}\x{9ED2}\x{9ED4}\x{9ED8}' . + '\x{9ED9}\x{9EDB}\x{9EDC}\x{9EDD}\x{9EDE}\x{9EE0}\x{9EE5}\x{9EE8}\x{9EEF}' . + '\x{9EF4}\x{9EF6}\x{9EF7}\x{9EF9}\x{9EFB}\x{9EFC}\x{9EFD}\x{9F07}\x{9F08}' . + '\x{9F0E}\x{9F13}\x{9F15}\x{9F20}\x{9F21}\x{9F2C}\x{9F3B}\x{9F3E}\x{9F4A}' . + '\x{9F4B}\x{9F4E}\x{9F4F}\x{9F52}\x{9F54}\x{9F5F}\x{9F60}\x{9F61}\x{9F62}' . + '\x{9F63}\x{9F66}\x{9F67}\x{9F6A}\x{9F6C}\x{9F72}\x{9F76}\x{9F77}\x{9F8D}' . + '\x{9F95}\x{9F9C}\x{9F9D}\x{9FA0}]{1,15}$/iu', + 12 => '/^[\x{002d}0-9a-z\x{3447}\x{3473}\x{359E}\x{360E}\x{361A}\x{3918}\x{396E}\x{39CF}\x{39D0}' . + '\x{39DF}\x{3A73}\x{3B4E}\x{3C6E}\x{3CE0}\x{4056}\x{415F}\x{4337}\x{43AC}' . + '\x{43B1}\x{43DD}\x{44D6}\x{464C}\x{4661}\x{4723}\x{4729}\x{477C}\x{478D}' . + '\x{4947}\x{497A}\x{497D}\x{4982}\x{4983}\x{4985}\x{4986}\x{499B}\x{499F}' . + '\x{49B6}\x{49B7}\x{4C77}\x{4C9F}\x{4CA0}\x{4CA1}\x{4CA2}\x{4CA3}\x{4D13}' . + '\x{4D14}\x{4D15}\x{4D16}\x{4D17}\x{4D18}\x{4D19}\x{4DAE}\x{4E00}\x{4E01}' . + '\x{4E02}\x{4E03}\x{4E04}\x{4E05}\x{4E06}\x{4E07}\x{4E08}\x{4E09}\x{4E0A}' . + '\x{4E0B}\x{4E0C}\x{4E0D}\x{4E0E}\x{4E0F}\x{4E10}\x{4E11}\x{4E13}\x{4E14}' . + '\x{4E15}\x{4E16}\x{4E17}\x{4E18}\x{4E19}\x{4E1A}\x{4E1B}\x{4E1C}\x{4E1D}' . + '\x{4E1E}\x{4E1F}\x{4E20}\x{4E21}\x{4E22}\x{4E23}\x{4E24}\x{4E25}\x{4E26}' . + '\x{4E27}\x{4E28}\x{4E2A}\x{4E2B}\x{4E2C}\x{4E2D}\x{4E2E}\x{4E2F}\x{4E30}' . + '\x{4E31}\x{4E32}\x{4E33}\x{4E34}\x{4E35}\x{4E36}\x{4E37}\x{4E38}\x{4E39}' . + '\x{4E3A}\x{4E3B}\x{4E3C}\x{4E3D}\x{4E3E}\x{4E3F}\x{4E40}\x{4E41}\x{4E42}' . + '\x{4E43}\x{4E44}\x{4E45}\x{4E46}\x{4E47}\x{4E48}\x{4E49}\x{4E4A}\x{4E4B}' . + '\x{4E4C}\x{4E4D}\x{4E4E}\x{4E4F}\x{4E50}\x{4E51}\x{4E52}\x{4E53}\x{4E54}' . + '\x{4E56}\x{4E57}\x{4E58}\x{4E59}\x{4E5A}\x{4E5B}\x{4E5C}\x{4E5D}\x{4E5E}' . + '\x{4E5F}\x{4E60}\x{4E61}\x{4E62}\x{4E63}\x{4E64}\x{4E65}\x{4E66}\x{4E67}' . + '\x{4E69}\x{4E6A}\x{4E6B}\x{4E6C}\x{4E6D}\x{4E6E}\x{4E6F}\x{4E70}\x{4E71}' . + '\x{4E72}\x{4E73}\x{4E74}\x{4E75}\x{4E76}\x{4E77}\x{4E78}\x{4E7A}\x{4E7B}' . + '\x{4E7C}\x{4E7D}\x{4E7E}\x{4E7F}\x{4E80}\x{4E81}\x{4E82}\x{4E83}\x{4E84}' . + '\x{4E85}\x{4E86}\x{4E87}\x{4E88}\x{4E89}\x{4E8B}\x{4E8C}\x{4E8D}\x{4E8E}' . + '\x{4E8F}\x{4E90}\x{4E91}\x{4E92}\x{4E93}\x{4E94}\x{4E95}\x{4E97}\x{4E98}' . + '\x{4E99}\x{4E9A}\x{4E9B}\x{4E9C}\x{4E9D}\x{4E9E}\x{4E9F}\x{4EA0}\x{4EA1}' . + '\x{4EA2}\x{4EA4}\x{4EA5}\x{4EA6}\x{4EA7}\x{4EA8}\x{4EA9}\x{4EAA}\x{4EAB}' . + '\x{4EAC}\x{4EAD}\x{4EAE}\x{4EAF}\x{4EB0}\x{4EB1}\x{4EB2}\x{4EB3}\x{4EB4}' . + '\x{4EB5}\x{4EB6}\x{4EB7}\x{4EB8}\x{4EB9}\x{4EBA}\x{4EBB}\x{4EBD}\x{4EBE}' . + '\x{4EBF}\x{4EC0}\x{4EC1}\x{4EC2}\x{4EC3}\x{4EC4}\x{4EC5}\x{4EC6}\x{4EC7}' . + '\x{4EC8}\x{4EC9}\x{4ECA}\x{4ECB}\x{4ECD}\x{4ECE}\x{4ECF}\x{4ED0}\x{4ED1}' . + '\x{4ED2}\x{4ED3}\x{4ED4}\x{4ED5}\x{4ED6}\x{4ED7}\x{4ED8}\x{4ED9}\x{4EDA}' . + '\x{4EDB}\x{4EDC}\x{4EDD}\x{4EDE}\x{4EDF}\x{4EE0}\x{4EE1}\x{4EE2}\x{4EE3}' . + '\x{4EE4}\x{4EE5}\x{4EE6}\x{4EE8}\x{4EE9}\x{4EEA}\x{4EEB}\x{4EEC}\x{4EEF}' . + '\x{4EF0}\x{4EF1}\x{4EF2}\x{4EF3}\x{4EF4}\x{4EF5}\x{4EF6}\x{4EF7}\x{4EFB}' . + '\x{4EFD}\x{4EFF}\x{4F00}\x{4F01}\x{4F02}\x{4F03}\x{4F04}\x{4F05}\x{4F06}' . + '\x{4F08}\x{4F09}\x{4F0A}\x{4F0B}\x{4F0C}\x{4F0D}\x{4F0E}\x{4F0F}\x{4F10}' . + '\x{4F11}\x{4F12}\x{4F13}\x{4F14}\x{4F15}\x{4F17}\x{4F18}\x{4F19}\x{4F1A}' . + '\x{4F1B}\x{4F1C}\x{4F1D}\x{4F1E}\x{4F1F}\x{4F20}\x{4F21}\x{4F22}\x{4F23}' . + '\x{4F24}\x{4F25}\x{4F26}\x{4F27}\x{4F29}\x{4F2A}\x{4F2B}\x{4F2C}\x{4F2D}' . + '\x{4F2E}\x{4F2F}\x{4F30}\x{4F32}\x{4F33}\x{4F34}\x{4F36}\x{4F38}\x{4F39}' . + '\x{4F3A}\x{4F3B}\x{4F3C}\x{4F3D}\x{4F3E}\x{4F3F}\x{4F41}\x{4F42}\x{4F43}' . + '\x{4F45}\x{4F46}\x{4F47}\x{4F48}\x{4F49}\x{4F4A}\x{4F4B}\x{4F4C}\x{4F4D}' . + '\x{4F4E}\x{4F4F}\x{4F50}\x{4F51}\x{4F52}\x{4F53}\x{4F54}\x{4F55}\x{4F56}' . + '\x{4F57}\x{4F58}\x{4F59}\x{4F5A}\x{4F5B}\x{4F5C}\x{4F5D}\x{4F5E}\x{4F5F}' . + '\x{4F60}\x{4F61}\x{4F62}\x{4F63}\x{4F64}\x{4F65}\x{4F66}\x{4F67}\x{4F68}' . + '\x{4F69}\x{4F6A}\x{4F6B}\x{4F6C}\x{4F6D}\x{4F6E}\x{4F6F}\x{4F70}\x{4F72}' . + '\x{4F73}\x{4F74}\x{4F75}\x{4F76}\x{4F77}\x{4F78}\x{4F79}\x{4F7A}\x{4F7B}' . + '\x{4F7C}\x{4F7D}\x{4F7E}\x{4F7F}\x{4F80}\x{4F81}\x{4F82}\x{4F83}\x{4F84}' . + '\x{4F85}\x{4F86}\x{4F87}\x{4F88}\x{4F89}\x{4F8A}\x{4F8B}\x{4F8D}\x{4F8F}' . + '\x{4F90}\x{4F91}\x{4F92}\x{4F93}\x{4F94}\x{4F95}\x{4F96}\x{4F97}\x{4F98}' . + '\x{4F99}\x{4F9A}\x{4F9B}\x{4F9C}\x{4F9D}\x{4F9E}\x{4F9F}\x{4FA0}\x{4FA1}' . + '\x{4FA3}\x{4FA4}\x{4FA5}\x{4FA6}\x{4FA7}\x{4FA8}\x{4FA9}\x{4FAA}\x{4FAB}' . + '\x{4FAC}\x{4FAE}\x{4FAF}\x{4FB0}\x{4FB1}\x{4FB2}\x{4FB3}\x{4FB4}\x{4FB5}' . + '\x{4FB6}\x{4FB7}\x{4FB8}\x{4FB9}\x{4FBA}\x{4FBB}\x{4FBC}\x{4FBE}\x{4FBF}' . + '\x{4FC0}\x{4FC1}\x{4FC2}\x{4FC3}\x{4FC4}\x{4FC5}\x{4FC7}\x{4FC9}\x{4FCA}' . + '\x{4FCB}\x{4FCD}\x{4FCE}\x{4FCF}\x{4FD0}\x{4FD1}\x{4FD2}\x{4FD3}\x{4FD4}' . + '\x{4FD5}\x{4FD6}\x{4FD7}\x{4FD8}\x{4FD9}\x{4FDA}\x{4FDB}\x{4FDC}\x{4FDD}' . + '\x{4FDE}\x{4FDF}\x{4FE0}\x{4FE1}\x{4FE3}\x{4FE4}\x{4FE5}\x{4FE6}\x{4FE7}' . + '\x{4FE8}\x{4FE9}\x{4FEA}\x{4FEB}\x{4FEC}\x{4FED}\x{4FEE}\x{4FEF}\x{4FF0}' . + '\x{4FF1}\x{4FF2}\x{4FF3}\x{4FF4}\x{4FF5}\x{4FF6}\x{4FF7}\x{4FF8}\x{4FF9}' . + '\x{4FFA}\x{4FFB}\x{4FFE}\x{4FFF}\x{5000}\x{5001}\x{5002}\x{5003}\x{5004}' . + '\x{5005}\x{5006}\x{5007}\x{5008}\x{5009}\x{500A}\x{500B}\x{500C}\x{500D}' . + '\x{500E}\x{500F}\x{5011}\x{5012}\x{5013}\x{5014}\x{5015}\x{5016}\x{5017}' . + '\x{5018}\x{5019}\x{501A}\x{501B}\x{501C}\x{501D}\x{501E}\x{501F}\x{5020}' . + '\x{5021}\x{5022}\x{5023}\x{5024}\x{5025}\x{5026}\x{5027}\x{5028}\x{5029}' . + '\x{502A}\x{502B}\x{502C}\x{502D}\x{502E}\x{502F}\x{5030}\x{5031}\x{5032}' . + '\x{5033}\x{5035}\x{5036}\x{5037}\x{5039}\x{503A}\x{503B}\x{503C}\x{503E}' . + '\x{503F}\x{5040}\x{5041}\x{5043}\x{5044}\x{5045}\x{5046}\x{5047}\x{5048}' . + '\x{5049}\x{504A}\x{504B}\x{504C}\x{504D}\x{504E}\x{504F}\x{5051}\x{5053}' . + '\x{5054}\x{5055}\x{5056}\x{5057}\x{5059}\x{505A}\x{505B}\x{505C}\x{505D}' . + '\x{505E}\x{505F}\x{5060}\x{5061}\x{5062}\x{5063}\x{5064}\x{5065}\x{5066}' . + '\x{5067}\x{5068}\x{5069}\x{506A}\x{506B}\x{506C}\x{506D}\x{506E}\x{506F}' . + '\x{5070}\x{5071}\x{5072}\x{5073}\x{5074}\x{5075}\x{5076}\x{5077}\x{5078}' . + '\x{5079}\x{507A}\x{507B}\x{507D}\x{507E}\x{507F}\x{5080}\x{5082}\x{5083}' . + '\x{5084}\x{5085}\x{5086}\x{5087}\x{5088}\x{5089}\x{508A}\x{508B}\x{508C}' . + '\x{508D}\x{508E}\x{508F}\x{5090}\x{5091}\x{5092}\x{5094}\x{5095}\x{5096}' . + '\x{5098}\x{5099}\x{509A}\x{509B}\x{509C}\x{509D}\x{509E}\x{50A2}\x{50A3}' . + '\x{50A4}\x{50A5}\x{50A6}\x{50A7}\x{50A8}\x{50A9}\x{50AA}\x{50AB}\x{50AC}' . + '\x{50AD}\x{50AE}\x{50AF}\x{50B0}\x{50B1}\x{50B2}\x{50B3}\x{50B4}\x{50B5}' . + '\x{50B6}\x{50B7}\x{50B8}\x{50BA}\x{50BB}\x{50BC}\x{50BD}\x{50BE}\x{50BF}' . + '\x{50C0}\x{50C1}\x{50C2}\x{50C4}\x{50C5}\x{50C6}\x{50C7}\x{50C8}\x{50C9}' . + '\x{50CA}\x{50CB}\x{50CC}\x{50CD}\x{50CE}\x{50CF}\x{50D0}\x{50D1}\x{50D2}' . + '\x{50D3}\x{50D4}\x{50D5}\x{50D6}\x{50D7}\x{50D9}\x{50DA}\x{50DB}\x{50DC}' . + '\x{50DD}\x{50DE}\x{50E0}\x{50E3}\x{50E4}\x{50E5}\x{50E6}\x{50E7}\x{50E8}' . + '\x{50E9}\x{50EA}\x{50EC}\x{50ED}\x{50EE}\x{50EF}\x{50F0}\x{50F1}\x{50F2}' . + '\x{50F3}\x{50F5}\x{50F6}\x{50F8}\x{50F9}\x{50FA}\x{50FB}\x{50FC}\x{50FD}' . + '\x{50FE}\x{50FF}\x{5100}\x{5101}\x{5102}\x{5103}\x{5104}\x{5105}\x{5106}' . + '\x{5107}\x{5108}\x{5109}\x{510A}\x{510B}\x{510C}\x{510D}\x{510E}\x{510F}' . + '\x{5110}\x{5111}\x{5112}\x{5113}\x{5114}\x{5115}\x{5116}\x{5117}\x{5118}' . + '\x{5119}\x{511A}\x{511C}\x{511D}\x{511E}\x{511F}\x{5120}\x{5121}\x{5122}' . + '\x{5123}\x{5124}\x{5125}\x{5126}\x{5127}\x{5129}\x{512A}\x{512C}\x{512D}' . + '\x{512E}\x{512F}\x{5130}\x{5131}\x{5132}\x{5133}\x{5134}\x{5135}\x{5136}' . + '\x{5137}\x{5138}\x{5139}\x{513A}\x{513B}\x{513C}\x{513D}\x{513E}\x{513F}' . + '\x{5140}\x{5141}\x{5143}\x{5144}\x{5145}\x{5146}\x{5147}\x{5148}\x{5149}' . + '\x{514B}\x{514C}\x{514D}\x{514E}\x{5150}\x{5151}\x{5152}\x{5154}\x{5155}' . + '\x{5156}\x{5157}\x{5159}\x{515A}\x{515B}\x{515C}\x{515D}\x{515E}\x{515F}' . + '\x{5161}\x{5162}\x{5163}\x{5165}\x{5166}\x{5167}\x{5168}\x{5169}\x{516A}' . + '\x{516B}\x{516C}\x{516D}\x{516E}\x{516F}\x{5170}\x{5171}\x{5173}\x{5174}' . + '\x{5175}\x{5176}\x{5177}\x{5178}\x{5179}\x{517A}\x{517B}\x{517C}\x{517D}' . + '\x{517F}\x{5180}\x{5181}\x{5182}\x{5185}\x{5186}\x{5187}\x{5188}\x{5189}' . + '\x{518A}\x{518B}\x{518C}\x{518D}\x{518F}\x{5190}\x{5191}\x{5192}\x{5193}' . + '\x{5194}\x{5195}\x{5196}\x{5197}\x{5198}\x{5199}\x{519A}\x{519B}\x{519C}' . + '\x{519D}\x{519E}\x{519F}\x{51A0}\x{51A2}\x{51A4}\x{51A5}\x{51A6}\x{51A7}' . + '\x{51A8}\x{51AA}\x{51AB}\x{51AC}\x{51AE}\x{51AF}\x{51B0}\x{51B1}\x{51B2}' . + '\x{51B3}\x{51B5}\x{51B6}\x{51B7}\x{51B9}\x{51BB}\x{51BC}\x{51BD}\x{51BE}' . + '\x{51BF}\x{51C0}\x{51C1}\x{51C3}\x{51C4}\x{51C5}\x{51C6}\x{51C7}\x{51C8}' . + '\x{51C9}\x{51CA}\x{51CB}\x{51CC}\x{51CD}\x{51CE}\x{51CF}\x{51D0}\x{51D1}' . + '\x{51D4}\x{51D5}\x{51D6}\x{51D7}\x{51D8}\x{51D9}\x{51DA}\x{51DB}\x{51DC}' . + '\x{51DD}\x{51DE}\x{51E0}\x{51E1}\x{51E2}\x{51E3}\x{51E4}\x{51E5}\x{51E7}' . + '\x{51E8}\x{51E9}\x{51EA}\x{51EB}\x{51ED}\x{51EF}\x{51F0}\x{51F1}\x{51F3}' . + '\x{51F4}\x{51F5}\x{51F6}\x{51F7}\x{51F8}\x{51F9}\x{51FA}\x{51FB}\x{51FC}' . + '\x{51FD}\x{51FE}\x{51FF}\x{5200}\x{5201}\x{5202}\x{5203}\x{5204}\x{5205}' . + '\x{5206}\x{5207}\x{5208}\x{5209}\x{520A}\x{520B}\x{520C}\x{520D}\x{520E}' . + '\x{520F}\x{5210}\x{5211}\x{5212}\x{5213}\x{5214}\x{5215}\x{5216}\x{5217}' . + '\x{5218}\x{5219}\x{521A}\x{521B}\x{521C}\x{521D}\x{521E}\x{521F}\x{5220}' . + '\x{5221}\x{5222}\x{5223}\x{5224}\x{5225}\x{5226}\x{5228}\x{5229}\x{522A}' . + '\x{522B}\x{522C}\x{522D}\x{522E}\x{522F}\x{5230}\x{5231}\x{5232}\x{5233}' . + '\x{5234}\x{5235}\x{5236}\x{5237}\x{5238}\x{5239}\x{523A}\x{523B}\x{523C}' . + '\x{523D}\x{523E}\x{523F}\x{5240}\x{5241}\x{5242}\x{5243}\x{5244}\x{5245}' . + '\x{5246}\x{5247}\x{5248}\x{5249}\x{524A}\x{524B}\x{524C}\x{524D}\x{524E}' . + '\x{5250}\x{5251}\x{5252}\x{5254}\x{5255}\x{5256}\x{5257}\x{5258}\x{5259}' . + '\x{525A}\x{525B}\x{525C}\x{525D}\x{525E}\x{525F}\x{5260}\x{5261}\x{5262}' . + '\x{5263}\x{5264}\x{5265}\x{5267}\x{5268}\x{5269}\x{526A}\x{526B}\x{526C}' . + '\x{526D}\x{526E}\x{526F}\x{5270}\x{5272}\x{5273}\x{5274}\x{5275}\x{5276}' . + '\x{5277}\x{5278}\x{527A}\x{527B}\x{527C}\x{527D}\x{527E}\x{527F}\x{5280}' . + '\x{5281}\x{5282}\x{5283}\x{5284}\x{5286}\x{5287}\x{5288}\x{5289}\x{528A}' . + '\x{528B}\x{528C}\x{528D}\x{528F}\x{5290}\x{5291}\x{5292}\x{5293}\x{5294}' . + '\x{5295}\x{5296}\x{5297}\x{5298}\x{5299}\x{529A}\x{529B}\x{529C}\x{529D}' . + '\x{529E}\x{529F}\x{52A0}\x{52A1}\x{52A2}\x{52A3}\x{52A5}\x{52A6}\x{52A7}' . + '\x{52A8}\x{52A9}\x{52AA}\x{52AB}\x{52AC}\x{52AD}\x{52AE}\x{52AF}\x{52B0}' . + '\x{52B1}\x{52B2}\x{52B3}\x{52B4}\x{52B5}\x{52B6}\x{52B7}\x{52B8}\x{52B9}' . + '\x{52BA}\x{52BB}\x{52BC}\x{52BD}\x{52BE}\x{52BF}\x{52C0}\x{52C1}\x{52C2}' . + '\x{52C3}\x{52C6}\x{52C7}\x{52C9}\x{52CA}\x{52CB}\x{52CD}\x{52CF}\x{52D0}' . + '\x{52D2}\x{52D3}\x{52D5}\x{52D6}\x{52D7}\x{52D8}\x{52D9}\x{52DA}\x{52DB}' . + '\x{52DC}\x{52DD}\x{52DE}\x{52DF}\x{52E0}\x{52E2}\x{52E3}\x{52E4}\x{52E6}' . + '\x{52E7}\x{52E8}\x{52E9}\x{52EA}\x{52EB}\x{52EC}\x{52ED}\x{52EF}\x{52F0}' . + '\x{52F1}\x{52F2}\x{52F3}\x{52F4}\x{52F5}\x{52F6}\x{52F7}\x{52F8}\x{52F9}' . + '\x{52FA}\x{52FB}\x{52FC}\x{52FD}\x{52FE}\x{52FF}\x{5300}\x{5301}\x{5302}' . + '\x{5305}\x{5306}\x{5307}\x{5308}\x{5309}\x{530A}\x{530B}\x{530C}\x{530D}' . + '\x{530E}\x{530F}\x{5310}\x{5311}\x{5312}\x{5313}\x{5314}\x{5315}\x{5316}' . + '\x{5317}\x{5319}\x{531A}\x{531C}\x{531D}\x{531F}\x{5320}\x{5321}\x{5322}' . + '\x{5323}\x{5324}\x{5325}\x{5326}\x{5328}\x{532A}\x{532B}\x{532C}\x{532D}' . + '\x{532E}\x{532F}\x{5330}\x{5331}\x{5333}\x{5334}\x{5337}\x{5339}\x{533A}' . + '\x{533B}\x{533C}\x{533D}\x{533E}\x{533F}\x{5340}\x{5341}\x{5343}\x{5344}' . + '\x{5345}\x{5346}\x{5347}\x{5348}\x{5349}\x{534A}\x{534B}\x{534C}\x{534D}' . + '\x{534E}\x{534F}\x{5350}\x{5351}\x{5352}\x{5353}\x{5354}\x{5355}\x{5356}' . + '\x{5357}\x{5358}\x{5359}\x{535A}\x{535C}\x{535E}\x{535F}\x{5360}\x{5361}' . + '\x{5362}\x{5363}\x{5364}\x{5365}\x{5366}\x{5367}\x{5369}\x{536B}\x{536C}' . + '\x{536E}\x{536F}\x{5370}\x{5371}\x{5372}\x{5373}\x{5374}\x{5375}\x{5376}' . + '\x{5377}\x{5378}\x{5379}\x{537A}\x{537B}\x{537C}\x{537D}\x{537E}\x{537F}' . + '\x{5381}\x{5382}\x{5383}\x{5384}\x{5385}\x{5386}\x{5387}\x{5388}\x{5389}' . + '\x{538A}\x{538B}\x{538C}\x{538D}\x{538E}\x{538F}\x{5390}\x{5391}\x{5392}' . + '\x{5393}\x{5394}\x{5395}\x{5396}\x{5397}\x{5398}\x{5399}\x{539A}\x{539B}' . + '\x{539C}\x{539D}\x{539E}\x{539F}\x{53A0}\x{53A2}\x{53A3}\x{53A4}\x{53A5}' . + '\x{53A6}\x{53A7}\x{53A8}\x{53A9}\x{53AC}\x{53AD}\x{53AE}\x{53B0}\x{53B1}' . + '\x{53B2}\x{53B3}\x{53B4}\x{53B5}\x{53B6}\x{53B7}\x{53B8}\x{53B9}\x{53BB}' . + '\x{53BC}\x{53BD}\x{53BE}\x{53BF}\x{53C0}\x{53C1}\x{53C2}\x{53C3}\x{53C4}' . + '\x{53C6}\x{53C7}\x{53C8}\x{53C9}\x{53CA}\x{53CB}\x{53CC}\x{53CD}\x{53CE}' . + '\x{53D0}\x{53D1}\x{53D2}\x{53D3}\x{53D4}\x{53D5}\x{53D6}\x{53D7}\x{53D8}' . + '\x{53D9}\x{53DB}\x{53DC}\x{53DF}\x{53E0}\x{53E1}\x{53E2}\x{53E3}\x{53E4}' . + '\x{53E5}\x{53E6}\x{53E8}\x{53E9}\x{53EA}\x{53EB}\x{53EC}\x{53ED}\x{53EE}' . + '\x{53EF}\x{53F0}\x{53F1}\x{53F2}\x{53F3}\x{53F4}\x{53F5}\x{53F6}\x{53F7}' . + '\x{53F8}\x{53F9}\x{53FA}\x{53FB}\x{53FC}\x{53FD}\x{53FE}\x{5401}\x{5402}' . + '\x{5403}\x{5404}\x{5405}\x{5406}\x{5407}\x{5408}\x{5409}\x{540A}\x{540B}' . + '\x{540C}\x{540D}\x{540E}\x{540F}\x{5410}\x{5411}\x{5412}\x{5413}\x{5414}' . + '\x{5415}\x{5416}\x{5417}\x{5418}\x{5419}\x{541B}\x{541C}\x{541D}\x{541E}' . + '\x{541F}\x{5420}\x{5421}\x{5423}\x{5424}\x{5425}\x{5426}\x{5427}\x{5428}' . + '\x{5429}\x{542A}\x{542B}\x{542C}\x{542D}\x{542E}\x{542F}\x{5430}\x{5431}' . + '\x{5432}\x{5433}\x{5434}\x{5435}\x{5436}\x{5437}\x{5438}\x{5439}\x{543A}' . + '\x{543B}\x{543C}\x{543D}\x{543E}\x{543F}\x{5440}\x{5441}\x{5442}\x{5443}' . + '\x{5444}\x{5445}\x{5446}\x{5447}\x{5448}\x{5449}\x{544A}\x{544B}\x{544D}' . + '\x{544E}\x{544F}\x{5450}\x{5451}\x{5452}\x{5453}\x{5454}\x{5455}\x{5456}' . + '\x{5457}\x{5458}\x{5459}\x{545A}\x{545B}\x{545C}\x{545E}\x{545F}\x{5460}' . + '\x{5461}\x{5462}\x{5463}\x{5464}\x{5465}\x{5466}\x{5467}\x{5468}\x{546A}' . + '\x{546B}\x{546C}\x{546D}\x{546E}\x{546F}\x{5470}\x{5471}\x{5472}\x{5473}' . + '\x{5474}\x{5475}\x{5476}\x{5477}\x{5478}\x{5479}\x{547A}\x{547B}\x{547C}' . + '\x{547D}\x{547E}\x{547F}\x{5480}\x{5481}\x{5482}\x{5483}\x{5484}\x{5485}' . + '\x{5486}\x{5487}\x{5488}\x{5489}\x{548B}\x{548C}\x{548D}\x{548E}\x{548F}' . + '\x{5490}\x{5491}\x{5492}\x{5493}\x{5494}\x{5495}\x{5496}\x{5497}\x{5498}' . + '\x{5499}\x{549A}\x{549B}\x{549C}\x{549D}\x{549E}\x{549F}\x{54A0}\x{54A1}' . + '\x{54A2}\x{54A3}\x{54A4}\x{54A5}\x{54A6}\x{54A7}\x{54A8}\x{54A9}\x{54AA}' . + '\x{54AB}\x{54AC}\x{54AD}\x{54AE}\x{54AF}\x{54B0}\x{54B1}\x{54B2}\x{54B3}' . + '\x{54B4}\x{54B6}\x{54B7}\x{54B8}\x{54B9}\x{54BA}\x{54BB}\x{54BC}\x{54BD}' . + '\x{54BE}\x{54BF}\x{54C0}\x{54C1}\x{54C2}\x{54C3}\x{54C4}\x{54C5}\x{54C6}' . + '\x{54C7}\x{54C8}\x{54C9}\x{54CA}\x{54CB}\x{54CC}\x{54CD}\x{54CE}\x{54CF}' . + '\x{54D0}\x{54D1}\x{54D2}\x{54D3}\x{54D4}\x{54D5}\x{54D6}\x{54D7}\x{54D8}' . + '\x{54D9}\x{54DA}\x{54DB}\x{54DC}\x{54DD}\x{54DE}\x{54DF}\x{54E0}\x{54E1}' . + '\x{54E2}\x{54E3}\x{54E4}\x{54E5}\x{54E6}\x{54E7}\x{54E8}\x{54E9}\x{54EA}' . + '\x{54EB}\x{54EC}\x{54ED}\x{54EE}\x{54EF}\x{54F0}\x{54F1}\x{54F2}\x{54F3}' . + '\x{54F4}\x{54F5}\x{54F7}\x{54F8}\x{54F9}\x{54FA}\x{54FB}\x{54FC}\x{54FD}' . + '\x{54FE}\x{54FF}\x{5500}\x{5501}\x{5502}\x{5503}\x{5504}\x{5505}\x{5506}' . + '\x{5507}\x{5508}\x{5509}\x{550A}\x{550B}\x{550C}\x{550D}\x{550E}\x{550F}' . + '\x{5510}\x{5511}\x{5512}\x{5513}\x{5514}\x{5516}\x{5517}\x{551A}\x{551B}' . + '\x{551C}\x{551D}\x{551E}\x{551F}\x{5520}\x{5521}\x{5522}\x{5523}\x{5524}' . + '\x{5525}\x{5526}\x{5527}\x{5528}\x{5529}\x{552A}\x{552B}\x{552C}\x{552D}' . + '\x{552E}\x{552F}\x{5530}\x{5531}\x{5532}\x{5533}\x{5534}\x{5535}\x{5536}' . + '\x{5537}\x{5538}\x{5539}\x{553A}\x{553B}\x{553C}\x{553D}\x{553E}\x{553F}' . + '\x{5540}\x{5541}\x{5542}\x{5543}\x{5544}\x{5545}\x{5546}\x{5548}\x{5549}' . + '\x{554A}\x{554B}\x{554C}\x{554D}\x{554E}\x{554F}\x{5550}\x{5551}\x{5552}' . + '\x{5553}\x{5554}\x{5555}\x{5556}\x{5557}\x{5558}\x{5559}\x{555A}\x{555B}' . + '\x{555C}\x{555D}\x{555E}\x{555F}\x{5561}\x{5562}\x{5563}\x{5564}\x{5565}' . + '\x{5566}\x{5567}\x{5568}\x{5569}\x{556A}\x{556B}\x{556C}\x{556D}\x{556E}' . + '\x{556F}\x{5570}\x{5571}\x{5572}\x{5573}\x{5574}\x{5575}\x{5576}\x{5577}' . + '\x{5578}\x{5579}\x{557B}\x{557C}\x{557D}\x{557E}\x{557F}\x{5580}\x{5581}' . + '\x{5582}\x{5583}\x{5584}\x{5585}\x{5586}\x{5587}\x{5588}\x{5589}\x{558A}' . + '\x{558B}\x{558C}\x{558D}\x{558E}\x{558F}\x{5590}\x{5591}\x{5592}\x{5593}' . + '\x{5594}\x{5595}\x{5596}\x{5597}\x{5598}\x{5599}\x{559A}\x{559B}\x{559C}' . + '\x{559D}\x{559E}\x{559F}\x{55A0}\x{55A1}\x{55A2}\x{55A3}\x{55A4}\x{55A5}' . + '\x{55A6}\x{55A7}\x{55A8}\x{55A9}\x{55AA}\x{55AB}\x{55AC}\x{55AD}\x{55AE}' . + '\x{55AF}\x{55B0}\x{55B1}\x{55B2}\x{55B3}\x{55B4}\x{55B5}\x{55B6}\x{55B7}' . + '\x{55B8}\x{55B9}\x{55BA}\x{55BB}\x{55BC}\x{55BD}\x{55BE}\x{55BF}\x{55C0}' . + '\x{55C1}\x{55C2}\x{55C3}\x{55C4}\x{55C5}\x{55C6}\x{55C7}\x{55C8}\x{55C9}' . + '\x{55CA}\x{55CB}\x{55CC}\x{55CD}\x{55CE}\x{55CF}\x{55D0}\x{55D1}\x{55D2}' . + '\x{55D3}\x{55D4}\x{55D5}\x{55D6}\x{55D7}\x{55D8}\x{55D9}\x{55DA}\x{55DB}' . + '\x{55DC}\x{55DD}\x{55DE}\x{55DF}\x{55E1}\x{55E2}\x{55E3}\x{55E4}\x{55E5}' . + '\x{55E6}\x{55E7}\x{55E8}\x{55E9}\x{55EA}\x{55EB}\x{55EC}\x{55ED}\x{55EE}' . + '\x{55EF}\x{55F0}\x{55F1}\x{55F2}\x{55F3}\x{55F4}\x{55F5}\x{55F6}\x{55F7}' . + '\x{55F9}\x{55FA}\x{55FB}\x{55FC}\x{55FD}\x{55FE}\x{55FF}\x{5600}\x{5601}' . + '\x{5602}\x{5603}\x{5604}\x{5606}\x{5607}\x{5608}\x{5609}\x{560C}\x{560D}' . + '\x{560E}\x{560F}\x{5610}\x{5611}\x{5612}\x{5613}\x{5614}\x{5615}\x{5616}' . + '\x{5617}\x{5618}\x{5619}\x{561A}\x{561B}\x{561C}\x{561D}\x{561E}\x{561F}' . + '\x{5621}\x{5622}\x{5623}\x{5624}\x{5625}\x{5626}\x{5627}\x{5628}\x{5629}' . + '\x{562A}\x{562C}\x{562D}\x{562E}\x{562F}\x{5630}\x{5631}\x{5632}\x{5633}' . + '\x{5634}\x{5635}\x{5636}\x{5638}\x{5639}\x{563A}\x{563B}\x{563D}\x{563E}' . + '\x{563F}\x{5640}\x{5641}\x{5642}\x{5643}\x{5645}\x{5646}\x{5647}\x{5648}' . + '\x{5649}\x{564A}\x{564C}\x{564D}\x{564E}\x{564F}\x{5650}\x{5652}\x{5653}' . + '\x{5654}\x{5655}\x{5657}\x{5658}\x{5659}\x{565A}\x{565B}\x{565C}\x{565D}' . + '\x{565E}\x{5660}\x{5662}\x{5663}\x{5664}\x{5665}\x{5666}\x{5667}\x{5668}' . + '\x{5669}\x{566A}\x{566B}\x{566C}\x{566D}\x{566E}\x{566F}\x{5670}\x{5671}' . + '\x{5672}\x{5673}\x{5674}\x{5676}\x{5677}\x{5678}\x{5679}\x{567A}\x{567B}' . + '\x{567C}\x{567E}\x{567F}\x{5680}\x{5681}\x{5682}\x{5683}\x{5684}\x{5685}' . + '\x{5686}\x{5687}\x{568A}\x{568C}\x{568D}\x{568E}\x{568F}\x{5690}\x{5691}' . + '\x{5692}\x{5693}\x{5694}\x{5695}\x{5697}\x{5698}\x{5699}\x{569A}\x{569B}' . + '\x{569C}\x{569D}\x{569F}\x{56A0}\x{56A1}\x{56A3}\x{56A4}\x{56A5}\x{56A6}' . + '\x{56A7}\x{56A8}\x{56A9}\x{56AA}\x{56AB}\x{56AC}\x{56AD}\x{56AE}\x{56AF}' . + '\x{56B0}\x{56B1}\x{56B2}\x{56B3}\x{56B4}\x{56B5}\x{56B6}\x{56B7}\x{56B8}' . + '\x{56B9}\x{56BB}\x{56BC}\x{56BD}\x{56BE}\x{56BF}\x{56C0}\x{56C1}\x{56C2}' . + '\x{56C3}\x{56C4}\x{56C5}\x{56C6}\x{56C7}\x{56C8}\x{56C9}\x{56CA}\x{56CB}' . + '\x{56CC}\x{56CD}\x{56CE}\x{56D0}\x{56D1}\x{56D2}\x{56D3}\x{56D4}\x{56D5}' . + '\x{56D6}\x{56D7}\x{56D8}\x{56DA}\x{56DB}\x{56DC}\x{56DD}\x{56DE}\x{56DF}' . + '\x{56E0}\x{56E1}\x{56E2}\x{56E3}\x{56E4}\x{56E5}\x{56E7}\x{56E8}\x{56E9}' . + '\x{56EA}\x{56EB}\x{56EC}\x{56ED}\x{56EE}\x{56EF}\x{56F0}\x{56F1}\x{56F2}' . + '\x{56F3}\x{56F4}\x{56F5}\x{56F7}\x{56F9}\x{56FA}\x{56FD}\x{56FE}\x{56FF}' . + '\x{5700}\x{5701}\x{5702}\x{5703}\x{5704}\x{5706}\x{5707}\x{5708}\x{5709}' . + '\x{570A}\x{570B}\x{570C}\x{570D}\x{570E}\x{570F}\x{5710}\x{5712}\x{5713}' . + '\x{5714}\x{5715}\x{5716}\x{5718}\x{5719}\x{571A}\x{571B}\x{571C}\x{571D}' . + '\x{571E}\x{571F}\x{5720}\x{5722}\x{5723}\x{5725}\x{5726}\x{5727}\x{5728}' . + '\x{5729}\x{572A}\x{572B}\x{572C}\x{572D}\x{572E}\x{572F}\x{5730}\x{5731}' . + '\x{5732}\x{5733}\x{5734}\x{5735}\x{5736}\x{5737}\x{5738}\x{5739}\x{573A}' . + '\x{573B}\x{573C}\x{573E}\x{573F}\x{5740}\x{5741}\x{5742}\x{5744}\x{5745}' . + '\x{5746}\x{5747}\x{5749}\x{574A}\x{574B}\x{574C}\x{574D}\x{574E}\x{574F}' . + '\x{5750}\x{5751}\x{5752}\x{5753}\x{5754}\x{5757}\x{5759}\x{575A}\x{575B}' . + '\x{575C}\x{575D}\x{575E}\x{575F}\x{5760}\x{5761}\x{5762}\x{5764}\x{5765}' . + '\x{5766}\x{5767}\x{5768}\x{5769}\x{576A}\x{576B}\x{576C}\x{576D}\x{576F}' . + '\x{5770}\x{5771}\x{5772}\x{5773}\x{5774}\x{5775}\x{5776}\x{5777}\x{5779}' . + '\x{577A}\x{577B}\x{577C}\x{577D}\x{577E}\x{577F}\x{5780}\x{5782}\x{5783}' . + '\x{5784}\x{5785}\x{5786}\x{5788}\x{5789}\x{578A}\x{578B}\x{578C}\x{578D}' . + '\x{578E}\x{578F}\x{5790}\x{5791}\x{5792}\x{5793}\x{5794}\x{5795}\x{5797}' . + '\x{5798}\x{5799}\x{579A}\x{579B}\x{579C}\x{579D}\x{579E}\x{579F}\x{57A0}' . + '\x{57A1}\x{57A2}\x{57A3}\x{57A4}\x{57A5}\x{57A6}\x{57A7}\x{57A9}\x{57AA}' . + '\x{57AB}\x{57AC}\x{57AD}\x{57AE}\x{57AF}\x{57B0}\x{57B1}\x{57B2}\x{57B3}' . + '\x{57B4}\x{57B5}\x{57B6}\x{57B7}\x{57B8}\x{57B9}\x{57BA}\x{57BB}\x{57BC}' . + '\x{57BD}\x{57BE}\x{57BF}\x{57C0}\x{57C1}\x{57C2}\x{57C3}\x{57C4}\x{57C5}' . + '\x{57C6}\x{57C7}\x{57C8}\x{57C9}\x{57CB}\x{57CC}\x{57CD}\x{57CE}\x{57CF}' . + '\x{57D0}\x{57D2}\x{57D3}\x{57D4}\x{57D5}\x{57D6}\x{57D8}\x{57D9}\x{57DA}' . + '\x{57DC}\x{57DD}\x{57DF}\x{57E0}\x{57E1}\x{57E2}\x{57E3}\x{57E4}\x{57E5}' . + '\x{57E6}\x{57E7}\x{57E8}\x{57E9}\x{57EA}\x{57EB}\x{57EC}\x{57ED}\x{57EE}' . + '\x{57EF}\x{57F0}\x{57F1}\x{57F2}\x{57F3}\x{57F4}\x{57F5}\x{57F6}\x{57F7}' . + '\x{57F8}\x{57F9}\x{57FA}\x{57FB}\x{57FC}\x{57FD}\x{57FE}\x{57FF}\x{5800}' . + '\x{5801}\x{5802}\x{5803}\x{5804}\x{5805}\x{5806}\x{5807}\x{5808}\x{5809}' . + '\x{580A}\x{580B}\x{580C}\x{580D}\x{580E}\x{580F}\x{5810}\x{5811}\x{5812}' . + '\x{5813}\x{5814}\x{5815}\x{5816}\x{5819}\x{581A}\x{581B}\x{581C}\x{581D}' . + '\x{581E}\x{581F}\x{5820}\x{5821}\x{5822}\x{5823}\x{5824}\x{5825}\x{5826}' . + '\x{5827}\x{5828}\x{5829}\x{582A}\x{582B}\x{582C}\x{582D}\x{582E}\x{582F}' . + '\x{5830}\x{5831}\x{5832}\x{5833}\x{5834}\x{5835}\x{5836}\x{5837}\x{5838}' . + '\x{5839}\x{583A}\x{583B}\x{583C}\x{583D}\x{583E}\x{583F}\x{5840}\x{5842}' . + '\x{5843}\x{5844}\x{5845}\x{5846}\x{5847}\x{5848}\x{5849}\x{584A}\x{584B}' . + '\x{584C}\x{584D}\x{584E}\x{584F}\x{5851}\x{5852}\x{5853}\x{5854}\x{5855}' . + '\x{5857}\x{5858}\x{5859}\x{585A}\x{585B}\x{585C}\x{585D}\x{585E}\x{585F}' . + '\x{5861}\x{5862}\x{5863}\x{5864}\x{5865}\x{5868}\x{5869}\x{586A}\x{586B}' . + '\x{586C}\x{586D}\x{586E}\x{586F}\x{5870}\x{5871}\x{5872}\x{5873}\x{5874}' . + '\x{5875}\x{5876}\x{5878}\x{5879}\x{587A}\x{587B}\x{587C}\x{587D}\x{587E}' . + '\x{587F}\x{5880}\x{5881}\x{5882}\x{5883}\x{5884}\x{5885}\x{5886}\x{5887}' . + '\x{5888}\x{5889}\x{588A}\x{588B}\x{588C}\x{588D}\x{588E}\x{588F}\x{5890}' . + '\x{5891}\x{5892}\x{5893}\x{5894}\x{5896}\x{5897}\x{5898}\x{5899}\x{589A}' . + '\x{589B}\x{589C}\x{589D}\x{589E}\x{589F}\x{58A0}\x{58A1}\x{58A2}\x{58A3}' . + '\x{58A4}\x{58A5}\x{58A6}\x{58A7}\x{58A8}\x{58A9}\x{58AB}\x{58AC}\x{58AD}' . + '\x{58AE}\x{58AF}\x{58B0}\x{58B1}\x{58B2}\x{58B3}\x{58B4}\x{58B7}\x{58B8}' . + '\x{58B9}\x{58BA}\x{58BB}\x{58BC}\x{58BD}\x{58BE}\x{58BF}\x{58C1}\x{58C2}' . + '\x{58C5}\x{58C6}\x{58C7}\x{58C8}\x{58C9}\x{58CA}\x{58CB}\x{58CE}\x{58CF}' . + '\x{58D1}\x{58D2}\x{58D3}\x{58D4}\x{58D5}\x{58D6}\x{58D7}\x{58D8}\x{58D9}' . + '\x{58DA}\x{58DB}\x{58DD}\x{58DE}\x{58DF}\x{58E0}\x{58E2}\x{58E3}\x{58E4}' . + '\x{58E5}\x{58E7}\x{58E8}\x{58E9}\x{58EA}\x{58EB}\x{58EC}\x{58ED}\x{58EE}' . + '\x{58EF}\x{58F0}\x{58F1}\x{58F2}\x{58F3}\x{58F4}\x{58F6}\x{58F7}\x{58F8}' . + '\x{58F9}\x{58FA}\x{58FB}\x{58FC}\x{58FD}\x{58FE}\x{58FF}\x{5900}\x{5902}' . + '\x{5903}\x{5904}\x{5906}\x{5907}\x{5909}\x{590A}\x{590B}\x{590C}\x{590D}' . + '\x{590E}\x{590F}\x{5910}\x{5912}\x{5914}\x{5915}\x{5916}\x{5917}\x{5918}' . + '\x{5919}\x{591A}\x{591B}\x{591C}\x{591D}\x{591E}\x{591F}\x{5920}\x{5921}' . + '\x{5922}\x{5924}\x{5925}\x{5926}\x{5927}\x{5928}\x{5929}\x{592A}\x{592B}' . + '\x{592C}\x{592D}\x{592E}\x{592F}\x{5930}\x{5931}\x{5932}\x{5934}\x{5935}' . + '\x{5937}\x{5938}\x{5939}\x{593A}\x{593B}\x{593C}\x{593D}\x{593E}\x{593F}' . + '\x{5940}\x{5941}\x{5942}\x{5943}\x{5944}\x{5945}\x{5946}\x{5947}\x{5948}' . + '\x{5949}\x{594A}\x{594B}\x{594C}\x{594D}\x{594E}\x{594F}\x{5950}\x{5951}' . + '\x{5952}\x{5953}\x{5954}\x{5955}\x{5956}\x{5957}\x{5958}\x{595A}\x{595C}' . + '\x{595D}\x{595E}\x{595F}\x{5960}\x{5961}\x{5962}\x{5963}\x{5964}\x{5965}' . + '\x{5966}\x{5967}\x{5968}\x{5969}\x{596A}\x{596B}\x{596C}\x{596D}\x{596E}' . + '\x{596F}\x{5970}\x{5971}\x{5972}\x{5973}\x{5974}\x{5975}\x{5976}\x{5977}' . + '\x{5978}\x{5979}\x{597A}\x{597B}\x{597C}\x{597D}\x{597E}\x{597F}\x{5980}' . + '\x{5981}\x{5982}\x{5983}\x{5984}\x{5985}\x{5986}\x{5987}\x{5988}\x{5989}' . + '\x{598A}\x{598B}\x{598C}\x{598D}\x{598E}\x{598F}\x{5990}\x{5991}\x{5992}' . + '\x{5993}\x{5994}\x{5995}\x{5996}\x{5997}\x{5998}\x{5999}\x{599A}\x{599C}' . + '\x{599D}\x{599E}\x{599F}\x{59A0}\x{59A1}\x{59A2}\x{59A3}\x{59A4}\x{59A5}' . + '\x{59A6}\x{59A7}\x{59A8}\x{59A9}\x{59AA}\x{59AB}\x{59AC}\x{59AD}\x{59AE}' . + '\x{59AF}\x{59B0}\x{59B1}\x{59B2}\x{59B3}\x{59B4}\x{59B5}\x{59B6}\x{59B8}' . + '\x{59B9}\x{59BA}\x{59BB}\x{59BC}\x{59BD}\x{59BE}\x{59BF}\x{59C0}\x{59C1}' . + '\x{59C2}\x{59C3}\x{59C4}\x{59C5}\x{59C6}\x{59C7}\x{59C8}\x{59C9}\x{59CA}' . + '\x{59CB}\x{59CC}\x{59CD}\x{59CE}\x{59CF}\x{59D0}\x{59D1}\x{59D2}\x{59D3}' . + '\x{59D4}\x{59D5}\x{59D6}\x{59D7}\x{59D8}\x{59D9}\x{59DA}\x{59DB}\x{59DC}' . + '\x{59DD}\x{59DE}\x{59DF}\x{59E0}\x{59E1}\x{59E2}\x{59E3}\x{59E4}\x{59E5}' . + '\x{59E6}\x{59E8}\x{59E9}\x{59EA}\x{59EB}\x{59EC}\x{59ED}\x{59EE}\x{59EF}' . + '\x{59F0}\x{59F1}\x{59F2}\x{59F3}\x{59F4}\x{59F5}\x{59F6}\x{59F7}\x{59F8}' . + '\x{59F9}\x{59FA}\x{59FB}\x{59FC}\x{59FD}\x{59FE}\x{59FF}\x{5A00}\x{5A01}' . + '\x{5A02}\x{5A03}\x{5A04}\x{5A05}\x{5A06}\x{5A07}\x{5A08}\x{5A09}\x{5A0A}' . + '\x{5A0B}\x{5A0C}\x{5A0D}\x{5A0E}\x{5A0F}\x{5A10}\x{5A11}\x{5A12}\x{5A13}' . + '\x{5A14}\x{5A15}\x{5A16}\x{5A17}\x{5A18}\x{5A19}\x{5A1A}\x{5A1B}\x{5A1C}' . + '\x{5A1D}\x{5A1E}\x{5A1F}\x{5A20}\x{5A21}\x{5A22}\x{5A23}\x{5A25}\x{5A27}' . + '\x{5A28}\x{5A29}\x{5A2A}\x{5A2B}\x{5A2D}\x{5A2E}\x{5A2F}\x{5A31}\x{5A32}' . + '\x{5A33}\x{5A34}\x{5A35}\x{5A36}\x{5A37}\x{5A38}\x{5A39}\x{5A3A}\x{5A3B}' . + '\x{5A3C}\x{5A3D}\x{5A3E}\x{5A3F}\x{5A40}\x{5A41}\x{5A42}\x{5A43}\x{5A44}' . + '\x{5A45}\x{5A46}\x{5A47}\x{5A48}\x{5A49}\x{5A4A}\x{5A4B}\x{5A4C}\x{5A4D}' . + '\x{5A4E}\x{5A4F}\x{5A50}\x{5A51}\x{5A52}\x{5A53}\x{5A55}\x{5A56}\x{5A57}' . + '\x{5A58}\x{5A5A}\x{5A5B}\x{5A5C}\x{5A5D}\x{5A5E}\x{5A5F}\x{5A60}\x{5A61}' . + '\x{5A62}\x{5A63}\x{5A64}\x{5A65}\x{5A66}\x{5A67}\x{5A68}\x{5A69}\x{5A6A}' . + '\x{5A6B}\x{5A6C}\x{5A6D}\x{5A6E}\x{5A70}\x{5A72}\x{5A73}\x{5A74}\x{5A75}' . + '\x{5A76}\x{5A77}\x{5A78}\x{5A79}\x{5A7A}\x{5A7B}\x{5A7C}\x{5A7D}\x{5A7E}' . + '\x{5A7F}\x{5A80}\x{5A81}\x{5A82}\x{5A83}\x{5A84}\x{5A85}\x{5A86}\x{5A88}' . + '\x{5A89}\x{5A8A}\x{5A8B}\x{5A8C}\x{5A8E}\x{5A8F}\x{5A90}\x{5A91}\x{5A92}' . + '\x{5A93}\x{5A94}\x{5A95}\x{5A96}\x{5A97}\x{5A98}\x{5A99}\x{5A9A}\x{5A9B}' . + '\x{5A9C}\x{5A9D}\x{5A9E}\x{5A9F}\x{5AA0}\x{5AA1}\x{5AA2}\x{5AA3}\x{5AA4}' . + '\x{5AA5}\x{5AA6}\x{5AA7}\x{5AA8}\x{5AA9}\x{5AAA}\x{5AAC}\x{5AAD}\x{5AAE}' . + '\x{5AAF}\x{5AB0}\x{5AB1}\x{5AB2}\x{5AB3}\x{5AB4}\x{5AB5}\x{5AB6}\x{5AB7}' . + '\x{5AB8}\x{5AB9}\x{5ABA}\x{5ABB}\x{5ABC}\x{5ABD}\x{5ABE}\x{5ABF}\x{5AC0}' . + '\x{5AC1}\x{5AC2}\x{5AC3}\x{5AC4}\x{5AC5}\x{5AC6}\x{5AC7}\x{5AC8}\x{5AC9}' . + '\x{5ACA}\x{5ACB}\x{5ACC}\x{5ACD}\x{5ACE}\x{5ACF}\x{5AD1}\x{5AD2}\x{5AD4}' . + '\x{5AD5}\x{5AD6}\x{5AD7}\x{5AD8}\x{5AD9}\x{5ADA}\x{5ADB}\x{5ADC}\x{5ADD}' . + '\x{5ADE}\x{5ADF}\x{5AE0}\x{5AE1}\x{5AE2}\x{5AE3}\x{5AE4}\x{5AE5}\x{5AE6}' . + '\x{5AE7}\x{5AE8}\x{5AE9}\x{5AEA}\x{5AEB}\x{5AEC}\x{5AED}\x{5AEE}\x{5AF1}' . + '\x{5AF2}\x{5AF3}\x{5AF4}\x{5AF5}\x{5AF6}\x{5AF7}\x{5AF8}\x{5AF9}\x{5AFA}' . + '\x{5AFB}\x{5AFC}\x{5AFD}\x{5AFE}\x{5AFF}\x{5B00}\x{5B01}\x{5B02}\x{5B03}' . + '\x{5B04}\x{5B05}\x{5B06}\x{5B07}\x{5B08}\x{5B09}\x{5B0B}\x{5B0C}\x{5B0E}' . + '\x{5B0F}\x{5B10}\x{5B11}\x{5B12}\x{5B13}\x{5B14}\x{5B15}\x{5B16}\x{5B17}' . + '\x{5B18}\x{5B19}\x{5B1A}\x{5B1B}\x{5B1C}\x{5B1D}\x{5B1E}\x{5B1F}\x{5B20}' . + '\x{5B21}\x{5B22}\x{5B23}\x{5B24}\x{5B25}\x{5B26}\x{5B27}\x{5B28}\x{5B29}' . + '\x{5B2A}\x{5B2B}\x{5B2C}\x{5B2D}\x{5B2E}\x{5B2F}\x{5B30}\x{5B31}\x{5B32}' . + '\x{5B33}\x{5B34}\x{5B35}\x{5B36}\x{5B37}\x{5B38}\x{5B3A}\x{5B3B}\x{5B3C}' . + '\x{5B3D}\x{5B3E}\x{5B3F}\x{5B40}\x{5B41}\x{5B42}\x{5B43}\x{5B44}\x{5B45}' . + '\x{5B47}\x{5B48}\x{5B49}\x{5B4A}\x{5B4B}\x{5B4C}\x{5B4D}\x{5B4E}\x{5B50}' . + '\x{5B51}\x{5B53}\x{5B54}\x{5B55}\x{5B56}\x{5B57}\x{5B58}\x{5B59}\x{5B5A}' . + '\x{5B5B}\x{5B5C}\x{5B5D}\x{5B5E}\x{5B5F}\x{5B62}\x{5B63}\x{5B64}\x{5B65}' . + '\x{5B66}\x{5B67}\x{5B68}\x{5B69}\x{5B6A}\x{5B6B}\x{5B6C}\x{5B6D}\x{5B6E}' . + '\x{5B70}\x{5B71}\x{5B72}\x{5B73}\x{5B74}\x{5B75}\x{5B76}\x{5B77}\x{5B78}' . + '\x{5B7A}\x{5B7B}\x{5B7C}\x{5B7D}\x{5B7F}\x{5B80}\x{5B81}\x{5B82}\x{5B83}' . + '\x{5B84}\x{5B85}\x{5B87}\x{5B88}\x{5B89}\x{5B8A}\x{5B8B}\x{5B8C}\x{5B8D}' . + '\x{5B8E}\x{5B8F}\x{5B91}\x{5B92}\x{5B93}\x{5B94}\x{5B95}\x{5B96}\x{5B97}' . + '\x{5B98}\x{5B99}\x{5B9A}\x{5B9B}\x{5B9C}\x{5B9D}\x{5B9E}\x{5B9F}\x{5BA0}' . + '\x{5BA1}\x{5BA2}\x{5BA3}\x{5BA4}\x{5BA5}\x{5BA6}\x{5BA7}\x{5BA8}\x{5BAA}' . + '\x{5BAB}\x{5BAC}\x{5BAD}\x{5BAE}\x{5BAF}\x{5BB0}\x{5BB1}\x{5BB3}\x{5BB4}' . + '\x{5BB5}\x{5BB6}\x{5BB8}\x{5BB9}\x{5BBA}\x{5BBB}\x{5BBD}\x{5BBE}\x{5BBF}' . + '\x{5BC0}\x{5BC1}\x{5BC2}\x{5BC3}\x{5BC4}\x{5BC5}\x{5BC6}\x{5BC7}\x{5BCA}' . + '\x{5BCB}\x{5BCC}\x{5BCD}\x{5BCE}\x{5BCF}\x{5BD0}\x{5BD1}\x{5BD2}\x{5BD3}' . + '\x{5BD4}\x{5BD5}\x{5BD6}\x{5BD8}\x{5BD9}\x{5BDB}\x{5BDC}\x{5BDD}\x{5BDE}' . + '\x{5BDF}\x{5BE0}\x{5BE1}\x{5BE2}\x{5BE3}\x{5BE4}\x{5BE5}\x{5BE6}\x{5BE7}' . + '\x{5BE8}\x{5BE9}\x{5BEA}\x{5BEB}\x{5BEC}\x{5BED}\x{5BEE}\x{5BEF}\x{5BF0}' . + '\x{5BF1}\x{5BF2}\x{5BF3}\x{5BF4}\x{5BF5}\x{5BF6}\x{5BF7}\x{5BF8}\x{5BF9}' . + '\x{5BFA}\x{5BFB}\x{5BFC}\x{5BFD}\x{5BFF}\x{5C01}\x{5C03}\x{5C04}\x{5C05}' . + '\x{5C06}\x{5C07}\x{5C08}\x{5C09}\x{5C0A}\x{5C0B}\x{5C0C}\x{5C0D}\x{5C0E}' . + '\x{5C0F}\x{5C10}\x{5C11}\x{5C12}\x{5C13}\x{5C14}\x{5C15}\x{5C16}\x{5C17}' . + '\x{5C18}\x{5C19}\x{5C1A}\x{5C1C}\x{5C1D}\x{5C1E}\x{5C1F}\x{5C20}\x{5C21}' . + '\x{5C22}\x{5C24}\x{5C25}\x{5C27}\x{5C28}\x{5C2A}\x{5C2B}\x{5C2C}\x{5C2D}' . + '\x{5C2E}\x{5C2F}\x{5C30}\x{5C31}\x{5C32}\x{5C33}\x{5C34}\x{5C35}\x{5C37}' . + '\x{5C38}\x{5C39}\x{5C3A}\x{5C3B}\x{5C3C}\x{5C3D}\x{5C3E}\x{5C3F}\x{5C40}' . + '\x{5C41}\x{5C42}\x{5C43}\x{5C44}\x{5C45}\x{5C46}\x{5C47}\x{5C48}\x{5C49}' . + '\x{5C4A}\x{5C4B}\x{5C4C}\x{5C4D}\x{5C4E}\x{5C4F}\x{5C50}\x{5C51}\x{5C52}' . + '\x{5C53}\x{5C54}\x{5C55}\x{5C56}\x{5C57}\x{5C58}\x{5C59}\x{5C5B}\x{5C5C}' . + '\x{5C5D}\x{5C5E}\x{5C5F}\x{5C60}\x{5C61}\x{5C62}\x{5C63}\x{5C64}\x{5C65}' . + '\x{5C66}\x{5C67}\x{5C68}\x{5C69}\x{5C6A}\x{5C6B}\x{5C6C}\x{5C6D}\x{5C6E}' . + '\x{5C6F}\x{5C70}\x{5C71}\x{5C72}\x{5C73}\x{5C74}\x{5C75}\x{5C76}\x{5C77}' . + '\x{5C78}\x{5C79}\x{5C7A}\x{5C7B}\x{5C7C}\x{5C7D}\x{5C7E}\x{5C7F}\x{5C80}' . + '\x{5C81}\x{5C82}\x{5C83}\x{5C84}\x{5C86}\x{5C87}\x{5C88}\x{5C89}\x{5C8A}' . + '\x{5C8B}\x{5C8C}\x{5C8D}\x{5C8E}\x{5C8F}\x{5C90}\x{5C91}\x{5C92}\x{5C93}' . + '\x{5C94}\x{5C95}\x{5C96}\x{5C97}\x{5C98}\x{5C99}\x{5C9A}\x{5C9B}\x{5C9C}' . + '\x{5C9D}\x{5C9E}\x{5C9F}\x{5CA0}\x{5CA1}\x{5CA2}\x{5CA3}\x{5CA4}\x{5CA5}' . + '\x{5CA6}\x{5CA7}\x{5CA8}\x{5CA9}\x{5CAA}\x{5CAB}\x{5CAC}\x{5CAD}\x{5CAE}' . + '\x{5CAF}\x{5CB0}\x{5CB1}\x{5CB2}\x{5CB3}\x{5CB5}\x{5CB6}\x{5CB7}\x{5CB8}' . + '\x{5CBA}\x{5CBB}\x{5CBC}\x{5CBD}\x{5CBE}\x{5CBF}\x{5CC1}\x{5CC2}\x{5CC3}' . + '\x{5CC4}\x{5CC5}\x{5CC6}\x{5CC7}\x{5CC8}\x{5CC9}\x{5CCA}\x{5CCB}\x{5CCC}' . + '\x{5CCD}\x{5CCE}\x{5CCF}\x{5CD0}\x{5CD1}\x{5CD2}\x{5CD3}\x{5CD4}\x{5CD6}' . + '\x{5CD7}\x{5CD8}\x{5CD9}\x{5CDA}\x{5CDB}\x{5CDC}\x{5CDE}\x{5CDF}\x{5CE0}' . + '\x{5CE1}\x{5CE2}\x{5CE3}\x{5CE4}\x{5CE5}\x{5CE6}\x{5CE7}\x{5CE8}\x{5CE9}' . + '\x{5CEA}\x{5CEB}\x{5CEC}\x{5CED}\x{5CEE}\x{5CEF}\x{5CF0}\x{5CF1}\x{5CF2}' . + '\x{5CF3}\x{5CF4}\x{5CF6}\x{5CF7}\x{5CF8}\x{5CF9}\x{5CFA}\x{5CFB}\x{5CFC}' . + '\x{5CFD}\x{5CFE}\x{5CFF}\x{5D00}\x{5D01}\x{5D02}\x{5D03}\x{5D04}\x{5D05}' . + '\x{5D06}\x{5D07}\x{5D08}\x{5D09}\x{5D0A}\x{5D0B}\x{5D0C}\x{5D0D}\x{5D0E}' . + '\x{5D0F}\x{5D10}\x{5D11}\x{5D12}\x{5D13}\x{5D14}\x{5D15}\x{5D16}\x{5D17}' . + '\x{5D18}\x{5D19}\x{5D1A}\x{5D1B}\x{5D1C}\x{5D1D}\x{5D1E}\x{5D1F}\x{5D20}' . + '\x{5D21}\x{5D22}\x{5D23}\x{5D24}\x{5D25}\x{5D26}\x{5D27}\x{5D28}\x{5D29}' . + '\x{5D2A}\x{5D2C}\x{5D2D}\x{5D2E}\x{5D30}\x{5D31}\x{5D32}\x{5D33}\x{5D34}' . + '\x{5D35}\x{5D36}\x{5D37}\x{5D38}\x{5D39}\x{5D3A}\x{5D3C}\x{5D3D}\x{5D3E}' . + '\x{5D3F}\x{5D40}\x{5D41}\x{5D42}\x{5D43}\x{5D44}\x{5D45}\x{5D46}\x{5D47}' . + '\x{5D48}\x{5D49}\x{5D4A}\x{5D4B}\x{5D4C}\x{5D4D}\x{5D4E}\x{5D4F}\x{5D50}' . + '\x{5D51}\x{5D52}\x{5D54}\x{5D55}\x{5D56}\x{5D58}\x{5D59}\x{5D5A}\x{5D5B}' . + '\x{5D5D}\x{5D5E}\x{5D5F}\x{5D61}\x{5D62}\x{5D63}\x{5D64}\x{5D65}\x{5D66}' . + '\x{5D67}\x{5D68}\x{5D69}\x{5D6A}\x{5D6B}\x{5D6C}\x{5D6D}\x{5D6E}\x{5D6F}' . + '\x{5D70}\x{5D71}\x{5D72}\x{5D73}\x{5D74}\x{5D75}\x{5D76}\x{5D77}\x{5D78}' . + '\x{5D79}\x{5D7A}\x{5D7B}\x{5D7C}\x{5D7D}\x{5D7E}\x{5D7F}\x{5D80}\x{5D81}' . + '\x{5D82}\x{5D84}\x{5D85}\x{5D86}\x{5D87}\x{5D88}\x{5D89}\x{5D8A}\x{5D8B}' . + '\x{5D8C}\x{5D8D}\x{5D8E}\x{5D8F}\x{5D90}\x{5D91}\x{5D92}\x{5D93}\x{5D94}' . + '\x{5D95}\x{5D97}\x{5D98}\x{5D99}\x{5D9A}\x{5D9B}\x{5D9C}\x{5D9D}\x{5D9E}' . + '\x{5D9F}\x{5DA0}\x{5DA1}\x{5DA2}\x{5DA5}\x{5DA6}\x{5DA7}\x{5DA8}\x{5DA9}' . + '\x{5DAA}\x{5DAC}\x{5DAD}\x{5DAE}\x{5DAF}\x{5DB0}\x{5DB1}\x{5DB2}\x{5DB4}' . + '\x{5DB5}\x{5DB6}\x{5DB7}\x{5DB8}\x{5DBA}\x{5DBB}\x{5DBC}\x{5DBD}\x{5DBE}' . + '\x{5DBF}\x{5DC0}\x{5DC1}\x{5DC2}\x{5DC3}\x{5DC5}\x{5DC6}\x{5DC7}\x{5DC8}' . + '\x{5DC9}\x{5DCA}\x{5DCB}\x{5DCC}\x{5DCD}\x{5DCE}\x{5DCF}\x{5DD0}\x{5DD1}' . + '\x{5DD2}\x{5DD3}\x{5DD4}\x{5DD5}\x{5DD6}\x{5DD8}\x{5DD9}\x{5DDB}\x{5DDD}' . + '\x{5DDE}\x{5DDF}\x{5DE0}\x{5DE1}\x{5DE2}\x{5DE3}\x{5DE4}\x{5DE5}\x{5DE6}' . + '\x{5DE7}\x{5DE8}\x{5DE9}\x{5DEA}\x{5DEB}\x{5DEC}\x{5DED}\x{5DEE}\x{5DEF}' . + '\x{5DF0}\x{5DF1}\x{5DF2}\x{5DF3}\x{5DF4}\x{5DF5}\x{5DF7}\x{5DF8}\x{5DF9}' . + '\x{5DFA}\x{5DFB}\x{5DFC}\x{5DFD}\x{5DFE}\x{5DFF}\x{5E00}\x{5E01}\x{5E02}' . + '\x{5E03}\x{5E04}\x{5E05}\x{5E06}\x{5E07}\x{5E08}\x{5E09}\x{5E0A}\x{5E0B}' . + '\x{5E0C}\x{5E0D}\x{5E0E}\x{5E0F}\x{5E10}\x{5E11}\x{5E13}\x{5E14}\x{5E15}' . + '\x{5E16}\x{5E17}\x{5E18}\x{5E19}\x{5E1A}\x{5E1B}\x{5E1C}\x{5E1D}\x{5E1E}' . + '\x{5E1F}\x{5E20}\x{5E21}\x{5E22}\x{5E23}\x{5E24}\x{5E25}\x{5E26}\x{5E27}' . + '\x{5E28}\x{5E29}\x{5E2A}\x{5E2B}\x{5E2C}\x{5E2D}\x{5E2E}\x{5E2F}\x{5E30}' . + '\x{5E31}\x{5E32}\x{5E33}\x{5E34}\x{5E35}\x{5E36}\x{5E37}\x{5E38}\x{5E39}' . + '\x{5E3A}\x{5E3B}\x{5E3C}\x{5E3D}\x{5E3E}\x{5E40}\x{5E41}\x{5E42}\x{5E43}' . + '\x{5E44}\x{5E45}\x{5E46}\x{5E47}\x{5E49}\x{5E4A}\x{5E4B}\x{5E4C}\x{5E4D}' . + '\x{5E4E}\x{5E4F}\x{5E50}\x{5E52}\x{5E53}\x{5E54}\x{5E55}\x{5E56}\x{5E57}' . + '\x{5E58}\x{5E59}\x{5E5A}\x{5E5B}\x{5E5C}\x{5E5D}\x{5E5E}\x{5E5F}\x{5E60}' . + '\x{5E61}\x{5E62}\x{5E63}\x{5E64}\x{5E65}\x{5E66}\x{5E67}\x{5E68}\x{5E69}' . + '\x{5E6A}\x{5E6B}\x{5E6C}\x{5E6D}\x{5E6E}\x{5E6F}\x{5E70}\x{5E71}\x{5E72}' . + '\x{5E73}\x{5E74}\x{5E75}\x{5E76}\x{5E77}\x{5E78}\x{5E79}\x{5E7A}\x{5E7B}' . + '\x{5E7C}\x{5E7D}\x{5E7E}\x{5E7F}\x{5E80}\x{5E81}\x{5E82}\x{5E83}\x{5E84}' . + '\x{5E85}\x{5E86}\x{5E87}\x{5E88}\x{5E89}\x{5E8A}\x{5E8B}\x{5E8C}\x{5E8D}' . + '\x{5E8E}\x{5E8F}\x{5E90}\x{5E91}\x{5E93}\x{5E94}\x{5E95}\x{5E96}\x{5E97}' . + '\x{5E98}\x{5E99}\x{5E9A}\x{5E9B}\x{5E9C}\x{5E9D}\x{5E9E}\x{5E9F}\x{5EA0}' . + '\x{5EA1}\x{5EA2}\x{5EA3}\x{5EA4}\x{5EA5}\x{5EA6}\x{5EA7}\x{5EA8}\x{5EA9}' . + '\x{5EAA}\x{5EAB}\x{5EAC}\x{5EAD}\x{5EAE}\x{5EAF}\x{5EB0}\x{5EB1}\x{5EB2}' . + '\x{5EB3}\x{5EB4}\x{5EB5}\x{5EB6}\x{5EB7}\x{5EB8}\x{5EB9}\x{5EBB}\x{5EBC}' . + '\x{5EBD}\x{5EBE}\x{5EBF}\x{5EC1}\x{5EC2}\x{5EC3}\x{5EC4}\x{5EC5}\x{5EC6}' . + '\x{5EC7}\x{5EC8}\x{5EC9}\x{5ECA}\x{5ECB}\x{5ECC}\x{5ECD}\x{5ECE}\x{5ECF}' . + '\x{5ED0}\x{5ED1}\x{5ED2}\x{5ED3}\x{5ED4}\x{5ED5}\x{5ED6}\x{5ED7}\x{5ED8}' . + '\x{5ED9}\x{5EDA}\x{5EDB}\x{5EDC}\x{5EDD}\x{5EDE}\x{5EDF}\x{5EE0}\x{5EE1}' . + '\x{5EE2}\x{5EE3}\x{5EE4}\x{5EE5}\x{5EE6}\x{5EE7}\x{5EE8}\x{5EE9}\x{5EEA}' . + '\x{5EEC}\x{5EED}\x{5EEE}\x{5EEF}\x{5EF0}\x{5EF1}\x{5EF2}\x{5EF3}\x{5EF4}' . + '\x{5EF5}\x{5EF6}\x{5EF7}\x{5EF8}\x{5EFA}\x{5EFB}\x{5EFC}\x{5EFD}\x{5EFE}' . + '\x{5EFF}\x{5F00}\x{5F01}\x{5F02}\x{5F03}\x{5F04}\x{5F05}\x{5F06}\x{5F07}' . + '\x{5F08}\x{5F0A}\x{5F0B}\x{5F0C}\x{5F0D}\x{5F0F}\x{5F11}\x{5F12}\x{5F13}' . + '\x{5F14}\x{5F15}\x{5F16}\x{5F17}\x{5F18}\x{5F19}\x{5F1A}\x{5F1B}\x{5F1C}' . + '\x{5F1D}\x{5F1E}\x{5F1F}\x{5F20}\x{5F21}\x{5F22}\x{5F23}\x{5F24}\x{5F25}' . + '\x{5F26}\x{5F27}\x{5F28}\x{5F29}\x{5F2A}\x{5F2B}\x{5F2C}\x{5F2D}\x{5F2E}' . + '\x{5F2F}\x{5F30}\x{5F31}\x{5F32}\x{5F33}\x{5F34}\x{5F35}\x{5F36}\x{5F37}' . + '\x{5F38}\x{5F39}\x{5F3A}\x{5F3C}\x{5F3E}\x{5F3F}\x{5F40}\x{5F41}\x{5F42}' . + '\x{5F43}\x{5F44}\x{5F45}\x{5F46}\x{5F47}\x{5F48}\x{5F49}\x{5F4A}\x{5F4B}' . + '\x{5F4C}\x{5F4D}\x{5F4E}\x{5F4F}\x{5F50}\x{5F51}\x{5F52}\x{5F53}\x{5F54}' . + '\x{5F55}\x{5F56}\x{5F57}\x{5F58}\x{5F59}\x{5F5A}\x{5F5B}\x{5F5C}\x{5F5D}' . + '\x{5F5E}\x{5F5F}\x{5F60}\x{5F61}\x{5F62}\x{5F63}\x{5F64}\x{5F65}\x{5F66}' . + '\x{5F67}\x{5F68}\x{5F69}\x{5F6A}\x{5F6B}\x{5F6C}\x{5F6D}\x{5F6E}\x{5F6F}' . + '\x{5F70}\x{5F71}\x{5F72}\x{5F73}\x{5F74}\x{5F75}\x{5F76}\x{5F77}\x{5F78}' . + '\x{5F79}\x{5F7A}\x{5F7B}\x{5F7C}\x{5F7D}\x{5F7E}\x{5F7F}\x{5F80}\x{5F81}' . + '\x{5F82}\x{5F83}\x{5F84}\x{5F85}\x{5F86}\x{5F87}\x{5F88}\x{5F89}\x{5F8A}' . + '\x{5F8B}\x{5F8C}\x{5F8D}\x{5F8E}\x{5F90}\x{5F91}\x{5F92}\x{5F93}\x{5F94}' . + '\x{5F95}\x{5F96}\x{5F97}\x{5F98}\x{5F99}\x{5F9B}\x{5F9C}\x{5F9D}\x{5F9E}' . + '\x{5F9F}\x{5FA0}\x{5FA1}\x{5FA2}\x{5FA5}\x{5FA6}\x{5FA7}\x{5FA8}\x{5FA9}' . + '\x{5FAA}\x{5FAB}\x{5FAC}\x{5FAD}\x{5FAE}\x{5FAF}\x{5FB1}\x{5FB2}\x{5FB3}' . + '\x{5FB4}\x{5FB5}\x{5FB6}\x{5FB7}\x{5FB8}\x{5FB9}\x{5FBA}\x{5FBB}\x{5FBC}' . + '\x{5FBD}\x{5FBE}\x{5FBF}\x{5FC0}\x{5FC1}\x{5FC3}\x{5FC4}\x{5FC5}\x{5FC6}' . + '\x{5FC7}\x{5FC8}\x{5FC9}\x{5FCA}\x{5FCB}\x{5FCC}\x{5FCD}\x{5FCF}\x{5FD0}' . + '\x{5FD1}\x{5FD2}\x{5FD3}\x{5FD4}\x{5FD5}\x{5FD6}\x{5FD7}\x{5FD8}\x{5FD9}' . + '\x{5FDA}\x{5FDC}\x{5FDD}\x{5FDE}\x{5FE0}\x{5FE1}\x{5FE3}\x{5FE4}\x{5FE5}' . + '\x{5FE6}\x{5FE7}\x{5FE8}\x{5FE9}\x{5FEA}\x{5FEB}\x{5FED}\x{5FEE}\x{5FEF}' . + '\x{5FF0}\x{5FF1}\x{5FF2}\x{5FF3}\x{5FF4}\x{5FF5}\x{5FF6}\x{5FF7}\x{5FF8}' . + '\x{5FF9}\x{5FFA}\x{5FFB}\x{5FFD}\x{5FFE}\x{5FFF}\x{6000}\x{6001}\x{6002}' . + '\x{6003}\x{6004}\x{6005}\x{6006}\x{6007}\x{6008}\x{6009}\x{600A}\x{600B}' . + '\x{600C}\x{600D}\x{600E}\x{600F}\x{6010}\x{6011}\x{6012}\x{6013}\x{6014}' . + '\x{6015}\x{6016}\x{6017}\x{6018}\x{6019}\x{601A}\x{601B}\x{601C}\x{601D}' . + '\x{601E}\x{601F}\x{6020}\x{6021}\x{6022}\x{6024}\x{6025}\x{6026}\x{6027}' . + '\x{6028}\x{6029}\x{602A}\x{602B}\x{602C}\x{602D}\x{602E}\x{602F}\x{6030}' . + '\x{6031}\x{6032}\x{6033}\x{6034}\x{6035}\x{6036}\x{6037}\x{6038}\x{6039}' . + '\x{603A}\x{603B}\x{603C}\x{603D}\x{603E}\x{603F}\x{6040}\x{6041}\x{6042}' . + '\x{6043}\x{6044}\x{6045}\x{6046}\x{6047}\x{6048}\x{6049}\x{604A}\x{604B}' . + '\x{604C}\x{604D}\x{604E}\x{604F}\x{6050}\x{6051}\x{6052}\x{6053}\x{6054}' . + '\x{6055}\x{6057}\x{6058}\x{6059}\x{605A}\x{605B}\x{605C}\x{605D}\x{605E}' . + '\x{605F}\x{6062}\x{6063}\x{6064}\x{6065}\x{6066}\x{6067}\x{6068}\x{6069}' . + '\x{606A}\x{606B}\x{606C}\x{606D}\x{606E}\x{606F}\x{6070}\x{6072}\x{6073}' . + '\x{6075}\x{6076}\x{6077}\x{6078}\x{6079}\x{607A}\x{607B}\x{607C}\x{607D}' . + '\x{607E}\x{607F}\x{6080}\x{6081}\x{6082}\x{6083}\x{6084}\x{6085}\x{6086}' . + '\x{6087}\x{6088}\x{6089}\x{608A}\x{608B}\x{608C}\x{608D}\x{608E}\x{608F}' . + '\x{6090}\x{6092}\x{6094}\x{6095}\x{6096}\x{6097}\x{6098}\x{6099}\x{609A}' . + '\x{609B}\x{609C}\x{609D}\x{609E}\x{609F}\x{60A0}\x{60A1}\x{60A2}\x{60A3}' . + '\x{60A4}\x{60A6}\x{60A7}\x{60A8}\x{60AA}\x{60AB}\x{60AC}\x{60AD}\x{60AE}' . + '\x{60AF}\x{60B0}\x{60B1}\x{60B2}\x{60B3}\x{60B4}\x{60B5}\x{60B6}\x{60B7}' . + '\x{60B8}\x{60B9}\x{60BA}\x{60BB}\x{60BC}\x{60BD}\x{60BE}\x{60BF}\x{60C0}' . + '\x{60C1}\x{60C2}\x{60C3}\x{60C4}\x{60C5}\x{60C6}\x{60C7}\x{60C8}\x{60C9}' . + '\x{60CA}\x{60CB}\x{60CC}\x{60CD}\x{60CE}\x{60CF}\x{60D0}\x{60D1}\x{60D3}' . + '\x{60D4}\x{60D5}\x{60D7}\x{60D8}\x{60D9}\x{60DA}\x{60DB}\x{60DC}\x{60DD}' . + '\x{60DF}\x{60E0}\x{60E1}\x{60E2}\x{60E4}\x{60E6}\x{60E7}\x{60E8}\x{60E9}' . + '\x{60EA}\x{60EB}\x{60EC}\x{60ED}\x{60EE}\x{60EF}\x{60F0}\x{60F1}\x{60F2}' . + '\x{60F3}\x{60F4}\x{60F5}\x{60F6}\x{60F7}\x{60F8}\x{60F9}\x{60FA}\x{60FB}' . + '\x{60FC}\x{60FE}\x{60FF}\x{6100}\x{6101}\x{6103}\x{6104}\x{6105}\x{6106}' . + '\x{6108}\x{6109}\x{610A}\x{610B}\x{610C}\x{610D}\x{610E}\x{610F}\x{6110}' . + '\x{6112}\x{6113}\x{6114}\x{6115}\x{6116}\x{6117}\x{6118}\x{6119}\x{611A}' . + '\x{611B}\x{611C}\x{611D}\x{611F}\x{6120}\x{6122}\x{6123}\x{6124}\x{6125}' . + '\x{6126}\x{6127}\x{6128}\x{6129}\x{612A}\x{612B}\x{612C}\x{612D}\x{612E}' . + '\x{612F}\x{6130}\x{6132}\x{6134}\x{6136}\x{6137}\x{613A}\x{613B}\x{613C}' . + '\x{613D}\x{613E}\x{613F}\x{6140}\x{6141}\x{6142}\x{6143}\x{6144}\x{6145}' . + '\x{6146}\x{6147}\x{6148}\x{6149}\x{614A}\x{614B}\x{614C}\x{614D}\x{614E}' . + '\x{614F}\x{6150}\x{6151}\x{6152}\x{6153}\x{6154}\x{6155}\x{6156}\x{6157}' . + '\x{6158}\x{6159}\x{615A}\x{615B}\x{615C}\x{615D}\x{615E}\x{615F}\x{6161}' . + '\x{6162}\x{6163}\x{6164}\x{6165}\x{6166}\x{6167}\x{6168}\x{6169}\x{616A}' . + '\x{616B}\x{616C}\x{616D}\x{616E}\x{6170}\x{6171}\x{6172}\x{6173}\x{6174}' . + '\x{6175}\x{6176}\x{6177}\x{6178}\x{6179}\x{617A}\x{617C}\x{617E}\x{6180}' . + '\x{6181}\x{6182}\x{6183}\x{6184}\x{6185}\x{6187}\x{6188}\x{6189}\x{618A}' . + '\x{618B}\x{618C}\x{618D}\x{618E}\x{618F}\x{6190}\x{6191}\x{6192}\x{6193}' . + '\x{6194}\x{6195}\x{6196}\x{6198}\x{6199}\x{619A}\x{619B}\x{619D}\x{619E}' . + '\x{619F}\x{61A0}\x{61A1}\x{61A2}\x{61A3}\x{61A4}\x{61A5}\x{61A6}\x{61A7}' . + '\x{61A8}\x{61A9}\x{61AA}\x{61AB}\x{61AC}\x{61AD}\x{61AE}\x{61AF}\x{61B0}' . + '\x{61B1}\x{61B2}\x{61B3}\x{61B4}\x{61B5}\x{61B6}\x{61B7}\x{61B8}\x{61BA}' . + '\x{61BC}\x{61BD}\x{61BE}\x{61BF}\x{61C0}\x{61C1}\x{61C2}\x{61C3}\x{61C4}' . + '\x{61C5}\x{61C6}\x{61C7}\x{61C8}\x{61C9}\x{61CA}\x{61CB}\x{61CC}\x{61CD}' . + '\x{61CE}\x{61CF}\x{61D0}\x{61D1}\x{61D2}\x{61D4}\x{61D6}\x{61D7}\x{61D8}' . + '\x{61D9}\x{61DA}\x{61DB}\x{61DC}\x{61DD}\x{61DE}\x{61DF}\x{61E0}\x{61E1}' . + '\x{61E2}\x{61E3}\x{61E4}\x{61E5}\x{61E6}\x{61E7}\x{61E8}\x{61E9}\x{61EA}' . + '\x{61EB}\x{61ED}\x{61EE}\x{61F0}\x{61F1}\x{61F2}\x{61F3}\x{61F5}\x{61F6}' . + '\x{61F7}\x{61F8}\x{61F9}\x{61FA}\x{61FB}\x{61FC}\x{61FD}\x{61FE}\x{61FF}' . + '\x{6200}\x{6201}\x{6202}\x{6203}\x{6204}\x{6206}\x{6207}\x{6208}\x{6209}' . + '\x{620A}\x{620B}\x{620C}\x{620D}\x{620E}\x{620F}\x{6210}\x{6211}\x{6212}' . + '\x{6213}\x{6214}\x{6215}\x{6216}\x{6217}\x{6218}\x{6219}\x{621A}\x{621B}' . + '\x{621C}\x{621D}\x{621E}\x{621F}\x{6220}\x{6221}\x{6222}\x{6223}\x{6224}' . + '\x{6225}\x{6226}\x{6227}\x{6228}\x{6229}\x{622A}\x{622B}\x{622C}\x{622D}' . + '\x{622E}\x{622F}\x{6230}\x{6231}\x{6232}\x{6233}\x{6234}\x{6236}\x{6237}' . + '\x{6238}\x{623A}\x{623B}\x{623C}\x{623D}\x{623E}\x{623F}\x{6240}\x{6241}' . + '\x{6242}\x{6243}\x{6244}\x{6245}\x{6246}\x{6247}\x{6248}\x{6249}\x{624A}' . + '\x{624B}\x{624C}\x{624D}\x{624E}\x{624F}\x{6250}\x{6251}\x{6252}\x{6253}' . + '\x{6254}\x{6255}\x{6256}\x{6258}\x{6259}\x{625A}\x{625B}\x{625C}\x{625D}' . + '\x{625E}\x{625F}\x{6260}\x{6261}\x{6262}\x{6263}\x{6264}\x{6265}\x{6266}' . + '\x{6267}\x{6268}\x{6269}\x{626A}\x{626B}\x{626C}\x{626D}\x{626E}\x{626F}' . + '\x{6270}\x{6271}\x{6272}\x{6273}\x{6274}\x{6275}\x{6276}\x{6277}\x{6278}' . + '\x{6279}\x{627A}\x{627B}\x{627C}\x{627D}\x{627E}\x{627F}\x{6280}\x{6281}' . + '\x{6283}\x{6284}\x{6285}\x{6286}\x{6287}\x{6288}\x{6289}\x{628A}\x{628B}' . + '\x{628C}\x{628E}\x{628F}\x{6290}\x{6291}\x{6292}\x{6293}\x{6294}\x{6295}' . + '\x{6296}\x{6297}\x{6298}\x{6299}\x{629A}\x{629B}\x{629C}\x{629E}\x{629F}' . + '\x{62A0}\x{62A1}\x{62A2}\x{62A3}\x{62A4}\x{62A5}\x{62A7}\x{62A8}\x{62A9}' . + '\x{62AA}\x{62AB}\x{62AC}\x{62AD}\x{62AE}\x{62AF}\x{62B0}\x{62B1}\x{62B2}' . + '\x{62B3}\x{62B4}\x{62B5}\x{62B6}\x{62B7}\x{62B8}\x{62B9}\x{62BA}\x{62BB}' . + '\x{62BC}\x{62BD}\x{62BE}\x{62BF}\x{62C0}\x{62C1}\x{62C2}\x{62C3}\x{62C4}' . + '\x{62C5}\x{62C6}\x{62C7}\x{62C8}\x{62C9}\x{62CA}\x{62CB}\x{62CC}\x{62CD}' . + '\x{62CE}\x{62CF}\x{62D0}\x{62D1}\x{62D2}\x{62D3}\x{62D4}\x{62D5}\x{62D6}' . + '\x{62D7}\x{62D8}\x{62D9}\x{62DA}\x{62DB}\x{62DC}\x{62DD}\x{62DF}\x{62E0}' . + '\x{62E1}\x{62E2}\x{62E3}\x{62E4}\x{62E5}\x{62E6}\x{62E7}\x{62E8}\x{62E9}' . + '\x{62EB}\x{62EC}\x{62ED}\x{62EE}\x{62EF}\x{62F0}\x{62F1}\x{62F2}\x{62F3}' . + '\x{62F4}\x{62F5}\x{62F6}\x{62F7}\x{62F8}\x{62F9}\x{62FA}\x{62FB}\x{62FC}' . + '\x{62FD}\x{62FE}\x{62FF}\x{6300}\x{6301}\x{6302}\x{6303}\x{6304}\x{6305}' . + '\x{6306}\x{6307}\x{6308}\x{6309}\x{630B}\x{630C}\x{630D}\x{630E}\x{630F}' . + '\x{6310}\x{6311}\x{6312}\x{6313}\x{6314}\x{6315}\x{6316}\x{6318}\x{6319}' . + '\x{631A}\x{631B}\x{631C}\x{631D}\x{631E}\x{631F}\x{6320}\x{6321}\x{6322}' . + '\x{6323}\x{6324}\x{6325}\x{6326}\x{6327}\x{6328}\x{6329}\x{632A}\x{632B}' . + '\x{632C}\x{632D}\x{632E}\x{632F}\x{6330}\x{6332}\x{6333}\x{6334}\x{6336}' . + '\x{6338}\x{6339}\x{633A}\x{633B}\x{633C}\x{633D}\x{633E}\x{6340}\x{6341}' . + '\x{6342}\x{6343}\x{6344}\x{6345}\x{6346}\x{6347}\x{6348}\x{6349}\x{634A}' . + '\x{634B}\x{634C}\x{634D}\x{634E}\x{634F}\x{6350}\x{6351}\x{6352}\x{6353}' . + '\x{6354}\x{6355}\x{6356}\x{6357}\x{6358}\x{6359}\x{635A}\x{635C}\x{635D}' . + '\x{635E}\x{635F}\x{6360}\x{6361}\x{6362}\x{6363}\x{6364}\x{6365}\x{6366}' . + '\x{6367}\x{6368}\x{6369}\x{636A}\x{636B}\x{636C}\x{636D}\x{636E}\x{636F}' . + '\x{6370}\x{6371}\x{6372}\x{6373}\x{6374}\x{6375}\x{6376}\x{6377}\x{6378}' . + '\x{6379}\x{637A}\x{637B}\x{637C}\x{637D}\x{637E}\x{6380}\x{6381}\x{6382}' . + '\x{6383}\x{6384}\x{6385}\x{6386}\x{6387}\x{6388}\x{6389}\x{638A}\x{638C}' . + '\x{638D}\x{638E}\x{638F}\x{6390}\x{6391}\x{6392}\x{6394}\x{6395}\x{6396}' . + '\x{6397}\x{6398}\x{6399}\x{639A}\x{639B}\x{639C}\x{639D}\x{639E}\x{639F}' . + '\x{63A0}\x{63A1}\x{63A2}\x{63A3}\x{63A4}\x{63A5}\x{63A6}\x{63A7}\x{63A8}' . + '\x{63A9}\x{63AA}\x{63AB}\x{63AC}\x{63AD}\x{63AE}\x{63AF}\x{63B0}\x{63B1}' . + '\x{63B2}\x{63B3}\x{63B4}\x{63B5}\x{63B6}\x{63B7}\x{63B8}\x{63B9}\x{63BA}' . + '\x{63BC}\x{63BD}\x{63BE}\x{63BF}\x{63C0}\x{63C1}\x{63C2}\x{63C3}\x{63C4}' . + '\x{63C5}\x{63C6}\x{63C7}\x{63C8}\x{63C9}\x{63CA}\x{63CB}\x{63CC}\x{63CD}' . + '\x{63CE}\x{63CF}\x{63D0}\x{63D2}\x{63D3}\x{63D4}\x{63D5}\x{63D6}\x{63D7}' . + '\x{63D8}\x{63D9}\x{63DA}\x{63DB}\x{63DC}\x{63DD}\x{63DE}\x{63DF}\x{63E0}' . + '\x{63E1}\x{63E2}\x{63E3}\x{63E4}\x{63E5}\x{63E6}\x{63E7}\x{63E8}\x{63E9}' . + '\x{63EA}\x{63EB}\x{63EC}\x{63ED}\x{63EE}\x{63EF}\x{63F0}\x{63F1}\x{63F2}' . + '\x{63F3}\x{63F4}\x{63F5}\x{63F6}\x{63F7}\x{63F8}\x{63F9}\x{63FA}\x{63FB}' . + '\x{63FC}\x{63FD}\x{63FE}\x{63FF}\x{6400}\x{6401}\x{6402}\x{6403}\x{6404}' . + '\x{6405}\x{6406}\x{6408}\x{6409}\x{640A}\x{640B}\x{640C}\x{640D}\x{640E}' . + '\x{640F}\x{6410}\x{6411}\x{6412}\x{6413}\x{6414}\x{6415}\x{6416}\x{6417}' . + '\x{6418}\x{6419}\x{641A}\x{641B}\x{641C}\x{641D}\x{641E}\x{641F}\x{6420}' . + '\x{6421}\x{6422}\x{6423}\x{6424}\x{6425}\x{6426}\x{6427}\x{6428}\x{6429}' . + '\x{642A}\x{642B}\x{642C}\x{642D}\x{642E}\x{642F}\x{6430}\x{6431}\x{6432}' . + '\x{6433}\x{6434}\x{6435}\x{6436}\x{6437}\x{6438}\x{6439}\x{643A}\x{643D}' . + '\x{643E}\x{643F}\x{6440}\x{6441}\x{6443}\x{6444}\x{6445}\x{6446}\x{6447}' . + '\x{6448}\x{644A}\x{644B}\x{644C}\x{644D}\x{644E}\x{644F}\x{6450}\x{6451}' . + '\x{6452}\x{6453}\x{6454}\x{6455}\x{6456}\x{6457}\x{6458}\x{6459}\x{645B}' . + '\x{645C}\x{645D}\x{645E}\x{645F}\x{6460}\x{6461}\x{6462}\x{6463}\x{6464}' . + '\x{6465}\x{6466}\x{6467}\x{6468}\x{6469}\x{646A}\x{646B}\x{646C}\x{646D}' . + '\x{646E}\x{646F}\x{6470}\x{6471}\x{6472}\x{6473}\x{6474}\x{6475}\x{6476}' . + '\x{6477}\x{6478}\x{6479}\x{647A}\x{647B}\x{647C}\x{647D}\x{647F}\x{6480}' . + '\x{6481}\x{6482}\x{6483}\x{6484}\x{6485}\x{6487}\x{6488}\x{6489}\x{648A}' . + '\x{648B}\x{648C}\x{648D}\x{648E}\x{648F}\x{6490}\x{6491}\x{6492}\x{6493}' . + '\x{6494}\x{6495}\x{6496}\x{6497}\x{6498}\x{6499}\x{649A}\x{649B}\x{649C}' . + '\x{649D}\x{649E}\x{649F}\x{64A0}\x{64A2}\x{64A3}\x{64A4}\x{64A5}\x{64A6}' . + '\x{64A7}\x{64A8}\x{64A9}\x{64AA}\x{64AB}\x{64AC}\x{64AD}\x{64AE}\x{64B0}' . + '\x{64B1}\x{64B2}\x{64B3}\x{64B4}\x{64B5}\x{64B7}\x{64B8}\x{64B9}\x{64BA}' . + '\x{64BB}\x{64BC}\x{64BD}\x{64BE}\x{64BF}\x{64C0}\x{64C1}\x{64C2}\x{64C3}' . + '\x{64C4}\x{64C5}\x{64C6}\x{64C7}\x{64C9}\x{64CA}\x{64CB}\x{64CC}\x{64CD}' . + '\x{64CE}\x{64CF}\x{64D0}\x{64D1}\x{64D2}\x{64D3}\x{64D4}\x{64D6}\x{64D7}' . + '\x{64D8}\x{64D9}\x{64DA}\x{64DB}\x{64DC}\x{64DD}\x{64DE}\x{64DF}\x{64E0}' . + '\x{64E2}\x{64E3}\x{64E4}\x{64E6}\x{64E7}\x{64E8}\x{64E9}\x{64EA}\x{64EB}' . + '\x{64EC}\x{64ED}\x{64EF}\x{64F0}\x{64F1}\x{64F2}\x{64F3}\x{64F4}\x{64F6}' . + '\x{64F7}\x{64F8}\x{64FA}\x{64FB}\x{64FC}\x{64FD}\x{64FE}\x{64FF}\x{6500}' . + '\x{6501}\x{6503}\x{6504}\x{6505}\x{6506}\x{6507}\x{6508}\x{6509}\x{650B}' . + '\x{650C}\x{650D}\x{650E}\x{650F}\x{6510}\x{6511}\x{6512}\x{6513}\x{6514}' . + '\x{6515}\x{6516}\x{6517}\x{6518}\x{6519}\x{651A}\x{651B}\x{651C}\x{651D}' . + '\x{651E}\x{6520}\x{6521}\x{6522}\x{6523}\x{6524}\x{6525}\x{6526}\x{6527}' . + '\x{6529}\x{652A}\x{652B}\x{652C}\x{652D}\x{652E}\x{652F}\x{6530}\x{6531}' . + '\x{6532}\x{6533}\x{6534}\x{6535}\x{6536}\x{6537}\x{6538}\x{6539}\x{653A}' . + '\x{653B}\x{653C}\x{653D}\x{653E}\x{653F}\x{6541}\x{6543}\x{6544}\x{6545}' . + '\x{6546}\x{6547}\x{6548}\x{6549}\x{654A}\x{654B}\x{654C}\x{654D}\x{654E}' . + '\x{654F}\x{6550}\x{6551}\x{6552}\x{6553}\x{6554}\x{6555}\x{6556}\x{6557}' . + '\x{6558}\x{6559}\x{655B}\x{655C}\x{655D}\x{655E}\x{6560}\x{6561}\x{6562}' . + '\x{6563}\x{6564}\x{6565}\x{6566}\x{6567}\x{6568}\x{6569}\x{656A}\x{656B}' . + '\x{656C}\x{656E}\x{656F}\x{6570}\x{6571}\x{6572}\x{6573}\x{6574}\x{6575}' . + '\x{6576}\x{6577}\x{6578}\x{6579}\x{657A}\x{657B}\x{657C}\x{657E}\x{657F}' . + '\x{6580}\x{6581}\x{6582}\x{6583}\x{6584}\x{6585}\x{6586}\x{6587}\x{6588}' . + '\x{6589}\x{658B}\x{658C}\x{658D}\x{658E}\x{658F}\x{6590}\x{6591}\x{6592}' . + '\x{6593}\x{6594}\x{6595}\x{6596}\x{6597}\x{6598}\x{6599}\x{659B}\x{659C}' . + '\x{659D}\x{659E}\x{659F}\x{65A0}\x{65A1}\x{65A2}\x{65A3}\x{65A4}\x{65A5}' . + '\x{65A6}\x{65A7}\x{65A8}\x{65A9}\x{65AA}\x{65AB}\x{65AC}\x{65AD}\x{65AE}' . + '\x{65AF}\x{65B0}\x{65B1}\x{65B2}\x{65B3}\x{65B4}\x{65B6}\x{65B7}\x{65B8}' . + '\x{65B9}\x{65BA}\x{65BB}\x{65BC}\x{65BD}\x{65BF}\x{65C0}\x{65C1}\x{65C2}' . + '\x{65C3}\x{65C4}\x{65C5}\x{65C6}\x{65C7}\x{65CA}\x{65CB}\x{65CC}\x{65CD}' . + '\x{65CE}\x{65CF}\x{65D0}\x{65D2}\x{65D3}\x{65D4}\x{65D5}\x{65D6}\x{65D7}' . + '\x{65DA}\x{65DB}\x{65DD}\x{65DE}\x{65DF}\x{65E0}\x{65E1}\x{65E2}\x{65E3}' . + '\x{65E5}\x{65E6}\x{65E7}\x{65E8}\x{65E9}\x{65EB}\x{65EC}\x{65ED}\x{65EE}' . + '\x{65EF}\x{65F0}\x{65F1}\x{65F2}\x{65F3}\x{65F4}\x{65F5}\x{65F6}\x{65F7}' . + '\x{65F8}\x{65FA}\x{65FB}\x{65FC}\x{65FD}\x{6600}\x{6601}\x{6602}\x{6603}' . + '\x{6604}\x{6605}\x{6606}\x{6607}\x{6608}\x{6609}\x{660A}\x{660B}\x{660C}' . + '\x{660D}\x{660E}\x{660F}\x{6610}\x{6611}\x{6612}\x{6613}\x{6614}\x{6615}' . + '\x{6616}\x{6618}\x{6619}\x{661A}\x{661B}\x{661C}\x{661D}\x{661F}\x{6620}' . + '\x{6621}\x{6622}\x{6623}\x{6624}\x{6625}\x{6626}\x{6627}\x{6628}\x{6629}' . + '\x{662A}\x{662B}\x{662D}\x{662E}\x{662F}\x{6630}\x{6631}\x{6632}\x{6633}' . + '\x{6634}\x{6635}\x{6636}\x{6639}\x{663A}\x{663C}\x{663D}\x{663E}\x{6640}' . + '\x{6641}\x{6642}\x{6643}\x{6644}\x{6645}\x{6646}\x{6647}\x{6649}\x{664A}' . + '\x{664B}\x{664C}\x{664E}\x{664F}\x{6650}\x{6651}\x{6652}\x{6653}\x{6654}' . + '\x{6655}\x{6656}\x{6657}\x{6658}\x{6659}\x{665A}\x{665B}\x{665C}\x{665D}' . + '\x{665E}\x{665F}\x{6661}\x{6662}\x{6664}\x{6665}\x{6666}\x{6668}\x{6669}' . + '\x{666A}\x{666B}\x{666C}\x{666D}\x{666E}\x{666F}\x{6670}\x{6671}\x{6672}' . + '\x{6673}\x{6674}\x{6675}\x{6676}\x{6677}\x{6678}\x{6679}\x{667A}\x{667B}' . + '\x{667C}\x{667D}\x{667E}\x{667F}\x{6680}\x{6681}\x{6682}\x{6683}\x{6684}' . + '\x{6685}\x{6686}\x{6687}\x{6688}\x{6689}\x{668A}\x{668B}\x{668C}\x{668D}' . + '\x{668E}\x{668F}\x{6690}\x{6691}\x{6693}\x{6694}\x{6695}\x{6696}\x{6697}' . + '\x{6698}\x{6699}\x{669A}\x{669B}\x{669D}\x{669F}\x{66A0}\x{66A1}\x{66A2}' . + '\x{66A3}\x{66A4}\x{66A5}\x{66A6}\x{66A7}\x{66A8}\x{66A9}\x{66AA}\x{66AB}' . + '\x{66AE}\x{66AF}\x{66B0}\x{66B1}\x{66B2}\x{66B3}\x{66B4}\x{66B5}\x{66B6}' . + '\x{66B7}\x{66B8}\x{66B9}\x{66BA}\x{66BB}\x{66BC}\x{66BD}\x{66BE}\x{66BF}' . + '\x{66C0}\x{66C1}\x{66C2}\x{66C3}\x{66C4}\x{66C5}\x{66C6}\x{66C7}\x{66C8}' . + '\x{66C9}\x{66CA}\x{66CB}\x{66CC}\x{66CD}\x{66CE}\x{66CF}\x{66D1}\x{66D2}' . + '\x{66D4}\x{66D5}\x{66D6}\x{66D8}\x{66D9}\x{66DA}\x{66DB}\x{66DC}\x{66DD}' . + '\x{66DE}\x{66E0}\x{66E1}\x{66E2}\x{66E3}\x{66E4}\x{66E5}\x{66E6}\x{66E7}' . + '\x{66E8}\x{66E9}\x{66EA}\x{66EB}\x{66EC}\x{66ED}\x{66EE}\x{66F0}\x{66F1}' . + '\x{66F2}\x{66F3}\x{66F4}\x{66F5}\x{66F6}\x{66F7}\x{66F8}\x{66F9}\x{66FA}' . + '\x{66FB}\x{66FC}\x{66FE}\x{66FF}\x{6700}\x{6701}\x{6703}\x{6704}\x{6705}' . + '\x{6706}\x{6708}\x{6709}\x{670A}\x{670B}\x{670C}\x{670D}\x{670E}\x{670F}' . + '\x{6710}\x{6711}\x{6712}\x{6713}\x{6714}\x{6715}\x{6716}\x{6717}\x{6718}' . + '\x{671A}\x{671B}\x{671C}\x{671D}\x{671E}\x{671F}\x{6720}\x{6721}\x{6722}' . + '\x{6723}\x{6725}\x{6726}\x{6727}\x{6728}\x{672A}\x{672B}\x{672C}\x{672D}' . + '\x{672E}\x{672F}\x{6730}\x{6731}\x{6732}\x{6733}\x{6734}\x{6735}\x{6736}' . + '\x{6737}\x{6738}\x{6739}\x{673A}\x{673B}\x{673C}\x{673D}\x{673E}\x{673F}' . + '\x{6740}\x{6741}\x{6742}\x{6743}\x{6744}\x{6745}\x{6746}\x{6747}\x{6748}' . + '\x{6749}\x{674A}\x{674B}\x{674C}\x{674D}\x{674E}\x{674F}\x{6750}\x{6751}' . + '\x{6752}\x{6753}\x{6754}\x{6755}\x{6756}\x{6757}\x{6758}\x{6759}\x{675A}' . + '\x{675B}\x{675C}\x{675D}\x{675E}\x{675F}\x{6760}\x{6761}\x{6762}\x{6763}' . + '\x{6764}\x{6765}\x{6766}\x{6768}\x{6769}\x{676A}\x{676B}\x{676C}\x{676D}' . + '\x{676E}\x{676F}\x{6770}\x{6771}\x{6772}\x{6773}\x{6774}\x{6775}\x{6776}' . + '\x{6777}\x{6778}\x{6779}\x{677A}\x{677B}\x{677C}\x{677D}\x{677E}\x{677F}' . + '\x{6780}\x{6781}\x{6782}\x{6783}\x{6784}\x{6785}\x{6786}\x{6787}\x{6789}' . + '\x{678A}\x{678B}\x{678C}\x{678D}\x{678E}\x{678F}\x{6790}\x{6791}\x{6792}' . + '\x{6793}\x{6794}\x{6795}\x{6797}\x{6798}\x{6799}\x{679A}\x{679B}\x{679C}' . + '\x{679D}\x{679E}\x{679F}\x{67A0}\x{67A1}\x{67A2}\x{67A3}\x{67A4}\x{67A5}' . + '\x{67A6}\x{67A7}\x{67A8}\x{67AA}\x{67AB}\x{67AC}\x{67AD}\x{67AE}\x{67AF}' . + '\x{67B0}\x{67B1}\x{67B2}\x{67B3}\x{67B4}\x{67B5}\x{67B6}\x{67B7}\x{67B8}' . + '\x{67B9}\x{67BA}\x{67BB}\x{67BC}\x{67BE}\x{67C0}\x{67C1}\x{67C2}\x{67C3}' . + '\x{67C4}\x{67C5}\x{67C6}\x{67C7}\x{67C8}\x{67C9}\x{67CA}\x{67CB}\x{67CC}' . + '\x{67CD}\x{67CE}\x{67CF}\x{67D0}\x{67D1}\x{67D2}\x{67D3}\x{67D4}\x{67D6}' . + '\x{67D8}\x{67D9}\x{67DA}\x{67DB}\x{67DC}\x{67DD}\x{67DE}\x{67DF}\x{67E0}' . + '\x{67E1}\x{67E2}\x{67E3}\x{67E4}\x{67E5}\x{67E6}\x{67E7}\x{67E8}\x{67E9}' . + '\x{67EA}\x{67EB}\x{67EC}\x{67ED}\x{67EE}\x{67EF}\x{67F0}\x{67F1}\x{67F2}' . + '\x{67F3}\x{67F4}\x{67F5}\x{67F6}\x{67F7}\x{67F8}\x{67FA}\x{67FB}\x{67FC}' . + '\x{67FD}\x{67FE}\x{67FF}\x{6800}\x{6802}\x{6803}\x{6804}\x{6805}\x{6806}' . + '\x{6807}\x{6808}\x{6809}\x{680A}\x{680B}\x{680C}\x{680D}\x{680E}\x{680F}' . + '\x{6810}\x{6811}\x{6812}\x{6813}\x{6814}\x{6816}\x{6817}\x{6818}\x{6819}' . + '\x{681A}\x{681B}\x{681C}\x{681D}\x{681F}\x{6820}\x{6821}\x{6822}\x{6823}' . + '\x{6824}\x{6825}\x{6826}\x{6828}\x{6829}\x{682A}\x{682B}\x{682C}\x{682D}' . + '\x{682E}\x{682F}\x{6831}\x{6832}\x{6833}\x{6834}\x{6835}\x{6836}\x{6837}' . + '\x{6838}\x{6839}\x{683A}\x{683B}\x{683C}\x{683D}\x{683E}\x{683F}\x{6840}' . + '\x{6841}\x{6842}\x{6843}\x{6844}\x{6845}\x{6846}\x{6847}\x{6848}\x{6849}' . + '\x{684A}\x{684B}\x{684C}\x{684D}\x{684E}\x{684F}\x{6850}\x{6851}\x{6852}' . + '\x{6853}\x{6854}\x{6855}\x{6856}\x{6857}\x{685B}\x{685D}\x{6860}\x{6861}' . + '\x{6862}\x{6863}\x{6864}\x{6865}\x{6866}\x{6867}\x{6868}\x{6869}\x{686A}' . + '\x{686B}\x{686C}\x{686D}\x{686E}\x{686F}\x{6870}\x{6871}\x{6872}\x{6873}' . + '\x{6874}\x{6875}\x{6876}\x{6877}\x{6878}\x{6879}\x{687B}\x{687C}\x{687D}' . + '\x{687E}\x{687F}\x{6880}\x{6881}\x{6882}\x{6883}\x{6884}\x{6885}\x{6886}' . + '\x{6887}\x{6888}\x{6889}\x{688A}\x{688B}\x{688C}\x{688D}\x{688E}\x{688F}' . + '\x{6890}\x{6891}\x{6892}\x{6893}\x{6894}\x{6896}\x{6897}\x{6898}\x{689A}' . + '\x{689B}\x{689C}\x{689D}\x{689E}\x{689F}\x{68A0}\x{68A1}\x{68A2}\x{68A3}' . + '\x{68A4}\x{68A6}\x{68A7}\x{68A8}\x{68A9}\x{68AA}\x{68AB}\x{68AC}\x{68AD}' . + '\x{68AE}\x{68AF}\x{68B0}\x{68B1}\x{68B2}\x{68B3}\x{68B4}\x{68B5}\x{68B6}' . + '\x{68B7}\x{68B9}\x{68BB}\x{68BC}\x{68BD}\x{68BE}\x{68BF}\x{68C0}\x{68C1}' . + '\x{68C2}\x{68C4}\x{68C6}\x{68C7}\x{68C8}\x{68C9}\x{68CA}\x{68CB}\x{68CC}' . + '\x{68CD}\x{68CE}\x{68CF}\x{68D0}\x{68D1}\x{68D2}\x{68D3}\x{68D4}\x{68D5}' . + '\x{68D6}\x{68D7}\x{68D8}\x{68DA}\x{68DB}\x{68DC}\x{68DD}\x{68DE}\x{68DF}' . + '\x{68E0}\x{68E1}\x{68E3}\x{68E4}\x{68E6}\x{68E7}\x{68E8}\x{68E9}\x{68EA}' . + '\x{68EB}\x{68EC}\x{68ED}\x{68EE}\x{68EF}\x{68F0}\x{68F1}\x{68F2}\x{68F3}' . + '\x{68F4}\x{68F5}\x{68F6}\x{68F7}\x{68F8}\x{68F9}\x{68FA}\x{68FB}\x{68FC}' . + '\x{68FD}\x{68FE}\x{68FF}\x{6901}\x{6902}\x{6903}\x{6904}\x{6905}\x{6906}' . + '\x{6907}\x{6908}\x{690A}\x{690B}\x{690C}\x{690D}\x{690E}\x{690F}\x{6910}' . + '\x{6911}\x{6912}\x{6913}\x{6914}\x{6915}\x{6916}\x{6917}\x{6918}\x{6919}' . + '\x{691A}\x{691B}\x{691C}\x{691D}\x{691E}\x{691F}\x{6920}\x{6921}\x{6922}' . + '\x{6923}\x{6924}\x{6925}\x{6926}\x{6927}\x{6928}\x{6929}\x{692A}\x{692B}' . + '\x{692C}\x{692D}\x{692E}\x{692F}\x{6930}\x{6931}\x{6932}\x{6933}\x{6934}' . + '\x{6935}\x{6936}\x{6937}\x{6938}\x{6939}\x{693A}\x{693B}\x{693C}\x{693D}' . + '\x{693F}\x{6940}\x{6941}\x{6942}\x{6943}\x{6944}\x{6945}\x{6946}\x{6947}' . + '\x{6948}\x{6949}\x{694A}\x{694B}\x{694C}\x{694E}\x{694F}\x{6950}\x{6951}' . + '\x{6952}\x{6953}\x{6954}\x{6955}\x{6956}\x{6957}\x{6958}\x{6959}\x{695A}' . + '\x{695B}\x{695C}\x{695D}\x{695E}\x{695F}\x{6960}\x{6961}\x{6962}\x{6963}' . + '\x{6964}\x{6965}\x{6966}\x{6967}\x{6968}\x{6969}\x{696A}\x{696B}\x{696C}' . + '\x{696D}\x{696E}\x{696F}\x{6970}\x{6971}\x{6972}\x{6973}\x{6974}\x{6975}' . + '\x{6976}\x{6977}\x{6978}\x{6979}\x{697A}\x{697B}\x{697C}\x{697D}\x{697E}' . + '\x{697F}\x{6980}\x{6981}\x{6982}\x{6983}\x{6984}\x{6985}\x{6986}\x{6987}' . + '\x{6988}\x{6989}\x{698A}\x{698B}\x{698C}\x{698D}\x{698E}\x{698F}\x{6990}' . + '\x{6991}\x{6992}\x{6993}\x{6994}\x{6995}\x{6996}\x{6997}\x{6998}\x{6999}' . + '\x{699A}\x{699B}\x{699C}\x{699D}\x{699E}\x{69A0}\x{69A1}\x{69A3}\x{69A4}' . + '\x{69A5}\x{69A6}\x{69A7}\x{69A8}\x{69A9}\x{69AA}\x{69AB}\x{69AC}\x{69AD}' . + '\x{69AE}\x{69AF}\x{69B0}\x{69B1}\x{69B2}\x{69B3}\x{69B4}\x{69B5}\x{69B6}' . + '\x{69B7}\x{69B8}\x{69B9}\x{69BA}\x{69BB}\x{69BC}\x{69BD}\x{69BE}\x{69BF}' . + '\x{69C1}\x{69C2}\x{69C3}\x{69C4}\x{69C5}\x{69C6}\x{69C7}\x{69C8}\x{69C9}' . + '\x{69CA}\x{69CB}\x{69CC}\x{69CD}\x{69CE}\x{69CF}\x{69D0}\x{69D3}\x{69D4}' . + '\x{69D8}\x{69D9}\x{69DA}\x{69DB}\x{69DC}\x{69DD}\x{69DE}\x{69DF}\x{69E0}' . + '\x{69E1}\x{69E2}\x{69E3}\x{69E4}\x{69E5}\x{69E6}\x{69E7}\x{69E8}\x{69E9}' . + '\x{69EA}\x{69EB}\x{69EC}\x{69ED}\x{69EE}\x{69EF}\x{69F0}\x{69F1}\x{69F2}' . + '\x{69F3}\x{69F4}\x{69F5}\x{69F6}\x{69F7}\x{69F8}\x{69FA}\x{69FB}\x{69FC}' . + '\x{69FD}\x{69FE}\x{69FF}\x{6A00}\x{6A01}\x{6A02}\x{6A04}\x{6A05}\x{6A06}' . + '\x{6A07}\x{6A08}\x{6A09}\x{6A0A}\x{6A0B}\x{6A0D}\x{6A0E}\x{6A0F}\x{6A10}' . + '\x{6A11}\x{6A12}\x{6A13}\x{6A14}\x{6A15}\x{6A16}\x{6A17}\x{6A18}\x{6A19}' . + '\x{6A1A}\x{6A1B}\x{6A1D}\x{6A1E}\x{6A1F}\x{6A20}\x{6A21}\x{6A22}\x{6A23}' . + '\x{6A25}\x{6A26}\x{6A27}\x{6A28}\x{6A29}\x{6A2A}\x{6A2B}\x{6A2C}\x{6A2D}' . + '\x{6A2E}\x{6A2F}\x{6A30}\x{6A31}\x{6A32}\x{6A33}\x{6A34}\x{6A35}\x{6A36}' . + '\x{6A38}\x{6A39}\x{6A3A}\x{6A3B}\x{6A3C}\x{6A3D}\x{6A3E}\x{6A3F}\x{6A40}' . + '\x{6A41}\x{6A42}\x{6A43}\x{6A44}\x{6A45}\x{6A46}\x{6A47}\x{6A48}\x{6A49}' . + '\x{6A4B}\x{6A4C}\x{6A4D}\x{6A4E}\x{6A4F}\x{6A50}\x{6A51}\x{6A52}\x{6A54}' . + '\x{6A55}\x{6A56}\x{6A57}\x{6A58}\x{6A59}\x{6A5A}\x{6A5B}\x{6A5D}\x{6A5E}' . + '\x{6A5F}\x{6A60}\x{6A61}\x{6A62}\x{6A63}\x{6A64}\x{6A65}\x{6A66}\x{6A67}' . + '\x{6A68}\x{6A69}\x{6A6A}\x{6A6B}\x{6A6C}\x{6A6D}\x{6A6F}\x{6A71}\x{6A72}' . + '\x{6A73}\x{6A74}\x{6A75}\x{6A76}\x{6A77}\x{6A78}\x{6A79}\x{6A7A}\x{6A7B}' . + '\x{6A7C}\x{6A7D}\x{6A7E}\x{6A7F}\x{6A80}\x{6A81}\x{6A82}\x{6A83}\x{6A84}' . + '\x{6A85}\x{6A87}\x{6A88}\x{6A89}\x{6A8B}\x{6A8C}\x{6A8D}\x{6A8E}\x{6A90}' . + '\x{6A91}\x{6A92}\x{6A93}\x{6A94}\x{6A95}\x{6A96}\x{6A97}\x{6A98}\x{6A9A}' . + '\x{6A9B}\x{6A9C}\x{6A9E}\x{6A9F}\x{6AA0}\x{6AA1}\x{6AA2}\x{6AA3}\x{6AA4}' . + '\x{6AA5}\x{6AA6}\x{6AA7}\x{6AA8}\x{6AA9}\x{6AAB}\x{6AAC}\x{6AAD}\x{6AAE}' . + '\x{6AAF}\x{6AB0}\x{6AB2}\x{6AB3}\x{6AB4}\x{6AB5}\x{6AB6}\x{6AB7}\x{6AB8}' . + '\x{6AB9}\x{6ABA}\x{6ABB}\x{6ABC}\x{6ABD}\x{6ABF}\x{6AC1}\x{6AC2}\x{6AC3}' . + '\x{6AC5}\x{6AC6}\x{6AC7}\x{6ACA}\x{6ACB}\x{6ACC}\x{6ACD}\x{6ACE}\x{6ACF}' . + '\x{6AD0}\x{6AD1}\x{6AD2}\x{6AD3}\x{6AD4}\x{6AD5}\x{6AD6}\x{6AD7}\x{6AD9}' . + '\x{6ADA}\x{6ADB}\x{6ADC}\x{6ADD}\x{6ADE}\x{6ADF}\x{6AE0}\x{6AE1}\x{6AE2}' . + '\x{6AE3}\x{6AE4}\x{6AE5}\x{6AE6}\x{6AE7}\x{6AE8}\x{6AEA}\x{6AEB}\x{6AEC}' . + '\x{6AED}\x{6AEE}\x{6AEF}\x{6AF0}\x{6AF1}\x{6AF2}\x{6AF3}\x{6AF4}\x{6AF5}' . + '\x{6AF6}\x{6AF7}\x{6AF8}\x{6AF9}\x{6AFA}\x{6AFB}\x{6AFC}\x{6AFD}\x{6AFE}' . + '\x{6AFF}\x{6B00}\x{6B01}\x{6B02}\x{6B03}\x{6B04}\x{6B05}\x{6B06}\x{6B07}' . + '\x{6B08}\x{6B09}\x{6B0A}\x{6B0B}\x{6B0C}\x{6B0D}\x{6B0F}\x{6B10}\x{6B11}' . + '\x{6B12}\x{6B13}\x{6B14}\x{6B15}\x{6B16}\x{6B17}\x{6B18}\x{6B19}\x{6B1A}' . + '\x{6B1C}\x{6B1D}\x{6B1E}\x{6B1F}\x{6B20}\x{6B21}\x{6B22}\x{6B23}\x{6B24}' . + '\x{6B25}\x{6B26}\x{6B27}\x{6B28}\x{6B29}\x{6B2A}\x{6B2B}\x{6B2C}\x{6B2D}' . + '\x{6B2F}\x{6B30}\x{6B31}\x{6B32}\x{6B33}\x{6B34}\x{6B36}\x{6B37}\x{6B38}' . + '\x{6B39}\x{6B3A}\x{6B3B}\x{6B3C}\x{6B3D}\x{6B3E}\x{6B3F}\x{6B41}\x{6B42}' . + '\x{6B43}\x{6B44}\x{6B45}\x{6B46}\x{6B47}\x{6B48}\x{6B49}\x{6B4A}\x{6B4B}' . + '\x{6B4C}\x{6B4D}\x{6B4E}\x{6B4F}\x{6B50}\x{6B51}\x{6B52}\x{6B53}\x{6B54}' . + '\x{6B55}\x{6B56}\x{6B59}\x{6B5A}\x{6B5B}\x{6B5C}\x{6B5E}\x{6B5F}\x{6B60}' . + '\x{6B61}\x{6B62}\x{6B63}\x{6B64}\x{6B65}\x{6B66}\x{6B67}\x{6B69}\x{6B6A}' . + '\x{6B6B}\x{6B6D}\x{6B6F}\x{6B70}\x{6B72}\x{6B73}\x{6B74}\x{6B76}\x{6B77}' . + '\x{6B78}\x{6B79}\x{6B7A}\x{6B7B}\x{6B7C}\x{6B7E}\x{6B7F}\x{6B80}\x{6B81}' . + '\x{6B82}\x{6B83}\x{6B84}\x{6B85}\x{6B86}\x{6B87}\x{6B88}\x{6B89}\x{6B8A}' . + '\x{6B8B}\x{6B8C}\x{6B8D}\x{6B8E}\x{6B8F}\x{6B90}\x{6B91}\x{6B92}\x{6B93}' . + '\x{6B94}\x{6B95}\x{6B96}\x{6B97}\x{6B98}\x{6B99}\x{6B9A}\x{6B9B}\x{6B9C}' . + '\x{6B9D}\x{6B9E}\x{6B9F}\x{6BA0}\x{6BA1}\x{6BA2}\x{6BA3}\x{6BA4}\x{6BA5}' . + '\x{6BA6}\x{6BA7}\x{6BA8}\x{6BA9}\x{6BAA}\x{6BAB}\x{6BAC}\x{6BAD}\x{6BAE}' . + '\x{6BAF}\x{6BB0}\x{6BB2}\x{6BB3}\x{6BB4}\x{6BB5}\x{6BB6}\x{6BB7}\x{6BB9}' . + '\x{6BBA}\x{6BBB}\x{6BBC}\x{6BBD}\x{6BBE}\x{6BBF}\x{6BC0}\x{6BC1}\x{6BC2}' . + '\x{6BC3}\x{6BC4}\x{6BC5}\x{6BC6}\x{6BC7}\x{6BC8}\x{6BC9}\x{6BCA}\x{6BCB}' . + '\x{6BCC}\x{6BCD}\x{6BCE}\x{6BCF}\x{6BD0}\x{6BD1}\x{6BD2}\x{6BD3}\x{6BD4}' . + '\x{6BD5}\x{6BD6}\x{6BD7}\x{6BD8}\x{6BD9}\x{6BDA}\x{6BDB}\x{6BDC}\x{6BDD}' . + '\x{6BDE}\x{6BDF}\x{6BE0}\x{6BE1}\x{6BE2}\x{6BE3}\x{6BE4}\x{6BE5}\x{6BE6}' . + '\x{6BE7}\x{6BE8}\x{6BEA}\x{6BEB}\x{6BEC}\x{6BED}\x{6BEE}\x{6BEF}\x{6BF0}' . + '\x{6BF2}\x{6BF3}\x{6BF5}\x{6BF6}\x{6BF7}\x{6BF8}\x{6BF9}\x{6BFB}\x{6BFC}' . + '\x{6BFD}\x{6BFE}\x{6BFF}\x{6C00}\x{6C01}\x{6C02}\x{6C03}\x{6C04}\x{6C05}' . + '\x{6C06}\x{6C07}\x{6C08}\x{6C09}\x{6C0B}\x{6C0C}\x{6C0D}\x{6C0E}\x{6C0F}' . + '\x{6C10}\x{6C11}\x{6C12}\x{6C13}\x{6C14}\x{6C15}\x{6C16}\x{6C18}\x{6C19}' . + '\x{6C1A}\x{6C1B}\x{6C1D}\x{6C1E}\x{6C1F}\x{6C20}\x{6C21}\x{6C22}\x{6C23}' . + '\x{6C24}\x{6C25}\x{6C26}\x{6C27}\x{6C28}\x{6C29}\x{6C2A}\x{6C2B}\x{6C2C}' . + '\x{6C2E}\x{6C2F}\x{6C30}\x{6C31}\x{6C32}\x{6C33}\x{6C34}\x{6C35}\x{6C36}' . + '\x{6C37}\x{6C38}\x{6C3A}\x{6C3B}\x{6C3D}\x{6C3E}\x{6C3F}\x{6C40}\x{6C41}' . + '\x{6C42}\x{6C43}\x{6C44}\x{6C46}\x{6C47}\x{6C48}\x{6C49}\x{6C4A}\x{6C4B}' . + '\x{6C4C}\x{6C4D}\x{6C4E}\x{6C4F}\x{6C50}\x{6C51}\x{6C52}\x{6C53}\x{6C54}' . + '\x{6C55}\x{6C56}\x{6C57}\x{6C58}\x{6C59}\x{6C5A}\x{6C5B}\x{6C5C}\x{6C5D}' . + '\x{6C5E}\x{6C5F}\x{6C60}\x{6C61}\x{6C62}\x{6C63}\x{6C64}\x{6C65}\x{6C66}' . + '\x{6C67}\x{6C68}\x{6C69}\x{6C6A}\x{6C6B}\x{6C6D}\x{6C6F}\x{6C70}\x{6C71}' . + '\x{6C72}\x{6C73}\x{6C74}\x{6C75}\x{6C76}\x{6C77}\x{6C78}\x{6C79}\x{6C7A}' . + '\x{6C7B}\x{6C7C}\x{6C7D}\x{6C7E}\x{6C7F}\x{6C80}\x{6C81}\x{6C82}\x{6C83}' . + '\x{6C84}\x{6C85}\x{6C86}\x{6C87}\x{6C88}\x{6C89}\x{6C8A}\x{6C8B}\x{6C8C}' . + '\x{6C8D}\x{6C8E}\x{6C8F}\x{6C90}\x{6C91}\x{6C92}\x{6C93}\x{6C94}\x{6C95}' . + '\x{6C96}\x{6C97}\x{6C98}\x{6C99}\x{6C9A}\x{6C9B}\x{6C9C}\x{6C9D}\x{6C9E}' . + '\x{6C9F}\x{6CA1}\x{6CA2}\x{6CA3}\x{6CA4}\x{6CA5}\x{6CA6}\x{6CA7}\x{6CA8}' . + '\x{6CA9}\x{6CAA}\x{6CAB}\x{6CAC}\x{6CAD}\x{6CAE}\x{6CAF}\x{6CB0}\x{6CB1}' . + '\x{6CB2}\x{6CB3}\x{6CB4}\x{6CB5}\x{6CB6}\x{6CB7}\x{6CB8}\x{6CB9}\x{6CBA}' . + '\x{6CBB}\x{6CBC}\x{6CBD}\x{6CBE}\x{6CBF}\x{6CC0}\x{6CC1}\x{6CC2}\x{6CC3}' . + '\x{6CC4}\x{6CC5}\x{6CC6}\x{6CC7}\x{6CC8}\x{6CC9}\x{6CCA}\x{6CCB}\x{6CCC}' . + '\x{6CCD}\x{6CCE}\x{6CCF}\x{6CD0}\x{6CD1}\x{6CD2}\x{6CD3}\x{6CD4}\x{6CD5}' . + '\x{6CD6}\x{6CD7}\x{6CD9}\x{6CDA}\x{6CDB}\x{6CDC}\x{6CDD}\x{6CDE}\x{6CDF}' . + '\x{6CE0}\x{6CE1}\x{6CE2}\x{6CE3}\x{6CE4}\x{6CE5}\x{6CE6}\x{6CE7}\x{6CE8}' . + '\x{6CE9}\x{6CEA}\x{6CEB}\x{6CEC}\x{6CED}\x{6CEE}\x{6CEF}\x{6CF0}\x{6CF1}' . + '\x{6CF2}\x{6CF3}\x{6CF5}\x{6CF6}\x{6CF7}\x{6CF8}\x{6CF9}\x{6CFA}\x{6CFB}' . + '\x{6CFC}\x{6CFD}\x{6CFE}\x{6CFF}\x{6D00}\x{6D01}\x{6D03}\x{6D04}\x{6D05}' . + '\x{6D06}\x{6D07}\x{6D08}\x{6D09}\x{6D0A}\x{6D0B}\x{6D0C}\x{6D0D}\x{6D0E}' . + '\x{6D0F}\x{6D10}\x{6D11}\x{6D12}\x{6D13}\x{6D14}\x{6D15}\x{6D16}\x{6D17}' . + '\x{6D18}\x{6D19}\x{6D1A}\x{6D1B}\x{6D1D}\x{6D1E}\x{6D1F}\x{6D20}\x{6D21}' . + '\x{6D22}\x{6D23}\x{6D25}\x{6D26}\x{6D27}\x{6D28}\x{6D29}\x{6D2A}\x{6D2B}' . + '\x{6D2C}\x{6D2D}\x{6D2E}\x{6D2F}\x{6D30}\x{6D31}\x{6D32}\x{6D33}\x{6D34}' . + '\x{6D35}\x{6D36}\x{6D37}\x{6D38}\x{6D39}\x{6D3A}\x{6D3B}\x{6D3C}\x{6D3D}' . + '\x{6D3E}\x{6D3F}\x{6D40}\x{6D41}\x{6D42}\x{6D43}\x{6D44}\x{6D45}\x{6D46}' . + '\x{6D47}\x{6D48}\x{6D49}\x{6D4A}\x{6D4B}\x{6D4C}\x{6D4D}\x{6D4E}\x{6D4F}' . + '\x{6D50}\x{6D51}\x{6D52}\x{6D53}\x{6D54}\x{6D55}\x{6D56}\x{6D57}\x{6D58}' . + '\x{6D59}\x{6D5A}\x{6D5B}\x{6D5C}\x{6D5D}\x{6D5E}\x{6D5F}\x{6D60}\x{6D61}' . + '\x{6D62}\x{6D63}\x{6D64}\x{6D65}\x{6D66}\x{6D67}\x{6D68}\x{6D69}\x{6D6A}' . + '\x{6D6B}\x{6D6C}\x{6D6D}\x{6D6E}\x{6D6F}\x{6D70}\x{6D72}\x{6D73}\x{6D74}' . + '\x{6D75}\x{6D76}\x{6D77}\x{6D78}\x{6D79}\x{6D7A}\x{6D7B}\x{6D7C}\x{6D7D}' . + '\x{6D7E}\x{6D7F}\x{6D80}\x{6D82}\x{6D83}\x{6D84}\x{6D85}\x{6D86}\x{6D87}' . + '\x{6D88}\x{6D89}\x{6D8A}\x{6D8B}\x{6D8C}\x{6D8D}\x{6D8E}\x{6D8F}\x{6D90}' . + '\x{6D91}\x{6D92}\x{6D93}\x{6D94}\x{6D95}\x{6D97}\x{6D98}\x{6D99}\x{6D9A}' . + '\x{6D9B}\x{6D9D}\x{6D9E}\x{6D9F}\x{6DA0}\x{6DA1}\x{6DA2}\x{6DA3}\x{6DA4}' . + '\x{6DA5}\x{6DA6}\x{6DA7}\x{6DA8}\x{6DA9}\x{6DAA}\x{6DAB}\x{6DAC}\x{6DAD}' . + '\x{6DAE}\x{6DAF}\x{6DB2}\x{6DB3}\x{6DB4}\x{6DB5}\x{6DB7}\x{6DB8}\x{6DB9}' . + '\x{6DBA}\x{6DBB}\x{6DBC}\x{6DBD}\x{6DBE}\x{6DBF}\x{6DC0}\x{6DC1}\x{6DC2}' . + '\x{6DC3}\x{6DC4}\x{6DC5}\x{6DC6}\x{6DC7}\x{6DC8}\x{6DC9}\x{6DCA}\x{6DCB}' . + '\x{6DCC}\x{6DCD}\x{6DCE}\x{6DCF}\x{6DD0}\x{6DD1}\x{6DD2}\x{6DD3}\x{6DD4}' . + '\x{6DD5}\x{6DD6}\x{6DD7}\x{6DD8}\x{6DD9}\x{6DDA}\x{6DDB}\x{6DDC}\x{6DDD}' . + '\x{6DDE}\x{6DDF}\x{6DE0}\x{6DE1}\x{6DE2}\x{6DE3}\x{6DE4}\x{6DE5}\x{6DE6}' . + '\x{6DE7}\x{6DE8}\x{6DE9}\x{6DEA}\x{6DEB}\x{6DEC}\x{6DED}\x{6DEE}\x{6DEF}' . + '\x{6DF0}\x{6DF1}\x{6DF2}\x{6DF3}\x{6DF4}\x{6DF5}\x{6DF6}\x{6DF7}\x{6DF8}' . + '\x{6DF9}\x{6DFA}\x{6DFB}\x{6DFC}\x{6DFD}\x{6E00}\x{6E03}\x{6E04}\x{6E05}' . + '\x{6E07}\x{6E08}\x{6E09}\x{6E0A}\x{6E0B}\x{6E0C}\x{6E0D}\x{6E0E}\x{6E0F}' . + '\x{6E10}\x{6E11}\x{6E14}\x{6E15}\x{6E16}\x{6E17}\x{6E19}\x{6E1A}\x{6E1B}' . + '\x{6E1C}\x{6E1D}\x{6E1E}\x{6E1F}\x{6E20}\x{6E21}\x{6E22}\x{6E23}\x{6E24}' . + '\x{6E25}\x{6E26}\x{6E27}\x{6E28}\x{6E29}\x{6E2B}\x{6E2C}\x{6E2D}\x{6E2E}' . + '\x{6E2F}\x{6E30}\x{6E31}\x{6E32}\x{6E33}\x{6E34}\x{6E35}\x{6E36}\x{6E37}' . + '\x{6E38}\x{6E39}\x{6E3A}\x{6E3B}\x{6E3C}\x{6E3D}\x{6E3E}\x{6E3F}\x{6E40}' . + '\x{6E41}\x{6E42}\x{6E43}\x{6E44}\x{6E45}\x{6E46}\x{6E47}\x{6E48}\x{6E49}' . + '\x{6E4A}\x{6E4B}\x{6E4D}\x{6E4E}\x{6E4F}\x{6E50}\x{6E51}\x{6E52}\x{6E53}' . + '\x{6E54}\x{6E55}\x{6E56}\x{6E57}\x{6E58}\x{6E59}\x{6E5A}\x{6E5B}\x{6E5C}' . + '\x{6E5D}\x{6E5E}\x{6E5F}\x{6E60}\x{6E61}\x{6E62}\x{6E63}\x{6E64}\x{6E65}' . + '\x{6E66}\x{6E67}\x{6E68}\x{6E69}\x{6E6A}\x{6E6B}\x{6E6D}\x{6E6E}\x{6E6F}' . + '\x{6E70}\x{6E71}\x{6E72}\x{6E73}\x{6E74}\x{6E75}\x{6E77}\x{6E78}\x{6E79}' . + '\x{6E7E}\x{6E7F}\x{6E80}\x{6E81}\x{6E82}\x{6E83}\x{6E84}\x{6E85}\x{6E86}' . + '\x{6E87}\x{6E88}\x{6E89}\x{6E8A}\x{6E8D}\x{6E8E}\x{6E8F}\x{6E90}\x{6E91}' . + '\x{6E92}\x{6E93}\x{6E94}\x{6E96}\x{6E97}\x{6E98}\x{6E99}\x{6E9A}\x{6E9B}' . + '\x{6E9C}\x{6E9D}\x{6E9E}\x{6E9F}\x{6EA0}\x{6EA1}\x{6EA2}\x{6EA3}\x{6EA4}' . + '\x{6EA5}\x{6EA6}\x{6EA7}\x{6EA8}\x{6EA9}\x{6EAA}\x{6EAB}\x{6EAC}\x{6EAD}' . + '\x{6EAE}\x{6EAF}\x{6EB0}\x{6EB1}\x{6EB2}\x{6EB3}\x{6EB4}\x{6EB5}\x{6EB6}' . + '\x{6EB7}\x{6EB8}\x{6EB9}\x{6EBA}\x{6EBB}\x{6EBC}\x{6EBD}\x{6EBE}\x{6EBF}' . + '\x{6EC0}\x{6EC1}\x{6EC2}\x{6EC3}\x{6EC4}\x{6EC5}\x{6EC6}\x{6EC7}\x{6EC8}' . + '\x{6EC9}\x{6ECA}\x{6ECB}\x{6ECC}\x{6ECD}\x{6ECE}\x{6ECF}\x{6ED0}\x{6ED1}' . + '\x{6ED2}\x{6ED3}\x{6ED4}\x{6ED5}\x{6ED6}\x{6ED7}\x{6ED8}\x{6ED9}\x{6EDA}' . + '\x{6EDC}\x{6EDE}\x{6EDF}\x{6EE0}\x{6EE1}\x{6EE2}\x{6EE4}\x{6EE5}\x{6EE6}' . + '\x{6EE7}\x{6EE8}\x{6EE9}\x{6EEA}\x{6EEB}\x{6EEC}\x{6EED}\x{6EEE}\x{6EEF}' . + '\x{6EF0}\x{6EF1}\x{6EF2}\x{6EF3}\x{6EF4}\x{6EF5}\x{6EF6}\x{6EF7}\x{6EF8}' . + '\x{6EF9}\x{6EFA}\x{6EFB}\x{6EFC}\x{6EFD}\x{6EFE}\x{6EFF}\x{6F00}\x{6F01}' . + '\x{6F02}\x{6F03}\x{6F05}\x{6F06}\x{6F07}\x{6F08}\x{6F09}\x{6F0A}\x{6F0C}' . + '\x{6F0D}\x{6F0E}\x{6F0F}\x{6F10}\x{6F11}\x{6F12}\x{6F13}\x{6F14}\x{6F15}' . + '\x{6F16}\x{6F17}\x{6F18}\x{6F19}\x{6F1A}\x{6F1B}\x{6F1C}\x{6F1D}\x{6F1E}' . + '\x{6F1F}\x{6F20}\x{6F21}\x{6F22}\x{6F23}\x{6F24}\x{6F25}\x{6F26}\x{6F27}' . + '\x{6F28}\x{6F29}\x{6F2A}\x{6F2B}\x{6F2C}\x{6F2D}\x{6F2E}\x{6F2F}\x{6F30}' . + '\x{6F31}\x{6F32}\x{6F33}\x{6F34}\x{6F35}\x{6F36}\x{6F37}\x{6F38}\x{6F39}' . + '\x{6F3A}\x{6F3B}\x{6F3C}\x{6F3D}\x{6F3E}\x{6F3F}\x{6F40}\x{6F41}\x{6F43}' . + '\x{6F44}\x{6F45}\x{6F46}\x{6F47}\x{6F49}\x{6F4B}\x{6F4C}\x{6F4D}\x{6F4E}' . + '\x{6F4F}\x{6F50}\x{6F51}\x{6F52}\x{6F53}\x{6F54}\x{6F55}\x{6F56}\x{6F57}' . + '\x{6F58}\x{6F59}\x{6F5A}\x{6F5B}\x{6F5C}\x{6F5D}\x{6F5E}\x{6F5F}\x{6F60}' . + '\x{6F61}\x{6F62}\x{6F63}\x{6F64}\x{6F65}\x{6F66}\x{6F67}\x{6F68}\x{6F69}' . + '\x{6F6A}\x{6F6B}\x{6F6C}\x{6F6D}\x{6F6E}\x{6F6F}\x{6F70}\x{6F71}\x{6F72}' . + '\x{6F73}\x{6F74}\x{6F75}\x{6F76}\x{6F77}\x{6F78}\x{6F7A}\x{6F7B}\x{6F7C}' . + '\x{6F7D}\x{6F7E}\x{6F7F}\x{6F80}\x{6F81}\x{6F82}\x{6F83}\x{6F84}\x{6F85}' . + '\x{6F86}\x{6F87}\x{6F88}\x{6F89}\x{6F8A}\x{6F8B}\x{6F8C}\x{6F8D}\x{6F8E}' . + '\x{6F8F}\x{6F90}\x{6F91}\x{6F92}\x{6F93}\x{6F94}\x{6F95}\x{6F96}\x{6F97}' . + '\x{6F99}\x{6F9B}\x{6F9C}\x{6F9D}\x{6F9E}\x{6FA0}\x{6FA1}\x{6FA2}\x{6FA3}' . + '\x{6FA4}\x{6FA5}\x{6FA6}\x{6FA7}\x{6FA8}\x{6FA9}\x{6FAA}\x{6FAB}\x{6FAC}' . + '\x{6FAD}\x{6FAE}\x{6FAF}\x{6FB0}\x{6FB1}\x{6FB2}\x{6FB3}\x{6FB4}\x{6FB5}' . + '\x{6FB6}\x{6FB8}\x{6FB9}\x{6FBA}\x{6FBB}\x{6FBC}\x{6FBD}\x{6FBE}\x{6FBF}' . + '\x{6FC0}\x{6FC1}\x{6FC2}\x{6FC3}\x{6FC4}\x{6FC6}\x{6FC7}\x{6FC8}\x{6FC9}' . + '\x{6FCA}\x{6FCB}\x{6FCC}\x{6FCD}\x{6FCE}\x{6FCF}\x{6FD1}\x{6FD2}\x{6FD4}' . + '\x{6FD5}\x{6FD6}\x{6FD7}\x{6FD8}\x{6FD9}\x{6FDA}\x{6FDB}\x{6FDC}\x{6FDD}' . + '\x{6FDE}\x{6FDF}\x{6FE0}\x{6FE1}\x{6FE2}\x{6FE3}\x{6FE4}\x{6FE5}\x{6FE6}' . + '\x{6FE7}\x{6FE8}\x{6FE9}\x{6FEA}\x{6FEB}\x{6FEC}\x{6FED}\x{6FEE}\x{6FEF}' . + '\x{6FF0}\x{6FF1}\x{6FF2}\x{6FF3}\x{6FF4}\x{6FF6}\x{6FF7}\x{6FF8}\x{6FF9}' . + '\x{6FFA}\x{6FFB}\x{6FFC}\x{6FFE}\x{6FFF}\x{7000}\x{7001}\x{7002}\x{7003}' . + '\x{7004}\x{7005}\x{7006}\x{7007}\x{7008}\x{7009}\x{700A}\x{700B}\x{700C}' . + '\x{700D}\x{700E}\x{700F}\x{7011}\x{7012}\x{7014}\x{7015}\x{7016}\x{7017}' . + '\x{7018}\x{7019}\x{701A}\x{701B}\x{701C}\x{701D}\x{701F}\x{7020}\x{7021}' . + '\x{7022}\x{7023}\x{7024}\x{7025}\x{7026}\x{7027}\x{7028}\x{7029}\x{702A}' . + '\x{702B}\x{702C}\x{702D}\x{702E}\x{702F}\x{7030}\x{7031}\x{7032}\x{7033}' . + '\x{7034}\x{7035}\x{7036}\x{7037}\x{7038}\x{7039}\x{703A}\x{703B}\x{703C}' . + '\x{703D}\x{703E}\x{703F}\x{7040}\x{7041}\x{7042}\x{7043}\x{7044}\x{7045}' . + '\x{7046}\x{7048}\x{7049}\x{704A}\x{704C}\x{704D}\x{704F}\x{7050}\x{7051}' . + '\x{7052}\x{7053}\x{7054}\x{7055}\x{7056}\x{7057}\x{7058}\x{7059}\x{705A}' . + '\x{705B}\x{705C}\x{705D}\x{705E}\x{705F}\x{7060}\x{7061}\x{7062}\x{7063}' . + '\x{7064}\x{7065}\x{7066}\x{7067}\x{7068}\x{7069}\x{706A}\x{706B}\x{706C}' . + '\x{706D}\x{706E}\x{706F}\x{7070}\x{7071}\x{7074}\x{7075}\x{7076}\x{7077}' . + '\x{7078}\x{7079}\x{707A}\x{707C}\x{707D}\x{707E}\x{707F}\x{7080}\x{7082}' . + '\x{7083}\x{7084}\x{7085}\x{7086}\x{7087}\x{7088}\x{7089}\x{708A}\x{708B}' . + '\x{708C}\x{708E}\x{708F}\x{7090}\x{7091}\x{7092}\x{7093}\x{7094}\x{7095}' . + '\x{7096}\x{7098}\x{7099}\x{709A}\x{709C}\x{709D}\x{709E}\x{709F}\x{70A0}' . + '\x{70A1}\x{70A2}\x{70A3}\x{70A4}\x{70A5}\x{70A6}\x{70A7}\x{70A8}\x{70A9}' . + '\x{70AB}\x{70AC}\x{70AD}\x{70AE}\x{70AF}\x{70B0}\x{70B1}\x{70B3}\x{70B4}' . + '\x{70B5}\x{70B7}\x{70B8}\x{70B9}\x{70BA}\x{70BB}\x{70BC}\x{70BD}\x{70BE}' . + '\x{70BF}\x{70C0}\x{70C1}\x{70C2}\x{70C3}\x{70C4}\x{70C5}\x{70C6}\x{70C7}' . + '\x{70C8}\x{70C9}\x{70CA}\x{70CB}\x{70CC}\x{70CD}\x{70CE}\x{70CF}\x{70D0}' . + '\x{70D1}\x{70D2}\x{70D3}\x{70D4}\x{70D6}\x{70D7}\x{70D8}\x{70D9}\x{70DA}' . + '\x{70DB}\x{70DC}\x{70DD}\x{70DE}\x{70DF}\x{70E0}\x{70E1}\x{70E2}\x{70E3}' . + '\x{70E4}\x{70E5}\x{70E6}\x{70E7}\x{70E8}\x{70E9}\x{70EA}\x{70EB}\x{70EC}' . + '\x{70ED}\x{70EE}\x{70EF}\x{70F0}\x{70F1}\x{70F2}\x{70F3}\x{70F4}\x{70F5}' . + '\x{70F6}\x{70F7}\x{70F8}\x{70F9}\x{70FA}\x{70FB}\x{70FC}\x{70FD}\x{70FF}' . + '\x{7100}\x{7101}\x{7102}\x{7103}\x{7104}\x{7105}\x{7106}\x{7107}\x{7109}' . + '\x{710A}\x{710B}\x{710C}\x{710D}\x{710E}\x{710F}\x{7110}\x{7111}\x{7112}' . + '\x{7113}\x{7115}\x{7116}\x{7117}\x{7118}\x{7119}\x{711A}\x{711B}\x{711C}' . + '\x{711D}\x{711E}\x{711F}\x{7120}\x{7121}\x{7122}\x{7123}\x{7125}\x{7126}' . + '\x{7127}\x{7128}\x{7129}\x{712A}\x{712B}\x{712C}\x{712D}\x{712E}\x{712F}' . + '\x{7130}\x{7131}\x{7132}\x{7135}\x{7136}\x{7137}\x{7138}\x{7139}\x{713A}' . + '\x{713B}\x{713D}\x{713E}\x{713F}\x{7140}\x{7141}\x{7142}\x{7143}\x{7144}' . + '\x{7145}\x{7146}\x{7147}\x{7148}\x{7149}\x{714A}\x{714B}\x{714C}\x{714D}' . + '\x{714E}\x{714F}\x{7150}\x{7151}\x{7152}\x{7153}\x{7154}\x{7156}\x{7158}' . + '\x{7159}\x{715A}\x{715B}\x{715C}\x{715D}\x{715E}\x{715F}\x{7160}\x{7161}' . + '\x{7162}\x{7163}\x{7164}\x{7165}\x{7166}\x{7167}\x{7168}\x{7169}\x{716A}' . + '\x{716C}\x{716E}\x{716F}\x{7170}\x{7171}\x{7172}\x{7173}\x{7174}\x{7175}' . + '\x{7176}\x{7177}\x{7178}\x{7179}\x{717A}\x{717B}\x{717C}\x{717D}\x{717E}' . + '\x{717F}\x{7180}\x{7181}\x{7182}\x{7183}\x{7184}\x{7185}\x{7186}\x{7187}' . + '\x{7188}\x{7189}\x{718A}\x{718B}\x{718C}\x{718E}\x{718F}\x{7190}\x{7191}' . + '\x{7192}\x{7193}\x{7194}\x{7195}\x{7197}\x{7198}\x{7199}\x{719A}\x{719B}' . + '\x{719C}\x{719D}\x{719E}\x{719F}\x{71A0}\x{71A1}\x{71A2}\x{71A3}\x{71A4}' . + '\x{71A5}\x{71A7}\x{71A8}\x{71A9}\x{71AA}\x{71AC}\x{71AD}\x{71AE}\x{71AF}' . + '\x{71B0}\x{71B1}\x{71B2}\x{71B3}\x{71B4}\x{71B5}\x{71B7}\x{71B8}\x{71B9}' . + '\x{71BA}\x{71BB}\x{71BC}\x{71BD}\x{71BE}\x{71BF}\x{71C0}\x{71C1}\x{71C2}' . + '\x{71C3}\x{71C4}\x{71C5}\x{71C6}\x{71C7}\x{71C8}\x{71C9}\x{71CA}\x{71CB}' . + '\x{71CD}\x{71CE}\x{71CF}\x{71D0}\x{71D1}\x{71D2}\x{71D4}\x{71D5}\x{71D6}' . + '\x{71D7}\x{71D8}\x{71D9}\x{71DA}\x{71DB}\x{71DC}\x{71DD}\x{71DE}\x{71DF}' . + '\x{71E0}\x{71E1}\x{71E2}\x{71E3}\x{71E4}\x{71E5}\x{71E6}\x{71E7}\x{71E8}' . + '\x{71E9}\x{71EA}\x{71EB}\x{71EC}\x{71ED}\x{71EE}\x{71EF}\x{71F0}\x{71F1}' . + '\x{71F2}\x{71F4}\x{71F5}\x{71F6}\x{71F7}\x{71F8}\x{71F9}\x{71FB}\x{71FC}' . + '\x{71FD}\x{71FE}\x{71FF}\x{7201}\x{7202}\x{7203}\x{7204}\x{7205}\x{7206}' . + '\x{7207}\x{7208}\x{7209}\x{720A}\x{720C}\x{720D}\x{720E}\x{720F}\x{7210}' . + '\x{7212}\x{7213}\x{7214}\x{7216}\x{7218}\x{7219}\x{721A}\x{721B}\x{721C}' . + '\x{721D}\x{721E}\x{721F}\x{7221}\x{7222}\x{7223}\x{7226}\x{7227}\x{7228}' . + '\x{7229}\x{722A}\x{722B}\x{722C}\x{722D}\x{722E}\x{7230}\x{7231}\x{7232}' . + '\x{7233}\x{7235}\x{7236}\x{7237}\x{7238}\x{7239}\x{723A}\x{723B}\x{723C}' . + '\x{723D}\x{723E}\x{723F}\x{7240}\x{7241}\x{7242}\x{7243}\x{7244}\x{7246}' . + '\x{7247}\x{7248}\x{7249}\x{724A}\x{724B}\x{724C}\x{724D}\x{724F}\x{7251}' . + '\x{7252}\x{7253}\x{7254}\x{7256}\x{7257}\x{7258}\x{7259}\x{725A}\x{725B}' . + '\x{725C}\x{725D}\x{725E}\x{725F}\x{7260}\x{7261}\x{7262}\x{7263}\x{7264}' . + '\x{7265}\x{7266}\x{7267}\x{7268}\x{7269}\x{726A}\x{726B}\x{726C}\x{726D}' . + '\x{726E}\x{726F}\x{7270}\x{7271}\x{7272}\x{7273}\x{7274}\x{7275}\x{7276}' . + '\x{7277}\x{7278}\x{7279}\x{727A}\x{727B}\x{727C}\x{727D}\x{727E}\x{727F}' . + '\x{7280}\x{7281}\x{7282}\x{7283}\x{7284}\x{7285}\x{7286}\x{7287}\x{7288}' . + '\x{7289}\x{728A}\x{728B}\x{728C}\x{728D}\x{728E}\x{728F}\x{7290}\x{7291}' . + '\x{7292}\x{7293}\x{7294}\x{7295}\x{7296}\x{7297}\x{7298}\x{7299}\x{729A}' . + '\x{729B}\x{729C}\x{729D}\x{729E}\x{729F}\x{72A1}\x{72A2}\x{72A3}\x{72A4}' . + '\x{72A5}\x{72A6}\x{72A7}\x{72A8}\x{72A9}\x{72AA}\x{72AC}\x{72AD}\x{72AE}' . + '\x{72AF}\x{72B0}\x{72B1}\x{72B2}\x{72B3}\x{72B4}\x{72B5}\x{72B6}\x{72B7}' . + '\x{72B8}\x{72B9}\x{72BA}\x{72BB}\x{72BC}\x{72BD}\x{72BF}\x{72C0}\x{72C1}' . + '\x{72C2}\x{72C3}\x{72C4}\x{72C5}\x{72C6}\x{72C7}\x{72C8}\x{72C9}\x{72CA}' . + '\x{72CB}\x{72CC}\x{72CD}\x{72CE}\x{72CF}\x{72D0}\x{72D1}\x{72D2}\x{72D3}' . + '\x{72D4}\x{72D5}\x{72D6}\x{72D7}\x{72D8}\x{72D9}\x{72DA}\x{72DB}\x{72DC}' . + '\x{72DD}\x{72DE}\x{72DF}\x{72E0}\x{72E1}\x{72E2}\x{72E3}\x{72E4}\x{72E5}' . + '\x{72E6}\x{72E7}\x{72E8}\x{72E9}\x{72EA}\x{72EB}\x{72EC}\x{72ED}\x{72EE}' . + '\x{72EF}\x{72F0}\x{72F1}\x{72F2}\x{72F3}\x{72F4}\x{72F5}\x{72F6}\x{72F7}' . + '\x{72F8}\x{72F9}\x{72FA}\x{72FB}\x{72FC}\x{72FD}\x{72FE}\x{72FF}\x{7300}' . + '\x{7301}\x{7303}\x{7304}\x{7305}\x{7306}\x{7307}\x{7308}\x{7309}\x{730A}' . + '\x{730B}\x{730C}\x{730D}\x{730E}\x{730F}\x{7311}\x{7312}\x{7313}\x{7314}' . + '\x{7315}\x{7316}\x{7317}\x{7318}\x{7319}\x{731A}\x{731B}\x{731C}\x{731D}' . + '\x{731E}\x{7320}\x{7321}\x{7322}\x{7323}\x{7324}\x{7325}\x{7326}\x{7327}' . + '\x{7329}\x{732A}\x{732B}\x{732C}\x{732D}\x{732E}\x{7330}\x{7331}\x{7332}' . + '\x{7333}\x{7334}\x{7335}\x{7336}\x{7337}\x{7338}\x{7339}\x{733A}\x{733B}' . + '\x{733C}\x{733D}\x{733E}\x{733F}\x{7340}\x{7341}\x{7342}\x{7343}\x{7344}' . + '\x{7345}\x{7346}\x{7347}\x{7348}\x{7349}\x{734A}\x{734B}\x{734C}\x{734D}' . + '\x{734E}\x{7350}\x{7351}\x{7352}\x{7354}\x{7355}\x{7356}\x{7357}\x{7358}' . + '\x{7359}\x{735A}\x{735B}\x{735C}\x{735D}\x{735E}\x{735F}\x{7360}\x{7361}' . + '\x{7362}\x{7364}\x{7365}\x{7366}\x{7367}\x{7368}\x{7369}\x{736A}\x{736B}' . + '\x{736C}\x{736D}\x{736E}\x{736F}\x{7370}\x{7371}\x{7372}\x{7373}\x{7374}' . + '\x{7375}\x{7376}\x{7377}\x{7378}\x{7379}\x{737A}\x{737B}\x{737C}\x{737D}' . + '\x{737E}\x{737F}\x{7380}\x{7381}\x{7382}\x{7383}\x{7384}\x{7385}\x{7386}' . + '\x{7387}\x{7388}\x{7389}\x{738A}\x{738B}\x{738C}\x{738D}\x{738E}\x{738F}' . + '\x{7390}\x{7391}\x{7392}\x{7393}\x{7394}\x{7395}\x{7396}\x{7397}\x{7398}' . + '\x{7399}\x{739A}\x{739B}\x{739D}\x{739E}\x{739F}\x{73A0}\x{73A1}\x{73A2}' . + '\x{73A3}\x{73A4}\x{73A5}\x{73A6}\x{73A7}\x{73A8}\x{73A9}\x{73AA}\x{73AB}' . + '\x{73AC}\x{73AD}\x{73AE}\x{73AF}\x{73B0}\x{73B1}\x{73B2}\x{73B3}\x{73B4}' . + '\x{73B5}\x{73B6}\x{73B7}\x{73B8}\x{73B9}\x{73BA}\x{73BB}\x{73BC}\x{73BD}' . + '\x{73BE}\x{73BF}\x{73C0}\x{73C2}\x{73C3}\x{73C4}\x{73C5}\x{73C6}\x{73C7}' . + '\x{73C8}\x{73C9}\x{73CA}\x{73CB}\x{73CC}\x{73CD}\x{73CE}\x{73CF}\x{73D0}' . + '\x{73D1}\x{73D2}\x{73D3}\x{73D4}\x{73D5}\x{73D6}\x{73D7}\x{73D8}\x{73D9}' . + '\x{73DA}\x{73DB}\x{73DC}\x{73DD}\x{73DE}\x{73DF}\x{73E0}\x{73E2}\x{73E3}' . + '\x{73E5}\x{73E6}\x{73E7}\x{73E8}\x{73E9}\x{73EA}\x{73EB}\x{73EC}\x{73ED}' . + '\x{73EE}\x{73EF}\x{73F0}\x{73F1}\x{73F2}\x{73F4}\x{73F5}\x{73F6}\x{73F7}' . + '\x{73F8}\x{73F9}\x{73FA}\x{73FC}\x{73FD}\x{73FE}\x{73FF}\x{7400}\x{7401}' . + '\x{7402}\x{7403}\x{7404}\x{7405}\x{7406}\x{7407}\x{7408}\x{7409}\x{740A}' . + '\x{740B}\x{740C}\x{740D}\x{740E}\x{740F}\x{7410}\x{7411}\x{7412}\x{7413}' . + '\x{7414}\x{7415}\x{7416}\x{7417}\x{7419}\x{741A}\x{741B}\x{741C}\x{741D}' . + '\x{741E}\x{741F}\x{7420}\x{7421}\x{7422}\x{7423}\x{7424}\x{7425}\x{7426}' . + '\x{7427}\x{7428}\x{7429}\x{742A}\x{742B}\x{742C}\x{742D}\x{742E}\x{742F}' . + '\x{7430}\x{7431}\x{7432}\x{7433}\x{7434}\x{7435}\x{7436}\x{7437}\x{7438}' . + '\x{743A}\x{743B}\x{743C}\x{743D}\x{743F}\x{7440}\x{7441}\x{7442}\x{7443}' . + '\x{7444}\x{7445}\x{7446}\x{7448}\x{744A}\x{744B}\x{744C}\x{744D}\x{744E}' . + '\x{744F}\x{7450}\x{7451}\x{7452}\x{7453}\x{7454}\x{7455}\x{7456}\x{7457}' . + '\x{7459}\x{745A}\x{745B}\x{745C}\x{745D}\x{745E}\x{745F}\x{7461}\x{7462}' . + '\x{7463}\x{7464}\x{7465}\x{7466}\x{7467}\x{7468}\x{7469}\x{746A}\x{746B}' . + '\x{746C}\x{746D}\x{746E}\x{746F}\x{7470}\x{7471}\x{7472}\x{7473}\x{7474}' . + '\x{7475}\x{7476}\x{7477}\x{7478}\x{7479}\x{747A}\x{747C}\x{747D}\x{747E}' . + '\x{747F}\x{7480}\x{7481}\x{7482}\x{7483}\x{7485}\x{7486}\x{7487}\x{7488}' . + '\x{7489}\x{748A}\x{748B}\x{748C}\x{748D}\x{748E}\x{748F}\x{7490}\x{7491}' . + '\x{7492}\x{7493}\x{7494}\x{7495}\x{7497}\x{7498}\x{7499}\x{749A}\x{749B}' . + '\x{749C}\x{749E}\x{749F}\x{74A0}\x{74A1}\x{74A3}\x{74A4}\x{74A5}\x{74A6}' . + '\x{74A7}\x{74A8}\x{74A9}\x{74AA}\x{74AB}\x{74AC}\x{74AD}\x{74AE}\x{74AF}' . + '\x{74B0}\x{74B1}\x{74B2}\x{74B3}\x{74B4}\x{74B5}\x{74B6}\x{74B7}\x{74B8}' . + '\x{74B9}\x{74BA}\x{74BB}\x{74BC}\x{74BD}\x{74BE}\x{74BF}\x{74C0}\x{74C1}' . + '\x{74C2}\x{74C3}\x{74C4}\x{74C5}\x{74C6}\x{74CA}\x{74CB}\x{74CD}\x{74CE}' . + '\x{74CF}\x{74D0}\x{74D1}\x{74D2}\x{74D3}\x{74D4}\x{74D5}\x{74D6}\x{74D7}' . + '\x{74D8}\x{74D9}\x{74DA}\x{74DB}\x{74DC}\x{74DD}\x{74DE}\x{74DF}\x{74E0}' . + '\x{74E1}\x{74E2}\x{74E3}\x{74E4}\x{74E5}\x{74E6}\x{74E7}\x{74E8}\x{74E9}' . + '\x{74EA}\x{74EC}\x{74ED}\x{74EE}\x{74EF}\x{74F0}\x{74F1}\x{74F2}\x{74F3}' . + '\x{74F4}\x{74F5}\x{74F6}\x{74F7}\x{74F8}\x{74F9}\x{74FA}\x{74FB}\x{74FC}' . + '\x{74FD}\x{74FE}\x{74FF}\x{7500}\x{7501}\x{7502}\x{7503}\x{7504}\x{7505}' . + '\x{7506}\x{7507}\x{7508}\x{7509}\x{750A}\x{750B}\x{750C}\x{750D}\x{750F}' . + '\x{7510}\x{7511}\x{7512}\x{7513}\x{7514}\x{7515}\x{7516}\x{7517}\x{7518}' . + '\x{7519}\x{751A}\x{751B}\x{751C}\x{751D}\x{751E}\x{751F}\x{7521}\x{7522}' . + '\x{7523}\x{7524}\x{7525}\x{7526}\x{7527}\x{7528}\x{7529}\x{752A}\x{752B}' . + '\x{752C}\x{752D}\x{752E}\x{752F}\x{7530}\x{7531}\x{7532}\x{7533}\x{7535}' . + '\x{7536}\x{7537}\x{7538}\x{7539}\x{753A}\x{753B}\x{753C}\x{753D}\x{753E}' . + '\x{753F}\x{7540}\x{7542}\x{7543}\x{7544}\x{7545}\x{7546}\x{7547}\x{7548}' . + '\x{7549}\x{754B}\x{754C}\x{754D}\x{754E}\x{754F}\x{7550}\x{7551}\x{7553}' . + '\x{7554}\x{7556}\x{7557}\x{7558}\x{7559}\x{755A}\x{755B}\x{755C}\x{755D}' . + '\x{755F}\x{7560}\x{7562}\x{7563}\x{7564}\x{7565}\x{7566}\x{7567}\x{7568}' . + '\x{7569}\x{756A}\x{756B}\x{756C}\x{756D}\x{756E}\x{756F}\x{7570}\x{7572}' . + '\x{7574}\x{7575}\x{7576}\x{7577}\x{7578}\x{7579}\x{757C}\x{757D}\x{757E}' . + '\x{757F}\x{7580}\x{7581}\x{7582}\x{7583}\x{7584}\x{7586}\x{7587}\x{7588}' . + '\x{7589}\x{758A}\x{758B}\x{758C}\x{758D}\x{758F}\x{7590}\x{7591}\x{7592}' . + '\x{7593}\x{7594}\x{7595}\x{7596}\x{7597}\x{7598}\x{7599}\x{759A}\x{759B}' . + '\x{759C}\x{759D}\x{759E}\x{759F}\x{75A0}\x{75A1}\x{75A2}\x{75A3}\x{75A4}' . + '\x{75A5}\x{75A6}\x{75A7}\x{75A8}\x{75AA}\x{75AB}\x{75AC}\x{75AD}\x{75AE}' . + '\x{75AF}\x{75B0}\x{75B1}\x{75B2}\x{75B3}\x{75B4}\x{75B5}\x{75B6}\x{75B8}' . + '\x{75B9}\x{75BA}\x{75BB}\x{75BC}\x{75BD}\x{75BE}\x{75BF}\x{75C0}\x{75C1}' . + '\x{75C2}\x{75C3}\x{75C4}\x{75C5}\x{75C6}\x{75C7}\x{75C8}\x{75C9}\x{75CA}' . + '\x{75CB}\x{75CC}\x{75CD}\x{75CE}\x{75CF}\x{75D0}\x{75D1}\x{75D2}\x{75D3}' . + '\x{75D4}\x{75D5}\x{75D6}\x{75D7}\x{75D8}\x{75D9}\x{75DA}\x{75DB}\x{75DD}' . + '\x{75DE}\x{75DF}\x{75E0}\x{75E1}\x{75E2}\x{75E3}\x{75E4}\x{75E5}\x{75E6}' . + '\x{75E7}\x{75E8}\x{75EA}\x{75EB}\x{75EC}\x{75ED}\x{75EF}\x{75F0}\x{75F1}' . + '\x{75F2}\x{75F3}\x{75F4}\x{75F5}\x{75F6}\x{75F7}\x{75F8}\x{75F9}\x{75FA}' . + '\x{75FB}\x{75FC}\x{75FD}\x{75FE}\x{75FF}\x{7600}\x{7601}\x{7602}\x{7603}' . + '\x{7604}\x{7605}\x{7606}\x{7607}\x{7608}\x{7609}\x{760A}\x{760B}\x{760C}' . + '\x{760D}\x{760E}\x{760F}\x{7610}\x{7611}\x{7612}\x{7613}\x{7614}\x{7615}' . + '\x{7616}\x{7617}\x{7618}\x{7619}\x{761A}\x{761B}\x{761C}\x{761D}\x{761E}' . + '\x{761F}\x{7620}\x{7621}\x{7622}\x{7623}\x{7624}\x{7625}\x{7626}\x{7627}' . + '\x{7628}\x{7629}\x{762A}\x{762B}\x{762D}\x{762E}\x{762F}\x{7630}\x{7631}' . + '\x{7632}\x{7633}\x{7634}\x{7635}\x{7636}\x{7637}\x{7638}\x{7639}\x{763A}' . + '\x{763B}\x{763C}\x{763D}\x{763E}\x{763F}\x{7640}\x{7641}\x{7642}\x{7643}' . + '\x{7646}\x{7647}\x{7648}\x{7649}\x{764A}\x{764B}\x{764C}\x{764D}\x{764F}' . + '\x{7650}\x{7652}\x{7653}\x{7654}\x{7656}\x{7657}\x{7658}\x{7659}\x{765A}' . + '\x{765B}\x{765C}\x{765D}\x{765E}\x{765F}\x{7660}\x{7661}\x{7662}\x{7663}' . + '\x{7664}\x{7665}\x{7666}\x{7667}\x{7668}\x{7669}\x{766A}\x{766B}\x{766C}' . + '\x{766D}\x{766E}\x{766F}\x{7670}\x{7671}\x{7672}\x{7674}\x{7675}\x{7676}' . + '\x{7677}\x{7678}\x{7679}\x{767B}\x{767C}\x{767D}\x{767E}\x{767F}\x{7680}' . + '\x{7681}\x{7682}\x{7683}\x{7684}\x{7685}\x{7686}\x{7687}\x{7688}\x{7689}' . + '\x{768A}\x{768B}\x{768C}\x{768E}\x{768F}\x{7690}\x{7691}\x{7692}\x{7693}' . + '\x{7694}\x{7695}\x{7696}\x{7697}\x{7698}\x{7699}\x{769A}\x{769B}\x{769C}' . + '\x{769D}\x{769E}\x{769F}\x{76A0}\x{76A3}\x{76A4}\x{76A6}\x{76A7}\x{76A9}' . + '\x{76AA}\x{76AB}\x{76AC}\x{76AD}\x{76AE}\x{76AF}\x{76B0}\x{76B1}\x{76B2}' . + '\x{76B4}\x{76B5}\x{76B7}\x{76B8}\x{76BA}\x{76BB}\x{76BC}\x{76BD}\x{76BE}' . + '\x{76BF}\x{76C0}\x{76C2}\x{76C3}\x{76C4}\x{76C5}\x{76C6}\x{76C7}\x{76C8}' . + '\x{76C9}\x{76CA}\x{76CD}\x{76CE}\x{76CF}\x{76D0}\x{76D1}\x{76D2}\x{76D3}' . + '\x{76D4}\x{76D5}\x{76D6}\x{76D7}\x{76D8}\x{76DA}\x{76DB}\x{76DC}\x{76DD}' . + '\x{76DE}\x{76DF}\x{76E0}\x{76E1}\x{76E2}\x{76E3}\x{76E4}\x{76E5}\x{76E6}' . + '\x{76E7}\x{76E8}\x{76E9}\x{76EA}\x{76EC}\x{76ED}\x{76EE}\x{76EF}\x{76F0}' . + '\x{76F1}\x{76F2}\x{76F3}\x{76F4}\x{76F5}\x{76F6}\x{76F7}\x{76F8}\x{76F9}' . + '\x{76FA}\x{76FB}\x{76FC}\x{76FD}\x{76FE}\x{76FF}\x{7701}\x{7703}\x{7704}' . + '\x{7705}\x{7706}\x{7707}\x{7708}\x{7709}\x{770A}\x{770B}\x{770C}\x{770D}' . + '\x{770F}\x{7710}\x{7711}\x{7712}\x{7713}\x{7714}\x{7715}\x{7716}\x{7717}' . + '\x{7718}\x{7719}\x{771A}\x{771B}\x{771C}\x{771D}\x{771E}\x{771F}\x{7720}' . + '\x{7722}\x{7723}\x{7725}\x{7726}\x{7727}\x{7728}\x{7729}\x{772A}\x{772C}' . + '\x{772D}\x{772E}\x{772F}\x{7730}\x{7731}\x{7732}\x{7733}\x{7734}\x{7735}' . + '\x{7736}\x{7737}\x{7738}\x{7739}\x{773A}\x{773B}\x{773C}\x{773D}\x{773E}' . + '\x{7740}\x{7741}\x{7743}\x{7744}\x{7745}\x{7746}\x{7747}\x{7748}\x{7749}' . + '\x{774A}\x{774B}\x{774C}\x{774D}\x{774E}\x{774F}\x{7750}\x{7751}\x{7752}' . + '\x{7753}\x{7754}\x{7755}\x{7756}\x{7757}\x{7758}\x{7759}\x{775A}\x{775B}' . + '\x{775C}\x{775D}\x{775E}\x{775F}\x{7760}\x{7761}\x{7762}\x{7763}\x{7765}' . + '\x{7766}\x{7767}\x{7768}\x{7769}\x{776A}\x{776B}\x{776C}\x{776D}\x{776E}' . + '\x{776F}\x{7770}\x{7771}\x{7772}\x{7773}\x{7774}\x{7775}\x{7776}\x{7777}' . + '\x{7778}\x{7779}\x{777A}\x{777B}\x{777C}\x{777D}\x{777E}\x{777F}\x{7780}' . + '\x{7781}\x{7782}\x{7783}\x{7784}\x{7785}\x{7786}\x{7787}\x{7788}\x{7789}' . + '\x{778A}\x{778B}\x{778C}\x{778D}\x{778E}\x{778F}\x{7790}\x{7791}\x{7792}' . + '\x{7793}\x{7794}\x{7795}\x{7797}\x{7798}\x{7799}\x{779A}\x{779B}\x{779C}' . + '\x{779D}\x{779E}\x{779F}\x{77A0}\x{77A1}\x{77A2}\x{77A3}\x{77A5}\x{77A6}' . + '\x{77A7}\x{77A8}\x{77A9}\x{77AA}\x{77AB}\x{77AC}\x{77AD}\x{77AE}\x{77AF}' . + '\x{77B0}\x{77B1}\x{77B2}\x{77B3}\x{77B4}\x{77B5}\x{77B6}\x{77B7}\x{77B8}' . + '\x{77B9}\x{77BA}\x{77BB}\x{77BC}\x{77BD}\x{77BF}\x{77C0}\x{77C2}\x{77C3}' . + '\x{77C4}\x{77C5}\x{77C6}\x{77C7}\x{77C8}\x{77C9}\x{77CA}\x{77CB}\x{77CC}' . + '\x{77CD}\x{77CE}\x{77CF}\x{77D0}\x{77D1}\x{77D3}\x{77D4}\x{77D5}\x{77D6}' . + '\x{77D7}\x{77D8}\x{77D9}\x{77DA}\x{77DB}\x{77DC}\x{77DE}\x{77DF}\x{77E0}' . + '\x{77E1}\x{77E2}\x{77E3}\x{77E5}\x{77E7}\x{77E8}\x{77E9}\x{77EA}\x{77EB}' . + '\x{77EC}\x{77ED}\x{77EE}\x{77EF}\x{77F0}\x{77F1}\x{77F2}\x{77F3}\x{77F6}' . + '\x{77F7}\x{77F8}\x{77F9}\x{77FA}\x{77FB}\x{77FC}\x{77FD}\x{77FE}\x{77FF}' . + '\x{7800}\x{7801}\x{7802}\x{7803}\x{7804}\x{7805}\x{7806}\x{7808}\x{7809}' . + '\x{780A}\x{780B}\x{780C}\x{780D}\x{780E}\x{780F}\x{7810}\x{7811}\x{7812}' . + '\x{7813}\x{7814}\x{7815}\x{7816}\x{7817}\x{7818}\x{7819}\x{781A}\x{781B}' . + '\x{781C}\x{781D}\x{781E}\x{781F}\x{7820}\x{7821}\x{7822}\x{7823}\x{7825}' . + '\x{7826}\x{7827}\x{7828}\x{7829}\x{782A}\x{782B}\x{782C}\x{782D}\x{782E}' . + '\x{782F}\x{7830}\x{7831}\x{7832}\x{7833}\x{7834}\x{7835}\x{7837}\x{7838}' . + '\x{7839}\x{783A}\x{783B}\x{783C}\x{783D}\x{783E}\x{7840}\x{7841}\x{7843}' . + '\x{7844}\x{7845}\x{7847}\x{7848}\x{7849}\x{784A}\x{784C}\x{784D}\x{784E}' . + '\x{7850}\x{7851}\x{7852}\x{7853}\x{7854}\x{7855}\x{7856}\x{7857}\x{7858}' . + '\x{7859}\x{785A}\x{785B}\x{785C}\x{785D}\x{785E}\x{785F}\x{7860}\x{7861}' . + '\x{7862}\x{7863}\x{7864}\x{7865}\x{7866}\x{7867}\x{7868}\x{7869}\x{786A}' . + '\x{786B}\x{786C}\x{786D}\x{786E}\x{786F}\x{7870}\x{7871}\x{7872}\x{7873}' . + '\x{7874}\x{7875}\x{7877}\x{7878}\x{7879}\x{787A}\x{787B}\x{787C}\x{787D}' . + '\x{787E}\x{787F}\x{7880}\x{7881}\x{7882}\x{7883}\x{7884}\x{7885}\x{7886}' . + '\x{7887}\x{7889}\x{788A}\x{788B}\x{788C}\x{788D}\x{788E}\x{788F}\x{7890}' . + '\x{7891}\x{7892}\x{7893}\x{7894}\x{7895}\x{7896}\x{7897}\x{7898}\x{7899}' . + '\x{789A}\x{789B}\x{789C}\x{789D}\x{789E}\x{789F}\x{78A0}\x{78A1}\x{78A2}' . + '\x{78A3}\x{78A4}\x{78A5}\x{78A6}\x{78A7}\x{78A8}\x{78A9}\x{78AA}\x{78AB}' . + '\x{78AC}\x{78AD}\x{78AE}\x{78AF}\x{78B0}\x{78B1}\x{78B2}\x{78B3}\x{78B4}' . + '\x{78B5}\x{78B6}\x{78B7}\x{78B8}\x{78B9}\x{78BA}\x{78BB}\x{78BC}\x{78BD}' . + '\x{78BE}\x{78BF}\x{78C0}\x{78C1}\x{78C3}\x{78C4}\x{78C5}\x{78C6}\x{78C8}' . + '\x{78C9}\x{78CA}\x{78CB}\x{78CC}\x{78CD}\x{78CE}\x{78CF}\x{78D0}\x{78D1}' . + '\x{78D3}\x{78D4}\x{78D5}\x{78D6}\x{78D7}\x{78D8}\x{78D9}\x{78DA}\x{78DB}' . + '\x{78DC}\x{78DD}\x{78DE}\x{78DF}\x{78E0}\x{78E1}\x{78E2}\x{78E3}\x{78E4}' . + '\x{78E5}\x{78E6}\x{78E7}\x{78E8}\x{78E9}\x{78EA}\x{78EB}\x{78EC}\x{78ED}' . + '\x{78EE}\x{78EF}\x{78F1}\x{78F2}\x{78F3}\x{78F4}\x{78F5}\x{78F6}\x{78F7}' . + '\x{78F9}\x{78FA}\x{78FB}\x{78FC}\x{78FD}\x{78FE}\x{78FF}\x{7901}\x{7902}' . + '\x{7903}\x{7904}\x{7905}\x{7906}\x{7907}\x{7909}\x{790A}\x{790B}\x{790C}' . + '\x{790E}\x{790F}\x{7910}\x{7911}\x{7912}\x{7913}\x{7914}\x{7916}\x{7917}' . + '\x{7918}\x{7919}\x{791A}\x{791B}\x{791C}\x{791D}\x{791E}\x{7921}\x{7922}' . + '\x{7923}\x{7924}\x{7925}\x{7926}\x{7927}\x{7928}\x{7929}\x{792A}\x{792B}' . + '\x{792C}\x{792D}\x{792E}\x{792F}\x{7930}\x{7931}\x{7933}\x{7934}\x{7935}' . + '\x{7937}\x{7938}\x{7939}\x{793A}\x{793B}\x{793C}\x{793D}\x{793E}\x{793F}' . + '\x{7940}\x{7941}\x{7942}\x{7943}\x{7944}\x{7945}\x{7946}\x{7947}\x{7948}' . + '\x{7949}\x{794A}\x{794B}\x{794C}\x{794D}\x{794E}\x{794F}\x{7950}\x{7951}' . + '\x{7952}\x{7953}\x{7954}\x{7955}\x{7956}\x{7957}\x{7958}\x{795A}\x{795B}' . + '\x{795C}\x{795D}\x{795E}\x{795F}\x{7960}\x{7961}\x{7962}\x{7963}\x{7964}' . + '\x{7965}\x{7966}\x{7967}\x{7968}\x{7969}\x{796A}\x{796B}\x{796D}\x{796F}' . + '\x{7970}\x{7971}\x{7972}\x{7973}\x{7974}\x{7977}\x{7978}\x{7979}\x{797A}' . + '\x{797B}\x{797C}\x{797D}\x{797E}\x{797F}\x{7980}\x{7981}\x{7982}\x{7983}' . + '\x{7984}\x{7985}\x{7988}\x{7989}\x{798A}\x{798B}\x{798C}\x{798D}\x{798E}' . + '\x{798F}\x{7990}\x{7991}\x{7992}\x{7993}\x{7994}\x{7995}\x{7996}\x{7997}' . + '\x{7998}\x{7999}\x{799A}\x{799B}\x{799C}\x{799F}\x{79A0}\x{79A1}\x{79A2}' . + '\x{79A3}\x{79A4}\x{79A5}\x{79A6}\x{79A7}\x{79A8}\x{79AA}\x{79AB}\x{79AC}' . + '\x{79AD}\x{79AE}\x{79AF}\x{79B0}\x{79B1}\x{79B2}\x{79B3}\x{79B4}\x{79B5}' . + '\x{79B6}\x{79B7}\x{79B8}\x{79B9}\x{79BA}\x{79BB}\x{79BD}\x{79BE}\x{79BF}' . + '\x{79C0}\x{79C1}\x{79C2}\x{79C3}\x{79C5}\x{79C6}\x{79C8}\x{79C9}\x{79CA}' . + '\x{79CB}\x{79CD}\x{79CE}\x{79CF}\x{79D0}\x{79D1}\x{79D2}\x{79D3}\x{79D5}' . + '\x{79D6}\x{79D8}\x{79D9}\x{79DA}\x{79DB}\x{79DC}\x{79DD}\x{79DE}\x{79DF}' . + '\x{79E0}\x{79E1}\x{79E2}\x{79E3}\x{79E4}\x{79E5}\x{79E6}\x{79E7}\x{79E8}' . + '\x{79E9}\x{79EA}\x{79EB}\x{79EC}\x{79ED}\x{79EE}\x{79EF}\x{79F0}\x{79F1}' . + '\x{79F2}\x{79F3}\x{79F4}\x{79F5}\x{79F6}\x{79F7}\x{79F8}\x{79F9}\x{79FA}' . + '\x{79FB}\x{79FC}\x{79FD}\x{79FE}\x{79FF}\x{7A00}\x{7A02}\x{7A03}\x{7A04}' . + '\x{7A05}\x{7A06}\x{7A08}\x{7A0A}\x{7A0B}\x{7A0C}\x{7A0D}\x{7A0E}\x{7A0F}' . + '\x{7A10}\x{7A11}\x{7A12}\x{7A13}\x{7A14}\x{7A15}\x{7A16}\x{7A17}\x{7A18}' . + '\x{7A19}\x{7A1A}\x{7A1B}\x{7A1C}\x{7A1D}\x{7A1E}\x{7A1F}\x{7A20}\x{7A21}' . + '\x{7A22}\x{7A23}\x{7A24}\x{7A25}\x{7A26}\x{7A27}\x{7A28}\x{7A29}\x{7A2A}' . + '\x{7A2B}\x{7A2D}\x{7A2E}\x{7A2F}\x{7A30}\x{7A31}\x{7A32}\x{7A33}\x{7A34}' . + '\x{7A35}\x{7A37}\x{7A39}\x{7A3B}\x{7A3C}\x{7A3D}\x{7A3E}\x{7A3F}\x{7A40}' . + '\x{7A41}\x{7A42}\x{7A43}\x{7A44}\x{7A45}\x{7A46}\x{7A47}\x{7A48}\x{7A49}' . + '\x{7A4A}\x{7A4B}\x{7A4C}\x{7A4D}\x{7A4E}\x{7A50}\x{7A51}\x{7A52}\x{7A53}' . + '\x{7A54}\x{7A55}\x{7A56}\x{7A57}\x{7A58}\x{7A59}\x{7A5A}\x{7A5B}\x{7A5C}' . + '\x{7A5D}\x{7A5E}\x{7A5F}\x{7A60}\x{7A61}\x{7A62}\x{7A65}\x{7A66}\x{7A67}' . + '\x{7A68}\x{7A69}\x{7A6B}\x{7A6C}\x{7A6D}\x{7A6E}\x{7A70}\x{7A71}\x{7A72}' . + '\x{7A73}\x{7A74}\x{7A75}\x{7A76}\x{7A77}\x{7A78}\x{7A79}\x{7A7A}\x{7A7B}' . + '\x{7A7C}\x{7A7D}\x{7A7E}\x{7A7F}\x{7A80}\x{7A81}\x{7A83}\x{7A84}\x{7A85}' . + '\x{7A86}\x{7A87}\x{7A88}\x{7A89}\x{7A8A}\x{7A8B}\x{7A8C}\x{7A8D}\x{7A8E}' . + '\x{7A8F}\x{7A90}\x{7A91}\x{7A92}\x{7A93}\x{7A94}\x{7A95}\x{7A96}\x{7A97}' . + '\x{7A98}\x{7A99}\x{7A9C}\x{7A9D}\x{7A9E}\x{7A9F}\x{7AA0}\x{7AA1}\x{7AA2}' . + '\x{7AA3}\x{7AA4}\x{7AA5}\x{7AA6}\x{7AA7}\x{7AA8}\x{7AA9}\x{7AAA}\x{7AAB}' . + '\x{7AAC}\x{7AAD}\x{7AAE}\x{7AAF}\x{7AB0}\x{7AB1}\x{7AB2}\x{7AB3}\x{7AB4}' . + '\x{7AB5}\x{7AB6}\x{7AB7}\x{7AB8}\x{7ABA}\x{7ABE}\x{7ABF}\x{7AC0}\x{7AC1}' . + '\x{7AC4}\x{7AC5}\x{7AC7}\x{7AC8}\x{7AC9}\x{7ACA}\x{7ACB}\x{7ACC}\x{7ACD}' . + '\x{7ACE}\x{7ACF}\x{7AD0}\x{7AD1}\x{7AD2}\x{7AD3}\x{7AD4}\x{7AD5}\x{7AD6}' . + '\x{7AD8}\x{7AD9}\x{7ADB}\x{7ADC}\x{7ADD}\x{7ADE}\x{7ADF}\x{7AE0}\x{7AE1}' . + '\x{7AE2}\x{7AE3}\x{7AE4}\x{7AE5}\x{7AE6}\x{7AE7}\x{7AE8}\x{7AEA}\x{7AEB}' . + '\x{7AEC}\x{7AED}\x{7AEE}\x{7AEF}\x{7AF0}\x{7AF1}\x{7AF2}\x{7AF3}\x{7AF4}' . + '\x{7AF6}\x{7AF7}\x{7AF8}\x{7AF9}\x{7AFA}\x{7AFB}\x{7AFD}\x{7AFE}\x{7AFF}' . + '\x{7B00}\x{7B01}\x{7B02}\x{7B03}\x{7B04}\x{7B05}\x{7B06}\x{7B08}\x{7B09}' . + '\x{7B0A}\x{7B0B}\x{7B0C}\x{7B0D}\x{7B0E}\x{7B0F}\x{7B10}\x{7B11}\x{7B12}' . + '\x{7B13}\x{7B14}\x{7B15}\x{7B16}\x{7B17}\x{7B18}\x{7B19}\x{7B1A}\x{7B1B}' . + '\x{7B1C}\x{7B1D}\x{7B1E}\x{7B20}\x{7B21}\x{7B22}\x{7B23}\x{7B24}\x{7B25}' . + '\x{7B26}\x{7B28}\x{7B2A}\x{7B2B}\x{7B2C}\x{7B2D}\x{7B2E}\x{7B2F}\x{7B30}' . + '\x{7B31}\x{7B32}\x{7B33}\x{7B34}\x{7B35}\x{7B36}\x{7B37}\x{7B38}\x{7B39}' . + '\x{7B3A}\x{7B3B}\x{7B3C}\x{7B3D}\x{7B3E}\x{7B3F}\x{7B40}\x{7B41}\x{7B43}' . + '\x{7B44}\x{7B45}\x{7B46}\x{7B47}\x{7B48}\x{7B49}\x{7B4A}\x{7B4B}\x{7B4C}' . + '\x{7B4D}\x{7B4E}\x{7B4F}\x{7B50}\x{7B51}\x{7B52}\x{7B54}\x{7B55}\x{7B56}' . + '\x{7B57}\x{7B58}\x{7B59}\x{7B5A}\x{7B5B}\x{7B5C}\x{7B5D}\x{7B5E}\x{7B5F}' . + '\x{7B60}\x{7B61}\x{7B62}\x{7B63}\x{7B64}\x{7B65}\x{7B66}\x{7B67}\x{7B68}' . + '\x{7B69}\x{7B6A}\x{7B6B}\x{7B6C}\x{7B6D}\x{7B6E}\x{7B70}\x{7B71}\x{7B72}' . + '\x{7B73}\x{7B74}\x{7B75}\x{7B76}\x{7B77}\x{7B78}\x{7B79}\x{7B7B}\x{7B7C}' . + '\x{7B7D}\x{7B7E}\x{7B7F}\x{7B80}\x{7B81}\x{7B82}\x{7B83}\x{7B84}\x{7B85}' . + '\x{7B87}\x{7B88}\x{7B89}\x{7B8A}\x{7B8B}\x{7B8C}\x{7B8D}\x{7B8E}\x{7B8F}' . + '\x{7B90}\x{7B91}\x{7B93}\x{7B94}\x{7B95}\x{7B96}\x{7B97}\x{7B98}\x{7B99}' . + '\x{7B9A}\x{7B9B}\x{7B9C}\x{7B9D}\x{7B9E}\x{7B9F}\x{7BA0}\x{7BA1}\x{7BA2}' . + '\x{7BA4}\x{7BA6}\x{7BA7}\x{7BA8}\x{7BA9}\x{7BAA}\x{7BAB}\x{7BAC}\x{7BAD}' . + '\x{7BAE}\x{7BAF}\x{7BB1}\x{7BB3}\x{7BB4}\x{7BB5}\x{7BB6}\x{7BB7}\x{7BB8}' . + '\x{7BB9}\x{7BBA}\x{7BBB}\x{7BBC}\x{7BBD}\x{7BBE}\x{7BBF}\x{7BC0}\x{7BC1}' . + '\x{7BC2}\x{7BC3}\x{7BC4}\x{7BC5}\x{7BC6}\x{7BC7}\x{7BC8}\x{7BC9}\x{7BCA}' . + '\x{7BCB}\x{7BCC}\x{7BCD}\x{7BCE}\x{7BD0}\x{7BD1}\x{7BD2}\x{7BD3}\x{7BD4}' . + '\x{7BD5}\x{7BD6}\x{7BD7}\x{7BD8}\x{7BD9}\x{7BDA}\x{7BDB}\x{7BDC}\x{7BDD}' . + '\x{7BDE}\x{7BDF}\x{7BE0}\x{7BE1}\x{7BE2}\x{7BE3}\x{7BE4}\x{7BE5}\x{7BE6}' . + '\x{7BE7}\x{7BE8}\x{7BE9}\x{7BEA}\x{7BEB}\x{7BEC}\x{7BED}\x{7BEE}\x{7BEF}' . + '\x{7BF0}\x{7BF1}\x{7BF2}\x{7BF3}\x{7BF4}\x{7BF5}\x{7BF6}\x{7BF7}\x{7BF8}' . + '\x{7BF9}\x{7BFB}\x{7BFC}\x{7BFD}\x{7BFE}\x{7BFF}\x{7C00}\x{7C01}\x{7C02}' . + '\x{7C03}\x{7C04}\x{7C05}\x{7C06}\x{7C07}\x{7C08}\x{7C09}\x{7C0A}\x{7C0B}' . + '\x{7C0C}\x{7C0D}\x{7C0E}\x{7C0F}\x{7C10}\x{7C11}\x{7C12}\x{7C13}\x{7C15}' . + '\x{7C16}\x{7C17}\x{7C18}\x{7C19}\x{7C1A}\x{7C1C}\x{7C1D}\x{7C1E}\x{7C1F}' . + '\x{7C20}\x{7C21}\x{7C22}\x{7C23}\x{7C24}\x{7C25}\x{7C26}\x{7C27}\x{7C28}' . + '\x{7C29}\x{7C2A}\x{7C2B}\x{7C2C}\x{7C2D}\x{7C30}\x{7C31}\x{7C32}\x{7C33}' . + '\x{7C34}\x{7C35}\x{7C36}\x{7C37}\x{7C38}\x{7C39}\x{7C3A}\x{7C3B}\x{7C3C}' . + '\x{7C3D}\x{7C3E}\x{7C3F}\x{7C40}\x{7C41}\x{7C42}\x{7C43}\x{7C44}\x{7C45}' . + '\x{7C46}\x{7C47}\x{7C48}\x{7C49}\x{7C4A}\x{7C4B}\x{7C4C}\x{7C4D}\x{7C4E}' . + '\x{7C50}\x{7C51}\x{7C53}\x{7C54}\x{7C56}\x{7C57}\x{7C58}\x{7C59}\x{7C5A}' . + '\x{7C5B}\x{7C5C}\x{7C5E}\x{7C5F}\x{7C60}\x{7C61}\x{7C62}\x{7C63}\x{7C64}' . + '\x{7C65}\x{7C66}\x{7C67}\x{7C68}\x{7C69}\x{7C6A}\x{7C6B}\x{7C6C}\x{7C6D}' . + '\x{7C6E}\x{7C6F}\x{7C70}\x{7C71}\x{7C72}\x{7C73}\x{7C74}\x{7C75}\x{7C77}' . + '\x{7C78}\x{7C79}\x{7C7A}\x{7C7B}\x{7C7C}\x{7C7D}\x{7C7E}\x{7C7F}\x{7C80}' . + '\x{7C81}\x{7C82}\x{7C84}\x{7C85}\x{7C86}\x{7C88}\x{7C89}\x{7C8A}\x{7C8B}' . + '\x{7C8C}\x{7C8D}\x{7C8E}\x{7C8F}\x{7C90}\x{7C91}\x{7C92}\x{7C94}\x{7C95}' . + '\x{7C96}\x{7C97}\x{7C98}\x{7C99}\x{7C9B}\x{7C9C}\x{7C9D}\x{7C9E}\x{7C9F}' . + '\x{7CA0}\x{7CA1}\x{7CA2}\x{7CA3}\x{7CA4}\x{7CA5}\x{7CA6}\x{7CA7}\x{7CA8}' . + '\x{7CA9}\x{7CAA}\x{7CAD}\x{7CAE}\x{7CAF}\x{7CB0}\x{7CB1}\x{7CB2}\x{7CB3}' . + '\x{7CB4}\x{7CB5}\x{7CB6}\x{7CB7}\x{7CB8}\x{7CB9}\x{7CBA}\x{7CBB}\x{7CBC}' . + '\x{7CBD}\x{7CBE}\x{7CBF}\x{7CC0}\x{7CC1}\x{7CC2}\x{7CC3}\x{7CC4}\x{7CC5}' . + '\x{7CC6}\x{7CC7}\x{7CC8}\x{7CC9}\x{7CCA}\x{7CCB}\x{7CCC}\x{7CCD}\x{7CCE}' . + '\x{7CCF}\x{7CD0}\x{7CD1}\x{7CD2}\x{7CD4}\x{7CD5}\x{7CD6}\x{7CD7}\x{7CD8}' . + '\x{7CD9}\x{7CDC}\x{7CDD}\x{7CDE}\x{7CDF}\x{7CE0}\x{7CE2}\x{7CE4}\x{7CE7}' . + '\x{7CE8}\x{7CE9}\x{7CEA}\x{7CEB}\x{7CEC}\x{7CED}\x{7CEE}\x{7CEF}\x{7CF0}' . + '\x{7CF1}\x{7CF2}\x{7CF3}\x{7CF4}\x{7CF5}\x{7CF6}\x{7CF7}\x{7CF8}\x{7CF9}' . + '\x{7CFA}\x{7CFB}\x{7CFD}\x{7CFE}\x{7D00}\x{7D01}\x{7D02}\x{7D03}\x{7D04}' . + '\x{7D05}\x{7D06}\x{7D07}\x{7D08}\x{7D09}\x{7D0A}\x{7D0B}\x{7D0C}\x{7D0D}' . + '\x{7D0E}\x{7D0F}\x{7D10}\x{7D11}\x{7D12}\x{7D13}\x{7D14}\x{7D15}\x{7D16}' . + '\x{7D17}\x{7D18}\x{7D19}\x{7D1A}\x{7D1B}\x{7D1C}\x{7D1D}\x{7D1E}\x{7D1F}' . + '\x{7D20}\x{7D21}\x{7D22}\x{7D24}\x{7D25}\x{7D26}\x{7D27}\x{7D28}\x{7D29}' . + '\x{7D2B}\x{7D2C}\x{7D2E}\x{7D2F}\x{7D30}\x{7D31}\x{7D32}\x{7D33}\x{7D34}' . + '\x{7D35}\x{7D36}\x{7D37}\x{7D38}\x{7D39}\x{7D3A}\x{7D3B}\x{7D3C}\x{7D3D}' . + '\x{7D3E}\x{7D3F}\x{7D40}\x{7D41}\x{7D42}\x{7D43}\x{7D44}\x{7D45}\x{7D46}' . + '\x{7D47}\x{7D49}\x{7D4A}\x{7D4B}\x{7D4C}\x{7D4E}\x{7D4F}\x{7D50}\x{7D51}' . + '\x{7D52}\x{7D53}\x{7D54}\x{7D55}\x{7D56}\x{7D57}\x{7D58}\x{7D59}\x{7D5B}' . + '\x{7D5C}\x{7D5D}\x{7D5E}\x{7D5F}\x{7D60}\x{7D61}\x{7D62}\x{7D63}\x{7D65}' . + '\x{7D66}\x{7D67}\x{7D68}\x{7D69}\x{7D6A}\x{7D6B}\x{7D6C}\x{7D6D}\x{7D6E}' . + '\x{7D6F}\x{7D70}\x{7D71}\x{7D72}\x{7D73}\x{7D74}\x{7D75}\x{7D76}\x{7D77}' . + '\x{7D79}\x{7D7A}\x{7D7B}\x{7D7C}\x{7D7D}\x{7D7E}\x{7D7F}\x{7D80}\x{7D81}' . + '\x{7D83}\x{7D84}\x{7D85}\x{7D86}\x{7D87}\x{7D88}\x{7D89}\x{7D8A}\x{7D8B}' . + '\x{7D8C}\x{7D8D}\x{7D8E}\x{7D8F}\x{7D90}\x{7D91}\x{7D92}\x{7D93}\x{7D94}' . + '\x{7D96}\x{7D97}\x{7D99}\x{7D9B}\x{7D9C}\x{7D9D}\x{7D9E}\x{7D9F}\x{7DA0}' . + '\x{7DA1}\x{7DA2}\x{7DA3}\x{7DA5}\x{7DA6}\x{7DA7}\x{7DA9}\x{7DAA}\x{7DAB}' . + '\x{7DAC}\x{7DAD}\x{7DAE}\x{7DAF}\x{7DB0}\x{7DB1}\x{7DB2}\x{7DB3}\x{7DB4}' . + '\x{7DB5}\x{7DB6}\x{7DB7}\x{7DB8}\x{7DB9}\x{7DBA}\x{7DBB}\x{7DBC}\x{7DBD}' . + '\x{7DBE}\x{7DBF}\x{7DC0}\x{7DC1}\x{7DC2}\x{7DC3}\x{7DC4}\x{7DC5}\x{7DC6}' . + '\x{7DC7}\x{7DC8}\x{7DC9}\x{7DCA}\x{7DCB}\x{7DCC}\x{7DCE}\x{7DCF}\x{7DD0}' . + '\x{7DD1}\x{7DD2}\x{7DD4}\x{7DD5}\x{7DD6}\x{7DD7}\x{7DD8}\x{7DD9}\x{7DDA}' . + '\x{7DDB}\x{7DDD}\x{7DDE}\x{7DDF}\x{7DE0}\x{7DE1}\x{7DE2}\x{7DE3}\x{7DE6}' . + '\x{7DE7}\x{7DE8}\x{7DE9}\x{7DEA}\x{7DEC}\x{7DED}\x{7DEE}\x{7DEF}\x{7DF0}' . + '\x{7DF1}\x{7DF2}\x{7DF3}\x{7DF4}\x{7DF5}\x{7DF6}\x{7DF7}\x{7DF8}\x{7DF9}' . + '\x{7DFA}\x{7DFB}\x{7DFC}\x{7E00}\x{7E01}\x{7E02}\x{7E03}\x{7E04}\x{7E05}' . + '\x{7E06}\x{7E07}\x{7E08}\x{7E09}\x{7E0A}\x{7E0B}\x{7E0C}\x{7E0D}\x{7E0E}' . + '\x{7E0F}\x{7E10}\x{7E11}\x{7E12}\x{7E13}\x{7E14}\x{7E15}\x{7E16}\x{7E17}' . + '\x{7E19}\x{7E1A}\x{7E1B}\x{7E1C}\x{7E1D}\x{7E1E}\x{7E1F}\x{7E20}\x{7E21}' . + '\x{7E22}\x{7E23}\x{7E24}\x{7E25}\x{7E26}\x{7E27}\x{7E28}\x{7E29}\x{7E2A}' . + '\x{7E2B}\x{7E2C}\x{7E2D}\x{7E2E}\x{7E2F}\x{7E30}\x{7E31}\x{7E32}\x{7E33}' . + '\x{7E34}\x{7E35}\x{7E36}\x{7E37}\x{7E38}\x{7E39}\x{7E3A}\x{7E3B}\x{7E3C}' . + '\x{7E3D}\x{7E3E}\x{7E3F}\x{7E40}\x{7E41}\x{7E42}\x{7E43}\x{7E44}\x{7E45}' . + '\x{7E46}\x{7E47}\x{7E48}\x{7E49}\x{7E4C}\x{7E4D}\x{7E4E}\x{7E4F}\x{7E50}' . + '\x{7E51}\x{7E52}\x{7E53}\x{7E54}\x{7E55}\x{7E56}\x{7E57}\x{7E58}\x{7E59}' . + '\x{7E5A}\x{7E5C}\x{7E5D}\x{7E5E}\x{7E5F}\x{7E60}\x{7E61}\x{7E62}\x{7E63}' . + '\x{7E65}\x{7E66}\x{7E67}\x{7E68}\x{7E69}\x{7E6A}\x{7E6B}\x{7E6C}\x{7E6D}' . + '\x{7E6E}\x{7E6F}\x{7E70}\x{7E71}\x{7E72}\x{7E73}\x{7E74}\x{7E75}\x{7E76}' . + '\x{7E77}\x{7E78}\x{7E79}\x{7E7A}\x{7E7B}\x{7E7C}\x{7E7D}\x{7E7E}\x{7E7F}' . + '\x{7E80}\x{7E81}\x{7E82}\x{7E83}\x{7E84}\x{7E85}\x{7E86}\x{7E87}\x{7E88}' . + '\x{7E89}\x{7E8A}\x{7E8B}\x{7E8C}\x{7E8D}\x{7E8E}\x{7E8F}\x{7E90}\x{7E91}' . + '\x{7E92}\x{7E93}\x{7E94}\x{7E95}\x{7E96}\x{7E97}\x{7E98}\x{7E99}\x{7E9A}' . + '\x{7E9B}\x{7E9C}\x{7E9E}\x{7E9F}\x{7EA0}\x{7EA1}\x{7EA2}\x{7EA3}\x{7EA4}' . + '\x{7EA5}\x{7EA6}\x{7EA7}\x{7EA8}\x{7EA9}\x{7EAA}\x{7EAB}\x{7EAC}\x{7EAD}' . + '\x{7EAE}\x{7EAF}\x{7EB0}\x{7EB1}\x{7EB2}\x{7EB3}\x{7EB4}\x{7EB5}\x{7EB6}' . + '\x{7EB7}\x{7EB8}\x{7EB9}\x{7EBA}\x{7EBB}\x{7EBC}\x{7EBD}\x{7EBE}\x{7EBF}' . + '\x{7EC0}\x{7EC1}\x{7EC2}\x{7EC3}\x{7EC4}\x{7EC5}\x{7EC6}\x{7EC7}\x{7EC8}' . + '\x{7EC9}\x{7ECA}\x{7ECB}\x{7ECC}\x{7ECD}\x{7ECE}\x{7ECF}\x{7ED0}\x{7ED1}' . + '\x{7ED2}\x{7ED3}\x{7ED4}\x{7ED5}\x{7ED6}\x{7ED7}\x{7ED8}\x{7ED9}\x{7EDA}' . + '\x{7EDB}\x{7EDC}\x{7EDD}\x{7EDE}\x{7EDF}\x{7EE0}\x{7EE1}\x{7EE2}\x{7EE3}' . + '\x{7EE4}\x{7EE5}\x{7EE6}\x{7EE7}\x{7EE8}\x{7EE9}\x{7EEA}\x{7EEB}\x{7EEC}' . + '\x{7EED}\x{7EEE}\x{7EEF}\x{7EF0}\x{7EF1}\x{7EF2}\x{7EF3}\x{7EF4}\x{7EF5}' . + '\x{7EF6}\x{7EF7}\x{7EF8}\x{7EF9}\x{7EFA}\x{7EFB}\x{7EFC}\x{7EFD}\x{7EFE}' . + '\x{7EFF}\x{7F00}\x{7F01}\x{7F02}\x{7F03}\x{7F04}\x{7F05}\x{7F06}\x{7F07}' . + '\x{7F08}\x{7F09}\x{7F0A}\x{7F0B}\x{7F0C}\x{7F0D}\x{7F0E}\x{7F0F}\x{7F10}' . + '\x{7F11}\x{7F12}\x{7F13}\x{7F14}\x{7F15}\x{7F16}\x{7F17}\x{7F18}\x{7F19}' . + '\x{7F1A}\x{7F1B}\x{7F1C}\x{7F1D}\x{7F1E}\x{7F1F}\x{7F20}\x{7F21}\x{7F22}' . + '\x{7F23}\x{7F24}\x{7F25}\x{7F26}\x{7F27}\x{7F28}\x{7F29}\x{7F2A}\x{7F2B}' . + '\x{7F2C}\x{7F2D}\x{7F2E}\x{7F2F}\x{7F30}\x{7F31}\x{7F32}\x{7F33}\x{7F34}' . + '\x{7F35}\x{7F36}\x{7F37}\x{7F38}\x{7F39}\x{7F3A}\x{7F3D}\x{7F3E}\x{7F3F}' . + '\x{7F40}\x{7F42}\x{7F43}\x{7F44}\x{7F45}\x{7F47}\x{7F48}\x{7F49}\x{7F4A}' . + '\x{7F4B}\x{7F4C}\x{7F4D}\x{7F4E}\x{7F4F}\x{7F50}\x{7F51}\x{7F52}\x{7F53}' . + '\x{7F54}\x{7F55}\x{7F56}\x{7F57}\x{7F58}\x{7F5A}\x{7F5B}\x{7F5C}\x{7F5D}' . + '\x{7F5E}\x{7F5F}\x{7F60}\x{7F61}\x{7F62}\x{7F63}\x{7F64}\x{7F65}\x{7F66}' . + '\x{7F67}\x{7F68}\x{7F69}\x{7F6A}\x{7F6B}\x{7F6C}\x{7F6D}\x{7F6E}\x{7F6F}' . + '\x{7F70}\x{7F71}\x{7F72}\x{7F73}\x{7F74}\x{7F75}\x{7F76}\x{7F77}\x{7F78}' . + '\x{7F79}\x{7F7A}\x{7F7B}\x{7F7C}\x{7F7D}\x{7F7E}\x{7F7F}\x{7F80}\x{7F81}' . + '\x{7F82}\x{7F83}\x{7F85}\x{7F86}\x{7F87}\x{7F88}\x{7F89}\x{7F8A}\x{7F8B}' . + '\x{7F8C}\x{7F8D}\x{7F8E}\x{7F8F}\x{7F91}\x{7F92}\x{7F93}\x{7F94}\x{7F95}' . + '\x{7F96}\x{7F98}\x{7F9A}\x{7F9B}\x{7F9C}\x{7F9D}\x{7F9E}\x{7F9F}\x{7FA0}' . + '\x{7FA1}\x{7FA2}\x{7FA3}\x{7FA4}\x{7FA5}\x{7FA6}\x{7FA7}\x{7FA8}\x{7FA9}' . + '\x{7FAA}\x{7FAB}\x{7FAC}\x{7FAD}\x{7FAE}\x{7FAF}\x{7FB0}\x{7FB1}\x{7FB2}' . + '\x{7FB3}\x{7FB5}\x{7FB6}\x{7FB7}\x{7FB8}\x{7FB9}\x{7FBA}\x{7FBB}\x{7FBC}' . + '\x{7FBD}\x{7FBE}\x{7FBF}\x{7FC0}\x{7FC1}\x{7FC2}\x{7FC3}\x{7FC4}\x{7FC5}' . + '\x{7FC6}\x{7FC7}\x{7FC8}\x{7FC9}\x{7FCA}\x{7FCB}\x{7FCC}\x{7FCD}\x{7FCE}' . + '\x{7FCF}\x{7FD0}\x{7FD1}\x{7FD2}\x{7FD3}\x{7FD4}\x{7FD5}\x{7FD7}\x{7FD8}' . + '\x{7FD9}\x{7FDA}\x{7FDB}\x{7FDC}\x{7FDE}\x{7FDF}\x{7FE0}\x{7FE1}\x{7FE2}' . + '\x{7FE3}\x{7FE5}\x{7FE6}\x{7FE7}\x{7FE8}\x{7FE9}\x{7FEA}\x{7FEB}\x{7FEC}' . + '\x{7FED}\x{7FEE}\x{7FEF}\x{7FF0}\x{7FF1}\x{7FF2}\x{7FF3}\x{7FF4}\x{7FF5}' . + '\x{7FF6}\x{7FF7}\x{7FF8}\x{7FF9}\x{7FFA}\x{7FFB}\x{7FFC}\x{7FFD}\x{7FFE}' . + '\x{7FFF}\x{8000}\x{8001}\x{8002}\x{8003}\x{8004}\x{8005}\x{8006}\x{8007}' . + '\x{8008}\x{8009}\x{800B}\x{800C}\x{800D}\x{800E}\x{800F}\x{8010}\x{8011}' . + '\x{8012}\x{8013}\x{8014}\x{8015}\x{8016}\x{8017}\x{8018}\x{8019}\x{801A}' . + '\x{801B}\x{801C}\x{801D}\x{801E}\x{801F}\x{8020}\x{8021}\x{8022}\x{8023}' . + '\x{8024}\x{8025}\x{8026}\x{8027}\x{8028}\x{8029}\x{802A}\x{802B}\x{802C}' . + '\x{802D}\x{802E}\x{8030}\x{8031}\x{8032}\x{8033}\x{8034}\x{8035}\x{8036}' . + '\x{8037}\x{8038}\x{8039}\x{803A}\x{803B}\x{803D}\x{803E}\x{803F}\x{8041}' . + '\x{8042}\x{8043}\x{8044}\x{8045}\x{8046}\x{8047}\x{8048}\x{8049}\x{804A}' . + '\x{804B}\x{804C}\x{804D}\x{804E}\x{804F}\x{8050}\x{8051}\x{8052}\x{8053}' . + '\x{8054}\x{8055}\x{8056}\x{8057}\x{8058}\x{8059}\x{805A}\x{805B}\x{805C}' . + '\x{805D}\x{805E}\x{805F}\x{8060}\x{8061}\x{8062}\x{8063}\x{8064}\x{8065}' . + '\x{8067}\x{8068}\x{8069}\x{806A}\x{806B}\x{806C}\x{806D}\x{806E}\x{806F}' . + '\x{8070}\x{8071}\x{8072}\x{8073}\x{8074}\x{8075}\x{8076}\x{8077}\x{8078}' . + '\x{8079}\x{807A}\x{807B}\x{807C}\x{807D}\x{807E}\x{807F}\x{8080}\x{8081}' . + '\x{8082}\x{8083}\x{8084}\x{8085}\x{8086}\x{8087}\x{8089}\x{808A}\x{808B}' . + '\x{808C}\x{808D}\x{808F}\x{8090}\x{8091}\x{8092}\x{8093}\x{8095}\x{8096}' . + '\x{8097}\x{8098}\x{8099}\x{809A}\x{809B}\x{809C}\x{809D}\x{809E}\x{809F}' . + '\x{80A0}\x{80A1}\x{80A2}\x{80A3}\x{80A4}\x{80A5}\x{80A9}\x{80AA}\x{80AB}' . + '\x{80AD}\x{80AE}\x{80AF}\x{80B0}\x{80B1}\x{80B2}\x{80B4}\x{80B5}\x{80B6}' . + '\x{80B7}\x{80B8}\x{80BA}\x{80BB}\x{80BC}\x{80BD}\x{80BE}\x{80BF}\x{80C0}' . + '\x{80C1}\x{80C2}\x{80C3}\x{80C4}\x{80C5}\x{80C6}\x{80C7}\x{80C8}\x{80C9}' . + '\x{80CA}\x{80CB}\x{80CC}\x{80CD}\x{80CE}\x{80CF}\x{80D0}\x{80D1}\x{80D2}' . + '\x{80D3}\x{80D4}\x{80D5}\x{80D6}\x{80D7}\x{80D8}\x{80D9}\x{80DA}\x{80DB}' . + '\x{80DC}\x{80DD}\x{80DE}\x{80E0}\x{80E1}\x{80E2}\x{80E3}\x{80E4}\x{80E5}' . + '\x{80E6}\x{80E7}\x{80E8}\x{80E9}\x{80EA}\x{80EB}\x{80EC}\x{80ED}\x{80EE}' . + '\x{80EF}\x{80F0}\x{80F1}\x{80F2}\x{80F3}\x{80F4}\x{80F5}\x{80F6}\x{80F7}' . + '\x{80F8}\x{80F9}\x{80FA}\x{80FB}\x{80FC}\x{80FD}\x{80FE}\x{80FF}\x{8100}' . + '\x{8101}\x{8102}\x{8105}\x{8106}\x{8107}\x{8108}\x{8109}\x{810A}\x{810B}' . + '\x{810C}\x{810D}\x{810E}\x{810F}\x{8110}\x{8111}\x{8112}\x{8113}\x{8114}' . + '\x{8115}\x{8116}\x{8118}\x{8119}\x{811A}\x{811B}\x{811C}\x{811D}\x{811E}' . + '\x{811F}\x{8120}\x{8121}\x{8122}\x{8123}\x{8124}\x{8125}\x{8126}\x{8127}' . + '\x{8128}\x{8129}\x{812A}\x{812B}\x{812C}\x{812D}\x{812E}\x{812F}\x{8130}' . + '\x{8131}\x{8132}\x{8136}\x{8137}\x{8138}\x{8139}\x{813A}\x{813B}\x{813C}' . + '\x{813D}\x{813E}\x{813F}\x{8140}\x{8141}\x{8142}\x{8143}\x{8144}\x{8145}' . + '\x{8146}\x{8147}\x{8148}\x{8149}\x{814A}\x{814B}\x{814C}\x{814D}\x{814E}' . + '\x{814F}\x{8150}\x{8151}\x{8152}\x{8153}\x{8154}\x{8155}\x{8156}\x{8157}' . + '\x{8158}\x{8159}\x{815A}\x{815B}\x{815C}\x{815D}\x{815E}\x{8160}\x{8161}' . + '\x{8162}\x{8163}\x{8164}\x{8165}\x{8166}\x{8167}\x{8168}\x{8169}\x{816A}' . + '\x{816B}\x{816C}\x{816D}\x{816E}\x{816F}\x{8170}\x{8171}\x{8172}\x{8173}' . + '\x{8174}\x{8175}\x{8176}\x{8177}\x{8178}\x{8179}\x{817A}\x{817B}\x{817C}' . + '\x{817D}\x{817E}\x{817F}\x{8180}\x{8181}\x{8182}\x{8183}\x{8185}\x{8186}' . + '\x{8187}\x{8188}\x{8189}\x{818A}\x{818B}\x{818C}\x{818D}\x{818E}\x{818F}' . + '\x{8191}\x{8192}\x{8193}\x{8194}\x{8195}\x{8197}\x{8198}\x{8199}\x{819A}' . + '\x{819B}\x{819C}\x{819D}\x{819E}\x{819F}\x{81A0}\x{81A1}\x{81A2}\x{81A3}' . + '\x{81A4}\x{81A5}\x{81A6}\x{81A7}\x{81A8}\x{81A9}\x{81AA}\x{81AB}\x{81AC}' . + '\x{81AD}\x{81AE}\x{81AF}\x{81B0}\x{81B1}\x{81B2}\x{81B3}\x{81B4}\x{81B5}' . + '\x{81B6}\x{81B7}\x{81B8}\x{81B9}\x{81BA}\x{81BB}\x{81BC}\x{81BD}\x{81BE}' . + '\x{81BF}\x{81C0}\x{81C1}\x{81C2}\x{81C3}\x{81C4}\x{81C5}\x{81C6}\x{81C7}' . + '\x{81C8}\x{81C9}\x{81CA}\x{81CC}\x{81CD}\x{81CE}\x{81CF}\x{81D0}\x{81D1}' . + '\x{81D2}\x{81D4}\x{81D5}\x{81D6}\x{81D7}\x{81D8}\x{81D9}\x{81DA}\x{81DB}' . + '\x{81DC}\x{81DD}\x{81DE}\x{81DF}\x{81E0}\x{81E1}\x{81E2}\x{81E3}\x{81E5}' . + '\x{81E6}\x{81E7}\x{81E8}\x{81E9}\x{81EA}\x{81EB}\x{81EC}\x{81ED}\x{81EE}' . + '\x{81F1}\x{81F2}\x{81F3}\x{81F4}\x{81F5}\x{81F6}\x{81F7}\x{81F8}\x{81F9}' . + '\x{81FA}\x{81FB}\x{81FC}\x{81FD}\x{81FE}\x{81FF}\x{8200}\x{8201}\x{8202}' . + '\x{8203}\x{8204}\x{8205}\x{8206}\x{8207}\x{8208}\x{8209}\x{820A}\x{820B}' . + '\x{820C}\x{820D}\x{820E}\x{820F}\x{8210}\x{8211}\x{8212}\x{8214}\x{8215}' . + '\x{8216}\x{8218}\x{8219}\x{821A}\x{821B}\x{821C}\x{821D}\x{821E}\x{821F}' . + '\x{8220}\x{8221}\x{8222}\x{8223}\x{8225}\x{8226}\x{8227}\x{8228}\x{8229}' . + '\x{822A}\x{822B}\x{822C}\x{822D}\x{822F}\x{8230}\x{8231}\x{8232}\x{8233}' . + '\x{8234}\x{8235}\x{8236}\x{8237}\x{8238}\x{8239}\x{823A}\x{823B}\x{823C}' . + '\x{823D}\x{823E}\x{823F}\x{8240}\x{8242}\x{8243}\x{8244}\x{8245}\x{8246}' . + '\x{8247}\x{8248}\x{8249}\x{824A}\x{824B}\x{824C}\x{824D}\x{824E}\x{824F}' . + '\x{8250}\x{8251}\x{8252}\x{8253}\x{8254}\x{8255}\x{8256}\x{8257}\x{8258}' . + '\x{8259}\x{825A}\x{825B}\x{825C}\x{825D}\x{825E}\x{825F}\x{8260}\x{8261}' . + '\x{8263}\x{8264}\x{8266}\x{8267}\x{8268}\x{8269}\x{826A}\x{826B}\x{826C}' . + '\x{826D}\x{826E}\x{826F}\x{8270}\x{8271}\x{8272}\x{8273}\x{8274}\x{8275}' . + '\x{8276}\x{8277}\x{8278}\x{8279}\x{827A}\x{827B}\x{827C}\x{827D}\x{827E}' . + '\x{827F}\x{8280}\x{8281}\x{8282}\x{8283}\x{8284}\x{8285}\x{8286}\x{8287}' . + '\x{8288}\x{8289}\x{828A}\x{828B}\x{828D}\x{828E}\x{828F}\x{8290}\x{8291}' . + '\x{8292}\x{8293}\x{8294}\x{8295}\x{8296}\x{8297}\x{8298}\x{8299}\x{829A}' . + '\x{829B}\x{829C}\x{829D}\x{829E}\x{829F}\x{82A0}\x{82A1}\x{82A2}\x{82A3}' . + '\x{82A4}\x{82A5}\x{82A6}\x{82A7}\x{82A8}\x{82A9}\x{82AA}\x{82AB}\x{82AC}' . + '\x{82AD}\x{82AE}\x{82AF}\x{82B0}\x{82B1}\x{82B3}\x{82B4}\x{82B5}\x{82B6}' . + '\x{82B7}\x{82B8}\x{82B9}\x{82BA}\x{82BB}\x{82BC}\x{82BD}\x{82BE}\x{82BF}' . + '\x{82C0}\x{82C1}\x{82C2}\x{82C3}\x{82C4}\x{82C5}\x{82C6}\x{82C7}\x{82C8}' . + '\x{82C9}\x{82CA}\x{82CB}\x{82CC}\x{82CD}\x{82CE}\x{82CF}\x{82D0}\x{82D1}' . + '\x{82D2}\x{82D3}\x{82D4}\x{82D5}\x{82D6}\x{82D7}\x{82D8}\x{82D9}\x{82DA}' . + '\x{82DB}\x{82DC}\x{82DD}\x{82DE}\x{82DF}\x{82E0}\x{82E1}\x{82E3}\x{82E4}' . + '\x{82E5}\x{82E6}\x{82E7}\x{82E8}\x{82E9}\x{82EA}\x{82EB}\x{82EC}\x{82ED}' . + '\x{82EE}\x{82EF}\x{82F0}\x{82F1}\x{82F2}\x{82F3}\x{82F4}\x{82F5}\x{82F6}' . + '\x{82F7}\x{82F8}\x{82F9}\x{82FA}\x{82FB}\x{82FD}\x{82FE}\x{82FF}\x{8300}' . + '\x{8301}\x{8302}\x{8303}\x{8304}\x{8305}\x{8306}\x{8307}\x{8308}\x{8309}' . + '\x{830B}\x{830C}\x{830D}\x{830E}\x{830F}\x{8311}\x{8312}\x{8313}\x{8314}' . + '\x{8315}\x{8316}\x{8317}\x{8318}\x{8319}\x{831A}\x{831B}\x{831C}\x{831D}' . + '\x{831E}\x{831F}\x{8320}\x{8321}\x{8322}\x{8323}\x{8324}\x{8325}\x{8326}' . + '\x{8327}\x{8328}\x{8329}\x{832A}\x{832B}\x{832C}\x{832D}\x{832E}\x{832F}' . + '\x{8331}\x{8332}\x{8333}\x{8334}\x{8335}\x{8336}\x{8337}\x{8338}\x{8339}' . + '\x{833A}\x{833B}\x{833C}\x{833D}\x{833E}\x{833F}\x{8340}\x{8341}\x{8342}' . + '\x{8343}\x{8344}\x{8345}\x{8346}\x{8347}\x{8348}\x{8349}\x{834A}\x{834B}' . + '\x{834C}\x{834D}\x{834E}\x{834F}\x{8350}\x{8351}\x{8352}\x{8353}\x{8354}' . + '\x{8356}\x{8357}\x{8358}\x{8359}\x{835A}\x{835B}\x{835C}\x{835D}\x{835E}' . + '\x{835F}\x{8360}\x{8361}\x{8362}\x{8363}\x{8364}\x{8365}\x{8366}\x{8367}' . + '\x{8368}\x{8369}\x{836A}\x{836B}\x{836C}\x{836D}\x{836E}\x{836F}\x{8370}' . + '\x{8371}\x{8372}\x{8373}\x{8374}\x{8375}\x{8376}\x{8377}\x{8378}\x{8379}' . + '\x{837A}\x{837B}\x{837C}\x{837D}\x{837E}\x{837F}\x{8380}\x{8381}\x{8382}' . + '\x{8383}\x{8384}\x{8385}\x{8386}\x{8387}\x{8388}\x{8389}\x{838A}\x{838B}' . + '\x{838C}\x{838D}\x{838E}\x{838F}\x{8390}\x{8391}\x{8392}\x{8393}\x{8394}' . + '\x{8395}\x{8396}\x{8397}\x{8398}\x{8399}\x{839A}\x{839B}\x{839C}\x{839D}' . + '\x{839E}\x{83A0}\x{83A1}\x{83A2}\x{83A3}\x{83A4}\x{83A5}\x{83A6}\x{83A7}' . + '\x{83A8}\x{83A9}\x{83AA}\x{83AB}\x{83AC}\x{83AD}\x{83AE}\x{83AF}\x{83B0}' . + '\x{83B1}\x{83B2}\x{83B3}\x{83B4}\x{83B6}\x{83B7}\x{83B8}\x{83B9}\x{83BA}' . + '\x{83BB}\x{83BC}\x{83BD}\x{83BF}\x{83C0}\x{83C1}\x{83C2}\x{83C3}\x{83C4}' . + '\x{83C5}\x{83C6}\x{83C7}\x{83C8}\x{83C9}\x{83CA}\x{83CB}\x{83CC}\x{83CD}' . + '\x{83CE}\x{83CF}\x{83D0}\x{83D1}\x{83D2}\x{83D3}\x{83D4}\x{83D5}\x{83D6}' . + '\x{83D7}\x{83D8}\x{83D9}\x{83DA}\x{83DB}\x{83DC}\x{83DD}\x{83DE}\x{83DF}' . + '\x{83E0}\x{83E1}\x{83E2}\x{83E3}\x{83E4}\x{83E5}\x{83E7}\x{83E8}\x{83E9}' . + '\x{83EA}\x{83EB}\x{83EC}\x{83EE}\x{83EF}\x{83F0}\x{83F1}\x{83F2}\x{83F3}' . + '\x{83F4}\x{83F5}\x{83F6}\x{83F7}\x{83F8}\x{83F9}\x{83FA}\x{83FB}\x{83FC}' . + '\x{83FD}\x{83FE}\x{83FF}\x{8400}\x{8401}\x{8402}\x{8403}\x{8404}\x{8405}' . + '\x{8406}\x{8407}\x{8408}\x{8409}\x{840A}\x{840B}\x{840C}\x{840D}\x{840E}' . + '\x{840F}\x{8410}\x{8411}\x{8412}\x{8413}\x{8415}\x{8418}\x{8419}\x{841A}' . + '\x{841B}\x{841C}\x{841D}\x{841E}\x{8421}\x{8422}\x{8423}\x{8424}\x{8425}' . + '\x{8426}\x{8427}\x{8428}\x{8429}\x{842A}\x{842B}\x{842C}\x{842D}\x{842E}' . + '\x{842F}\x{8430}\x{8431}\x{8432}\x{8433}\x{8434}\x{8435}\x{8436}\x{8437}' . + '\x{8438}\x{8439}\x{843A}\x{843B}\x{843C}\x{843D}\x{843E}\x{843F}\x{8440}' . + '\x{8441}\x{8442}\x{8443}\x{8444}\x{8445}\x{8446}\x{8447}\x{8448}\x{8449}' . + '\x{844A}\x{844B}\x{844C}\x{844D}\x{844E}\x{844F}\x{8450}\x{8451}\x{8452}' . + '\x{8453}\x{8454}\x{8455}\x{8456}\x{8457}\x{8459}\x{845A}\x{845B}\x{845C}' . + '\x{845D}\x{845E}\x{845F}\x{8460}\x{8461}\x{8462}\x{8463}\x{8464}\x{8465}' . + '\x{8466}\x{8467}\x{8468}\x{8469}\x{846A}\x{846B}\x{846C}\x{846D}\x{846E}' . + '\x{846F}\x{8470}\x{8471}\x{8472}\x{8473}\x{8474}\x{8475}\x{8476}\x{8477}' . + '\x{8478}\x{8479}\x{847A}\x{847B}\x{847C}\x{847D}\x{847E}\x{847F}\x{8480}' . + '\x{8481}\x{8482}\x{8484}\x{8485}\x{8486}\x{8487}\x{8488}\x{8489}\x{848A}' . + '\x{848B}\x{848C}\x{848D}\x{848E}\x{848F}\x{8490}\x{8491}\x{8492}\x{8493}' . + '\x{8494}\x{8496}\x{8497}\x{8498}\x{8499}\x{849A}\x{849B}\x{849C}\x{849D}' . + '\x{849E}\x{849F}\x{84A0}\x{84A1}\x{84A2}\x{84A3}\x{84A4}\x{84A5}\x{84A6}' . + '\x{84A7}\x{84A8}\x{84A9}\x{84AA}\x{84AB}\x{84AC}\x{84AE}\x{84AF}\x{84B0}' . + '\x{84B1}\x{84B2}\x{84B3}\x{84B4}\x{84B5}\x{84B6}\x{84B8}\x{84B9}\x{84BA}' . + '\x{84BB}\x{84BC}\x{84BD}\x{84BE}\x{84BF}\x{84C0}\x{84C1}\x{84C2}\x{84C4}' . + '\x{84C5}\x{84C6}\x{84C7}\x{84C8}\x{84C9}\x{84CA}\x{84CB}\x{84CC}\x{84CD}' . + '\x{84CE}\x{84CF}\x{84D0}\x{84D1}\x{84D2}\x{84D3}\x{84D4}\x{84D5}\x{84D6}' . + '\x{84D7}\x{84D8}\x{84D9}\x{84DB}\x{84DC}\x{84DD}\x{84DE}\x{84DF}\x{84E0}' . + '\x{84E1}\x{84E2}\x{84E3}\x{84E4}\x{84E5}\x{84E6}\x{84E7}\x{84E8}\x{84E9}' . + '\x{84EA}\x{84EB}\x{84EC}\x{84EE}\x{84EF}\x{84F0}\x{84F1}\x{84F2}\x{84F3}' . + '\x{84F4}\x{84F5}\x{84F6}\x{84F7}\x{84F8}\x{84F9}\x{84FA}\x{84FB}\x{84FC}' . + '\x{84FD}\x{84FE}\x{84FF}\x{8500}\x{8501}\x{8502}\x{8503}\x{8504}\x{8506}' . + '\x{8507}\x{8508}\x{8509}\x{850A}\x{850B}\x{850C}\x{850D}\x{850E}\x{850F}' . + '\x{8511}\x{8512}\x{8513}\x{8514}\x{8515}\x{8516}\x{8517}\x{8518}\x{8519}' . + '\x{851A}\x{851B}\x{851C}\x{851D}\x{851E}\x{851F}\x{8520}\x{8521}\x{8522}' . + '\x{8523}\x{8524}\x{8525}\x{8526}\x{8527}\x{8528}\x{8529}\x{852A}\x{852B}' . + '\x{852C}\x{852D}\x{852E}\x{852F}\x{8530}\x{8531}\x{8534}\x{8535}\x{8536}' . + '\x{8537}\x{8538}\x{8539}\x{853A}\x{853B}\x{853C}\x{853D}\x{853E}\x{853F}' . + '\x{8540}\x{8541}\x{8542}\x{8543}\x{8544}\x{8545}\x{8546}\x{8547}\x{8548}' . + '\x{8549}\x{854A}\x{854B}\x{854D}\x{854E}\x{854F}\x{8551}\x{8552}\x{8553}' . + '\x{8554}\x{8555}\x{8556}\x{8557}\x{8558}\x{8559}\x{855A}\x{855B}\x{855C}' . + '\x{855D}\x{855E}\x{855F}\x{8560}\x{8561}\x{8562}\x{8563}\x{8564}\x{8565}' . + '\x{8566}\x{8567}\x{8568}\x{8569}\x{856A}\x{856B}\x{856C}\x{856D}\x{856E}' . + '\x{856F}\x{8570}\x{8571}\x{8572}\x{8573}\x{8574}\x{8575}\x{8576}\x{8577}' . + '\x{8578}\x{8579}\x{857A}\x{857B}\x{857C}\x{857D}\x{857E}\x{8580}\x{8581}' . + '\x{8582}\x{8583}\x{8584}\x{8585}\x{8586}\x{8587}\x{8588}\x{8589}\x{858A}' . + '\x{858B}\x{858C}\x{858D}\x{858E}\x{858F}\x{8590}\x{8591}\x{8592}\x{8594}' . + '\x{8595}\x{8596}\x{8598}\x{8599}\x{859A}\x{859B}\x{859C}\x{859D}\x{859E}' . + '\x{859F}\x{85A0}\x{85A1}\x{85A2}\x{85A3}\x{85A4}\x{85A5}\x{85A6}\x{85A7}' . + '\x{85A8}\x{85A9}\x{85AA}\x{85AB}\x{85AC}\x{85AD}\x{85AE}\x{85AF}\x{85B0}' . + '\x{85B1}\x{85B3}\x{85B4}\x{85B5}\x{85B6}\x{85B7}\x{85B8}\x{85B9}\x{85BA}' . + '\x{85BC}\x{85BD}\x{85BE}\x{85BF}\x{85C0}\x{85C1}\x{85C2}\x{85C3}\x{85C4}' . + '\x{85C5}\x{85C6}\x{85C7}\x{85C8}\x{85C9}\x{85CA}\x{85CB}\x{85CD}\x{85CE}' . + '\x{85CF}\x{85D0}\x{85D1}\x{85D2}\x{85D3}\x{85D4}\x{85D5}\x{85D6}\x{85D7}' . + '\x{85D8}\x{85D9}\x{85DA}\x{85DB}\x{85DC}\x{85DD}\x{85DE}\x{85DF}\x{85E0}' . + '\x{85E1}\x{85E2}\x{85E3}\x{85E4}\x{85E5}\x{85E6}\x{85E7}\x{85E8}\x{85E9}' . + '\x{85EA}\x{85EB}\x{85EC}\x{85ED}\x{85EF}\x{85F0}\x{85F1}\x{85F2}\x{85F4}' . + '\x{85F5}\x{85F6}\x{85F7}\x{85F8}\x{85F9}\x{85FA}\x{85FB}\x{85FD}\x{85FE}' . + '\x{85FF}\x{8600}\x{8601}\x{8602}\x{8604}\x{8605}\x{8606}\x{8607}\x{8608}' . + '\x{8609}\x{860A}\x{860B}\x{860C}\x{860F}\x{8611}\x{8612}\x{8613}\x{8614}' . + '\x{8616}\x{8617}\x{8618}\x{8619}\x{861A}\x{861B}\x{861C}\x{861E}\x{861F}' . + '\x{8620}\x{8621}\x{8622}\x{8623}\x{8624}\x{8625}\x{8626}\x{8627}\x{8628}' . + '\x{8629}\x{862A}\x{862B}\x{862C}\x{862D}\x{862E}\x{862F}\x{8630}\x{8631}' . + '\x{8632}\x{8633}\x{8634}\x{8635}\x{8636}\x{8638}\x{8639}\x{863A}\x{863B}' . + '\x{863C}\x{863D}\x{863E}\x{863F}\x{8640}\x{8641}\x{8642}\x{8643}\x{8644}' . + '\x{8645}\x{8646}\x{8647}\x{8648}\x{8649}\x{864A}\x{864B}\x{864C}\x{864D}' . + '\x{864E}\x{864F}\x{8650}\x{8651}\x{8652}\x{8653}\x{8654}\x{8655}\x{8656}' . + '\x{8658}\x{8659}\x{865A}\x{865B}\x{865C}\x{865D}\x{865E}\x{865F}\x{8660}' . + '\x{8661}\x{8662}\x{8663}\x{8664}\x{8665}\x{8666}\x{8667}\x{8668}\x{8669}' . + '\x{866A}\x{866B}\x{866C}\x{866D}\x{866E}\x{866F}\x{8670}\x{8671}\x{8672}' . + '\x{8673}\x{8674}\x{8676}\x{8677}\x{8678}\x{8679}\x{867A}\x{867B}\x{867C}' . + '\x{867D}\x{867E}\x{867F}\x{8680}\x{8681}\x{8682}\x{8683}\x{8684}\x{8685}' . + '\x{8686}\x{8687}\x{8688}\x{868A}\x{868B}\x{868C}\x{868D}\x{868E}\x{868F}' . + '\x{8690}\x{8691}\x{8693}\x{8694}\x{8695}\x{8696}\x{8697}\x{8698}\x{8699}' . + '\x{869A}\x{869B}\x{869C}\x{869D}\x{869E}\x{869F}\x{86A1}\x{86A2}\x{86A3}' . + '\x{86A4}\x{86A5}\x{86A7}\x{86A8}\x{86A9}\x{86AA}\x{86AB}\x{86AC}\x{86AD}' . + '\x{86AE}\x{86AF}\x{86B0}\x{86B1}\x{86B2}\x{86B3}\x{86B4}\x{86B5}\x{86B6}' . + '\x{86B7}\x{86B8}\x{86B9}\x{86BA}\x{86BB}\x{86BC}\x{86BD}\x{86BE}\x{86BF}' . + '\x{86C0}\x{86C1}\x{86C2}\x{86C3}\x{86C4}\x{86C5}\x{86C6}\x{86C7}\x{86C8}' . + '\x{86C9}\x{86CA}\x{86CB}\x{86CC}\x{86CE}\x{86CF}\x{86D0}\x{86D1}\x{86D2}' . + '\x{86D3}\x{86D4}\x{86D6}\x{86D7}\x{86D8}\x{86D9}\x{86DA}\x{86DB}\x{86DC}' . + '\x{86DD}\x{86DE}\x{86DF}\x{86E1}\x{86E2}\x{86E3}\x{86E4}\x{86E5}\x{86E6}' . + '\x{86E8}\x{86E9}\x{86EA}\x{86EB}\x{86EC}\x{86ED}\x{86EE}\x{86EF}\x{86F0}' . + '\x{86F1}\x{86F2}\x{86F3}\x{86F4}\x{86F5}\x{86F6}\x{86F7}\x{86F8}\x{86F9}' . + '\x{86FA}\x{86FB}\x{86FC}\x{86FE}\x{86FF}\x{8700}\x{8701}\x{8702}\x{8703}' . + '\x{8704}\x{8705}\x{8706}\x{8707}\x{8708}\x{8709}\x{870A}\x{870B}\x{870C}' . + '\x{870D}\x{870E}\x{870F}\x{8710}\x{8711}\x{8712}\x{8713}\x{8714}\x{8715}' . + '\x{8716}\x{8717}\x{8718}\x{8719}\x{871A}\x{871B}\x{871C}\x{871E}\x{871F}' . + '\x{8720}\x{8721}\x{8722}\x{8723}\x{8724}\x{8725}\x{8726}\x{8727}\x{8728}' . + '\x{8729}\x{872A}\x{872B}\x{872C}\x{872D}\x{872E}\x{8730}\x{8731}\x{8732}' . + '\x{8733}\x{8734}\x{8735}\x{8736}\x{8737}\x{8738}\x{8739}\x{873A}\x{873B}' . + '\x{873C}\x{873E}\x{873F}\x{8740}\x{8741}\x{8742}\x{8743}\x{8744}\x{8746}' . + '\x{8747}\x{8748}\x{8749}\x{874A}\x{874C}\x{874D}\x{874E}\x{874F}\x{8750}' . + '\x{8751}\x{8752}\x{8753}\x{8754}\x{8755}\x{8756}\x{8757}\x{8758}\x{8759}' . + '\x{875A}\x{875B}\x{875C}\x{875D}\x{875E}\x{875F}\x{8760}\x{8761}\x{8762}' . + '\x{8763}\x{8764}\x{8765}\x{8766}\x{8767}\x{8768}\x{8769}\x{876A}\x{876B}' . + '\x{876C}\x{876D}\x{876E}\x{876F}\x{8770}\x{8772}\x{8773}\x{8774}\x{8775}' . + '\x{8776}\x{8777}\x{8778}\x{8779}\x{877A}\x{877B}\x{877C}\x{877D}\x{877E}' . + '\x{8780}\x{8781}\x{8782}\x{8783}\x{8784}\x{8785}\x{8786}\x{8787}\x{8788}' . + '\x{8789}\x{878A}\x{878B}\x{878C}\x{878D}\x{878F}\x{8790}\x{8791}\x{8792}' . + '\x{8793}\x{8794}\x{8795}\x{8796}\x{8797}\x{8798}\x{879A}\x{879B}\x{879C}' . + '\x{879D}\x{879E}\x{879F}\x{87A0}\x{87A1}\x{87A2}\x{87A3}\x{87A4}\x{87A5}' . + '\x{87A6}\x{87A7}\x{87A8}\x{87A9}\x{87AA}\x{87AB}\x{87AC}\x{87AD}\x{87AE}' . + '\x{87AF}\x{87B0}\x{87B1}\x{87B2}\x{87B3}\x{87B4}\x{87B5}\x{87B6}\x{87B7}' . + '\x{87B8}\x{87B9}\x{87BA}\x{87BB}\x{87BC}\x{87BD}\x{87BE}\x{87BF}\x{87C0}' . + '\x{87C1}\x{87C2}\x{87C3}\x{87C4}\x{87C5}\x{87C6}\x{87C7}\x{87C8}\x{87C9}' . + '\x{87CA}\x{87CB}\x{87CC}\x{87CD}\x{87CE}\x{87CF}\x{87D0}\x{87D1}\x{87D2}' . + '\x{87D3}\x{87D4}\x{87D5}\x{87D6}\x{87D7}\x{87D8}\x{87D9}\x{87DB}\x{87DC}' . + '\x{87DD}\x{87DE}\x{87DF}\x{87E0}\x{87E1}\x{87E2}\x{87E3}\x{87E4}\x{87E5}' . + '\x{87E6}\x{87E7}\x{87E8}\x{87E9}\x{87EA}\x{87EB}\x{87EC}\x{87ED}\x{87EE}' . + '\x{87EF}\x{87F1}\x{87F2}\x{87F3}\x{87F4}\x{87F5}\x{87F6}\x{87F7}\x{87F8}' . + '\x{87F9}\x{87FA}\x{87FB}\x{87FC}\x{87FD}\x{87FE}\x{87FF}\x{8800}\x{8801}' . + '\x{8802}\x{8803}\x{8804}\x{8805}\x{8806}\x{8808}\x{8809}\x{880A}\x{880B}' . + '\x{880C}\x{880D}\x{880E}\x{880F}\x{8810}\x{8811}\x{8813}\x{8814}\x{8815}' . + '\x{8816}\x{8817}\x{8818}\x{8819}\x{881A}\x{881B}\x{881C}\x{881D}\x{881E}' . + '\x{881F}\x{8820}\x{8821}\x{8822}\x{8823}\x{8824}\x{8825}\x{8826}\x{8827}' . + '\x{8828}\x{8829}\x{882A}\x{882B}\x{882C}\x{882E}\x{882F}\x{8830}\x{8831}' . + '\x{8832}\x{8833}\x{8834}\x{8835}\x{8836}\x{8837}\x{8838}\x{8839}\x{883B}' . + '\x{883C}\x{883D}\x{883E}\x{883F}\x{8840}\x{8841}\x{8842}\x{8843}\x{8844}' . + '\x{8845}\x{8846}\x{8848}\x{8849}\x{884A}\x{884B}\x{884C}\x{884D}\x{884E}' . + '\x{884F}\x{8850}\x{8851}\x{8852}\x{8853}\x{8854}\x{8855}\x{8856}\x{8857}' . + '\x{8859}\x{885A}\x{885B}\x{885D}\x{885E}\x{8860}\x{8861}\x{8862}\x{8863}' . + '\x{8864}\x{8865}\x{8866}\x{8867}\x{8868}\x{8869}\x{886A}\x{886B}\x{886C}' . + '\x{886D}\x{886E}\x{886F}\x{8870}\x{8871}\x{8872}\x{8873}\x{8874}\x{8875}' . + '\x{8876}\x{8877}\x{8878}\x{8879}\x{887B}\x{887C}\x{887D}\x{887E}\x{887F}' . + '\x{8880}\x{8881}\x{8882}\x{8883}\x{8884}\x{8885}\x{8886}\x{8887}\x{8888}' . + '\x{8889}\x{888A}\x{888B}\x{888C}\x{888D}\x{888E}\x{888F}\x{8890}\x{8891}' . + '\x{8892}\x{8893}\x{8894}\x{8895}\x{8896}\x{8897}\x{8898}\x{8899}\x{889A}' . + '\x{889B}\x{889C}\x{889D}\x{889E}\x{889F}\x{88A0}\x{88A1}\x{88A2}\x{88A3}' . + '\x{88A4}\x{88A5}\x{88A6}\x{88A7}\x{88A8}\x{88A9}\x{88AA}\x{88AB}\x{88AC}' . + '\x{88AD}\x{88AE}\x{88AF}\x{88B0}\x{88B1}\x{88B2}\x{88B3}\x{88B4}\x{88B6}' . + '\x{88B7}\x{88B8}\x{88B9}\x{88BA}\x{88BB}\x{88BC}\x{88BD}\x{88BE}\x{88BF}' . + '\x{88C0}\x{88C1}\x{88C2}\x{88C3}\x{88C4}\x{88C5}\x{88C6}\x{88C7}\x{88C8}' . + '\x{88C9}\x{88CA}\x{88CB}\x{88CC}\x{88CD}\x{88CE}\x{88CF}\x{88D0}\x{88D1}' . + '\x{88D2}\x{88D3}\x{88D4}\x{88D5}\x{88D6}\x{88D7}\x{88D8}\x{88D9}\x{88DA}' . + '\x{88DB}\x{88DC}\x{88DD}\x{88DE}\x{88DF}\x{88E0}\x{88E1}\x{88E2}\x{88E3}' . + '\x{88E4}\x{88E5}\x{88E7}\x{88E8}\x{88EA}\x{88EB}\x{88EC}\x{88EE}\x{88EF}' . + '\x{88F0}\x{88F1}\x{88F2}\x{88F3}\x{88F4}\x{88F5}\x{88F6}\x{88F7}\x{88F8}' . + '\x{88F9}\x{88FA}\x{88FB}\x{88FC}\x{88FD}\x{88FE}\x{88FF}\x{8900}\x{8901}' . + '\x{8902}\x{8904}\x{8905}\x{8906}\x{8907}\x{8908}\x{8909}\x{890A}\x{890B}' . + '\x{890C}\x{890D}\x{890E}\x{8910}\x{8911}\x{8912}\x{8913}\x{8914}\x{8915}' . + '\x{8916}\x{8917}\x{8918}\x{8919}\x{891A}\x{891B}\x{891C}\x{891D}\x{891E}' . + '\x{891F}\x{8920}\x{8921}\x{8922}\x{8923}\x{8925}\x{8926}\x{8927}\x{8928}' . + '\x{8929}\x{892A}\x{892B}\x{892C}\x{892D}\x{892E}\x{892F}\x{8930}\x{8931}' . + '\x{8932}\x{8933}\x{8934}\x{8935}\x{8936}\x{8937}\x{8938}\x{8939}\x{893A}' . + '\x{893B}\x{893C}\x{893D}\x{893E}\x{893F}\x{8940}\x{8941}\x{8942}\x{8943}' . + '\x{8944}\x{8945}\x{8946}\x{8947}\x{8948}\x{8949}\x{894A}\x{894B}\x{894C}' . + '\x{894E}\x{894F}\x{8950}\x{8951}\x{8952}\x{8953}\x{8954}\x{8955}\x{8956}' . + '\x{8957}\x{8958}\x{8959}\x{895A}\x{895B}\x{895C}\x{895D}\x{895E}\x{895F}' . + '\x{8960}\x{8961}\x{8962}\x{8963}\x{8964}\x{8966}\x{8967}\x{8968}\x{8969}' . + '\x{896A}\x{896B}\x{896C}\x{896D}\x{896E}\x{896F}\x{8970}\x{8971}\x{8972}' . + '\x{8973}\x{8974}\x{8976}\x{8977}\x{8978}\x{8979}\x{897A}\x{897B}\x{897C}' . + '\x{897E}\x{897F}\x{8980}\x{8981}\x{8982}\x{8983}\x{8984}\x{8985}\x{8986}' . + '\x{8987}\x{8988}\x{8989}\x{898A}\x{898B}\x{898C}\x{898E}\x{898F}\x{8991}' . + '\x{8992}\x{8993}\x{8995}\x{8996}\x{8997}\x{8998}\x{899A}\x{899B}\x{899C}' . + '\x{899D}\x{899E}\x{899F}\x{89A0}\x{89A1}\x{89A2}\x{89A3}\x{89A4}\x{89A5}' . + '\x{89A6}\x{89A7}\x{89A8}\x{89AA}\x{89AB}\x{89AC}\x{89AD}\x{89AE}\x{89AF}' . + '\x{89B1}\x{89B2}\x{89B3}\x{89B5}\x{89B6}\x{89B7}\x{89B8}\x{89B9}\x{89BA}' . + '\x{89BD}\x{89BE}\x{89BF}\x{89C0}\x{89C1}\x{89C2}\x{89C3}\x{89C4}\x{89C5}' . + '\x{89C6}\x{89C7}\x{89C8}\x{89C9}\x{89CA}\x{89CB}\x{89CC}\x{89CD}\x{89CE}' . + '\x{89CF}\x{89D0}\x{89D1}\x{89D2}\x{89D3}\x{89D4}\x{89D5}\x{89D6}\x{89D7}' . + '\x{89D8}\x{89D9}\x{89DA}\x{89DB}\x{89DC}\x{89DD}\x{89DE}\x{89DF}\x{89E0}' . + '\x{89E1}\x{89E2}\x{89E3}\x{89E4}\x{89E5}\x{89E6}\x{89E7}\x{89E8}\x{89E9}' . + '\x{89EA}\x{89EB}\x{89EC}\x{89ED}\x{89EF}\x{89F0}\x{89F1}\x{89F2}\x{89F3}' . + '\x{89F4}\x{89F6}\x{89F7}\x{89F8}\x{89FA}\x{89FB}\x{89FC}\x{89FE}\x{89FF}' . + '\x{8A00}\x{8A01}\x{8A02}\x{8A03}\x{8A04}\x{8A07}\x{8A08}\x{8A09}\x{8A0A}' . + '\x{8A0B}\x{8A0C}\x{8A0D}\x{8A0E}\x{8A0F}\x{8A10}\x{8A11}\x{8A12}\x{8A13}' . + '\x{8A15}\x{8A16}\x{8A17}\x{8A18}\x{8A1A}\x{8A1B}\x{8A1C}\x{8A1D}\x{8A1E}' . + '\x{8A1F}\x{8A22}\x{8A23}\x{8A24}\x{8A25}\x{8A26}\x{8A27}\x{8A28}\x{8A29}' . + '\x{8A2A}\x{8A2C}\x{8A2D}\x{8A2E}\x{8A2F}\x{8A30}\x{8A31}\x{8A32}\x{8A34}' . + '\x{8A35}\x{8A36}\x{8A37}\x{8A38}\x{8A39}\x{8A3A}\x{8A3B}\x{8A3C}\x{8A3E}' . + '\x{8A3F}\x{8A40}\x{8A41}\x{8A42}\x{8A43}\x{8A44}\x{8A45}\x{8A46}\x{8A47}' . + '\x{8A48}\x{8A49}\x{8A4A}\x{8A4C}\x{8A4D}\x{8A4E}\x{8A4F}\x{8A50}\x{8A51}' . + '\x{8A52}\x{8A53}\x{8A54}\x{8A55}\x{8A56}\x{8A57}\x{8A58}\x{8A59}\x{8A5A}' . + '\x{8A5B}\x{8A5C}\x{8A5D}\x{8A5E}\x{8A5F}\x{8A60}\x{8A61}\x{8A62}\x{8A63}' . + '\x{8A65}\x{8A66}\x{8A67}\x{8A68}\x{8A69}\x{8A6A}\x{8A6B}\x{8A6C}\x{8A6D}' . + '\x{8A6E}\x{8A6F}\x{8A70}\x{8A71}\x{8A72}\x{8A73}\x{8A74}\x{8A75}\x{8A76}' . + '\x{8A77}\x{8A79}\x{8A7A}\x{8A7B}\x{8A7C}\x{8A7E}\x{8A7F}\x{8A80}\x{8A81}' . + '\x{8A82}\x{8A83}\x{8A84}\x{8A85}\x{8A86}\x{8A87}\x{8A89}\x{8A8A}\x{8A8B}' . + '\x{8A8C}\x{8A8D}\x{8A8E}\x{8A8F}\x{8A90}\x{8A91}\x{8A92}\x{8A93}\x{8A94}' . + '\x{8A95}\x{8A96}\x{8A97}\x{8A98}\x{8A99}\x{8A9A}\x{8A9B}\x{8A9C}\x{8A9D}' . + '\x{8A9E}\x{8AA0}\x{8AA1}\x{8AA2}\x{8AA3}\x{8AA4}\x{8AA5}\x{8AA6}\x{8AA7}' . + '\x{8AA8}\x{8AA9}\x{8AAA}\x{8AAB}\x{8AAC}\x{8AAE}\x{8AB0}\x{8AB1}\x{8AB2}' . + '\x{8AB3}\x{8AB4}\x{8AB5}\x{8AB6}\x{8AB8}\x{8AB9}\x{8ABA}\x{8ABB}\x{8ABC}' . + '\x{8ABD}\x{8ABE}\x{8ABF}\x{8AC0}\x{8AC1}\x{8AC2}\x{8AC3}\x{8AC4}\x{8AC5}' . + '\x{8AC6}\x{8AC7}\x{8AC8}\x{8AC9}\x{8ACA}\x{8ACB}\x{8ACC}\x{8ACD}\x{8ACE}' . + '\x{8ACF}\x{8AD1}\x{8AD2}\x{8AD3}\x{8AD4}\x{8AD5}\x{8AD6}\x{8AD7}\x{8AD8}' . + '\x{8AD9}\x{8ADA}\x{8ADB}\x{8ADC}\x{8ADD}\x{8ADE}\x{8ADF}\x{8AE0}\x{8AE1}' . + '\x{8AE2}\x{8AE3}\x{8AE4}\x{8AE5}\x{8AE6}\x{8AE7}\x{8AE8}\x{8AE9}\x{8AEA}' . + '\x{8AEB}\x{8AED}\x{8AEE}\x{8AEF}\x{8AF0}\x{8AF1}\x{8AF2}\x{8AF3}\x{8AF4}' . + '\x{8AF5}\x{8AF6}\x{8AF7}\x{8AF8}\x{8AF9}\x{8AFA}\x{8AFB}\x{8AFC}\x{8AFD}' . + '\x{8AFE}\x{8AFF}\x{8B00}\x{8B01}\x{8B02}\x{8B03}\x{8B04}\x{8B05}\x{8B06}' . + '\x{8B07}\x{8B08}\x{8B09}\x{8B0A}\x{8B0B}\x{8B0D}\x{8B0E}\x{8B0F}\x{8B10}' . + '\x{8B11}\x{8B12}\x{8B13}\x{8B14}\x{8B15}\x{8B16}\x{8B17}\x{8B18}\x{8B19}' . + '\x{8B1A}\x{8B1B}\x{8B1C}\x{8B1D}\x{8B1E}\x{8B1F}\x{8B20}\x{8B21}\x{8B22}' . + '\x{8B23}\x{8B24}\x{8B25}\x{8B26}\x{8B27}\x{8B28}\x{8B2A}\x{8B2B}\x{8B2C}' . + '\x{8B2D}\x{8B2E}\x{8B2F}\x{8B30}\x{8B31}\x{8B33}\x{8B34}\x{8B35}\x{8B36}' . + '\x{8B37}\x{8B39}\x{8B3A}\x{8B3B}\x{8B3C}\x{8B3D}\x{8B3E}\x{8B40}\x{8B41}' . + '\x{8B42}\x{8B43}\x{8B44}\x{8B45}\x{8B46}\x{8B47}\x{8B48}\x{8B49}\x{8B4A}' . + '\x{8B4B}\x{8B4C}\x{8B4D}\x{8B4E}\x{8B4F}\x{8B50}\x{8B51}\x{8B52}\x{8B53}' . + '\x{8B54}\x{8B55}\x{8B56}\x{8B57}\x{8B58}\x{8B59}\x{8B5A}\x{8B5B}\x{8B5C}' . + '\x{8B5D}\x{8B5E}\x{8B5F}\x{8B60}\x{8B63}\x{8B64}\x{8B65}\x{8B66}\x{8B67}' . + '\x{8B68}\x{8B6A}\x{8B6B}\x{8B6C}\x{8B6D}\x{8B6E}\x{8B6F}\x{8B70}\x{8B71}' . + '\x{8B73}\x{8B74}\x{8B76}\x{8B77}\x{8B78}\x{8B79}\x{8B7A}\x{8B7B}\x{8B7D}' . + '\x{8B7E}\x{8B7F}\x{8B80}\x{8B82}\x{8B83}\x{8B84}\x{8B85}\x{8B86}\x{8B88}' . + '\x{8B89}\x{8B8A}\x{8B8B}\x{8B8C}\x{8B8E}\x{8B90}\x{8B91}\x{8B92}\x{8B93}' . + '\x{8B94}\x{8B95}\x{8B96}\x{8B97}\x{8B98}\x{8B99}\x{8B9A}\x{8B9C}\x{8B9D}' . + '\x{8B9E}\x{8B9F}\x{8BA0}\x{8BA1}\x{8BA2}\x{8BA3}\x{8BA4}\x{8BA5}\x{8BA6}' . + '\x{8BA7}\x{8BA8}\x{8BA9}\x{8BAA}\x{8BAB}\x{8BAC}\x{8BAD}\x{8BAE}\x{8BAF}' . + '\x{8BB0}\x{8BB1}\x{8BB2}\x{8BB3}\x{8BB4}\x{8BB5}\x{8BB6}\x{8BB7}\x{8BB8}' . + '\x{8BB9}\x{8BBA}\x{8BBB}\x{8BBC}\x{8BBD}\x{8BBE}\x{8BBF}\x{8BC0}\x{8BC1}' . + '\x{8BC2}\x{8BC3}\x{8BC4}\x{8BC5}\x{8BC6}\x{8BC7}\x{8BC8}\x{8BC9}\x{8BCA}' . + '\x{8BCB}\x{8BCC}\x{8BCD}\x{8BCE}\x{8BCF}\x{8BD0}\x{8BD1}\x{8BD2}\x{8BD3}' . + '\x{8BD4}\x{8BD5}\x{8BD6}\x{8BD7}\x{8BD8}\x{8BD9}\x{8BDA}\x{8BDB}\x{8BDC}' . + '\x{8BDD}\x{8BDE}\x{8BDF}\x{8BE0}\x{8BE1}\x{8BE2}\x{8BE3}\x{8BE4}\x{8BE5}' . + '\x{8BE6}\x{8BE7}\x{8BE8}\x{8BE9}\x{8BEA}\x{8BEB}\x{8BEC}\x{8BED}\x{8BEE}' . + '\x{8BEF}\x{8BF0}\x{8BF1}\x{8BF2}\x{8BF3}\x{8BF4}\x{8BF5}\x{8BF6}\x{8BF7}' . + '\x{8BF8}\x{8BF9}\x{8BFA}\x{8BFB}\x{8BFC}\x{8BFD}\x{8BFE}\x{8BFF}\x{8C00}' . + '\x{8C01}\x{8C02}\x{8C03}\x{8C04}\x{8C05}\x{8C06}\x{8C07}\x{8C08}\x{8C09}' . + '\x{8C0A}\x{8C0B}\x{8C0C}\x{8C0D}\x{8C0E}\x{8C0F}\x{8C10}\x{8C11}\x{8C12}' . + '\x{8C13}\x{8C14}\x{8C15}\x{8C16}\x{8C17}\x{8C18}\x{8C19}\x{8C1A}\x{8C1B}' . + '\x{8C1C}\x{8C1D}\x{8C1E}\x{8C1F}\x{8C20}\x{8C21}\x{8C22}\x{8C23}\x{8C24}' . + '\x{8C25}\x{8C26}\x{8C27}\x{8C28}\x{8C29}\x{8C2A}\x{8C2B}\x{8C2C}\x{8C2D}' . + '\x{8C2E}\x{8C2F}\x{8C30}\x{8C31}\x{8C32}\x{8C33}\x{8C34}\x{8C35}\x{8C36}' . + '\x{8C37}\x{8C39}\x{8C3A}\x{8C3B}\x{8C3C}\x{8C3D}\x{8C3E}\x{8C3F}\x{8C41}' . + '\x{8C42}\x{8C43}\x{8C45}\x{8C46}\x{8C47}\x{8C48}\x{8C49}\x{8C4A}\x{8C4B}' . + '\x{8C4C}\x{8C4D}\x{8C4E}\x{8C4F}\x{8C50}\x{8C54}\x{8C55}\x{8C56}\x{8C57}' . + '\x{8C59}\x{8C5A}\x{8C5B}\x{8C5C}\x{8C5D}\x{8C5E}\x{8C5F}\x{8C60}\x{8C61}' . + '\x{8C62}\x{8C63}\x{8C64}\x{8C65}\x{8C66}\x{8C67}\x{8C68}\x{8C69}\x{8C6A}' . + '\x{8C6B}\x{8C6C}\x{8C6D}\x{8C6E}\x{8C6F}\x{8C70}\x{8C71}\x{8C72}\x{8C73}' . + '\x{8C75}\x{8C76}\x{8C77}\x{8C78}\x{8C79}\x{8C7A}\x{8C7B}\x{8C7D}\x{8C7E}' . + '\x{8C80}\x{8C81}\x{8C82}\x{8C84}\x{8C85}\x{8C86}\x{8C88}\x{8C89}\x{8C8A}' . + '\x{8C8C}\x{8C8D}\x{8C8F}\x{8C90}\x{8C91}\x{8C92}\x{8C93}\x{8C94}\x{8C95}' . + '\x{8C96}\x{8C97}\x{8C98}\x{8C99}\x{8C9A}\x{8C9C}\x{8C9D}\x{8C9E}\x{8C9F}' . + '\x{8CA0}\x{8CA1}\x{8CA2}\x{8CA3}\x{8CA4}\x{8CA5}\x{8CA7}\x{8CA8}\x{8CA9}' . + '\x{8CAA}\x{8CAB}\x{8CAC}\x{8CAD}\x{8CAE}\x{8CAF}\x{8CB0}\x{8CB1}\x{8CB2}' . + '\x{8CB3}\x{8CB4}\x{8CB5}\x{8CB6}\x{8CB7}\x{8CB8}\x{8CB9}\x{8CBA}\x{8CBB}' . + '\x{8CBC}\x{8CBD}\x{8CBE}\x{8CBF}\x{8CC0}\x{8CC1}\x{8CC2}\x{8CC3}\x{8CC4}' . + '\x{8CC5}\x{8CC6}\x{8CC7}\x{8CC8}\x{8CC9}\x{8CCA}\x{8CCC}\x{8CCE}\x{8CCF}' . + '\x{8CD0}\x{8CD1}\x{8CD2}\x{8CD3}\x{8CD4}\x{8CD5}\x{8CD7}\x{8CD9}\x{8CDA}' . + '\x{8CDB}\x{8CDC}\x{8CDD}\x{8CDE}\x{8CDF}\x{8CE0}\x{8CE1}\x{8CE2}\x{8CE3}' . + '\x{8CE4}\x{8CE5}\x{8CE6}\x{8CE7}\x{8CE8}\x{8CEA}\x{8CEB}\x{8CEC}\x{8CED}' . + '\x{8CEE}\x{8CEF}\x{8CF0}\x{8CF1}\x{8CF2}\x{8CF3}\x{8CF4}\x{8CF5}\x{8CF6}' . + '\x{8CF8}\x{8CF9}\x{8CFA}\x{8CFB}\x{8CFC}\x{8CFD}\x{8CFE}\x{8CFF}\x{8D00}' . + '\x{8D02}\x{8D03}\x{8D04}\x{8D05}\x{8D06}\x{8D07}\x{8D08}\x{8D09}\x{8D0A}' . + '\x{8D0B}\x{8D0C}\x{8D0D}\x{8D0E}\x{8D0F}\x{8D10}\x{8D13}\x{8D14}\x{8D15}' . + '\x{8D16}\x{8D17}\x{8D18}\x{8D19}\x{8D1A}\x{8D1B}\x{8D1C}\x{8D1D}\x{8D1E}' . + '\x{8D1F}\x{8D20}\x{8D21}\x{8D22}\x{8D23}\x{8D24}\x{8D25}\x{8D26}\x{8D27}' . + '\x{8D28}\x{8D29}\x{8D2A}\x{8D2B}\x{8D2C}\x{8D2D}\x{8D2E}\x{8D2F}\x{8D30}' . + '\x{8D31}\x{8D32}\x{8D33}\x{8D34}\x{8D35}\x{8D36}\x{8D37}\x{8D38}\x{8D39}' . + '\x{8D3A}\x{8D3B}\x{8D3C}\x{8D3D}\x{8D3E}\x{8D3F}\x{8D40}\x{8D41}\x{8D42}' . + '\x{8D43}\x{8D44}\x{8D45}\x{8D46}\x{8D47}\x{8D48}\x{8D49}\x{8D4A}\x{8D4B}' . + '\x{8D4C}\x{8D4D}\x{8D4E}\x{8D4F}\x{8D50}\x{8D51}\x{8D52}\x{8D53}\x{8D54}' . + '\x{8D55}\x{8D56}\x{8D57}\x{8D58}\x{8D59}\x{8D5A}\x{8D5B}\x{8D5C}\x{8D5D}' . + '\x{8D5E}\x{8D5F}\x{8D60}\x{8D61}\x{8D62}\x{8D63}\x{8D64}\x{8D65}\x{8D66}' . + '\x{8D67}\x{8D68}\x{8D69}\x{8D6A}\x{8D6B}\x{8D6C}\x{8D6D}\x{8D6E}\x{8D6F}' . + '\x{8D70}\x{8D71}\x{8D72}\x{8D73}\x{8D74}\x{8D75}\x{8D76}\x{8D77}\x{8D78}' . + '\x{8D79}\x{8D7A}\x{8D7B}\x{8D7D}\x{8D7E}\x{8D7F}\x{8D80}\x{8D81}\x{8D82}' . + '\x{8D83}\x{8D84}\x{8D85}\x{8D86}\x{8D87}\x{8D88}\x{8D89}\x{8D8A}\x{8D8B}' . + '\x{8D8C}\x{8D8D}\x{8D8E}\x{8D8F}\x{8D90}\x{8D91}\x{8D92}\x{8D93}\x{8D94}' . + '\x{8D95}\x{8D96}\x{8D97}\x{8D98}\x{8D99}\x{8D9A}\x{8D9B}\x{8D9C}\x{8D9D}' . + '\x{8D9E}\x{8D9F}\x{8DA0}\x{8DA1}\x{8DA2}\x{8DA3}\x{8DA4}\x{8DA5}\x{8DA7}' . + '\x{8DA8}\x{8DA9}\x{8DAA}\x{8DAB}\x{8DAC}\x{8DAD}\x{8DAE}\x{8DAF}\x{8DB0}' . + '\x{8DB1}\x{8DB2}\x{8DB3}\x{8DB4}\x{8DB5}\x{8DB6}\x{8DB7}\x{8DB8}\x{8DB9}' . + '\x{8DBA}\x{8DBB}\x{8DBC}\x{8DBD}\x{8DBE}\x{8DBF}\x{8DC1}\x{8DC2}\x{8DC3}' . + '\x{8DC4}\x{8DC5}\x{8DC6}\x{8DC7}\x{8DC8}\x{8DC9}\x{8DCA}\x{8DCB}\x{8DCC}' . + '\x{8DCD}\x{8DCE}\x{8DCF}\x{8DD0}\x{8DD1}\x{8DD2}\x{8DD3}\x{8DD4}\x{8DD5}' . + '\x{8DD6}\x{8DD7}\x{8DD8}\x{8DD9}\x{8DDA}\x{8DDB}\x{8DDC}\x{8DDD}\x{8DDE}' . + '\x{8DDF}\x{8DE0}\x{8DE1}\x{8DE2}\x{8DE3}\x{8DE4}\x{8DE6}\x{8DE7}\x{8DE8}' . + '\x{8DE9}\x{8DEA}\x{8DEB}\x{8DEC}\x{8DED}\x{8DEE}\x{8DEF}\x{8DF0}\x{8DF1}' . + '\x{8DF2}\x{8DF3}\x{8DF4}\x{8DF5}\x{8DF6}\x{8DF7}\x{8DF8}\x{8DF9}\x{8DFA}' . + '\x{8DFB}\x{8DFC}\x{8DFD}\x{8DFE}\x{8DFF}\x{8E00}\x{8E02}\x{8E03}\x{8E04}' . + '\x{8E05}\x{8E06}\x{8E07}\x{8E08}\x{8E09}\x{8E0A}\x{8E0C}\x{8E0D}\x{8E0E}' . + '\x{8E0F}\x{8E10}\x{8E11}\x{8E12}\x{8E13}\x{8E14}\x{8E15}\x{8E16}\x{8E17}' . + '\x{8E18}\x{8E19}\x{8E1A}\x{8E1B}\x{8E1C}\x{8E1D}\x{8E1E}\x{8E1F}\x{8E20}' . + '\x{8E21}\x{8E22}\x{8E23}\x{8E24}\x{8E25}\x{8E26}\x{8E27}\x{8E28}\x{8E29}' . + '\x{8E2A}\x{8E2B}\x{8E2C}\x{8E2D}\x{8E2E}\x{8E2F}\x{8E30}\x{8E31}\x{8E33}' . + '\x{8E34}\x{8E35}\x{8E36}\x{8E37}\x{8E38}\x{8E39}\x{8E3A}\x{8E3B}\x{8E3C}' . + '\x{8E3D}\x{8E3E}\x{8E3F}\x{8E40}\x{8E41}\x{8E42}\x{8E43}\x{8E44}\x{8E45}' . + '\x{8E47}\x{8E48}\x{8E49}\x{8E4A}\x{8E4B}\x{8E4C}\x{8E4D}\x{8E4E}\x{8E50}' . + '\x{8E51}\x{8E52}\x{8E53}\x{8E54}\x{8E55}\x{8E56}\x{8E57}\x{8E58}\x{8E59}' . + '\x{8E5A}\x{8E5B}\x{8E5C}\x{8E5D}\x{8E5E}\x{8E5F}\x{8E60}\x{8E61}\x{8E62}' . + '\x{8E63}\x{8E64}\x{8E65}\x{8E66}\x{8E67}\x{8E68}\x{8E69}\x{8E6A}\x{8E6B}' . + '\x{8E6C}\x{8E6D}\x{8E6F}\x{8E70}\x{8E71}\x{8E72}\x{8E73}\x{8E74}\x{8E76}' . + '\x{8E78}\x{8E7A}\x{8E7B}\x{8E7C}\x{8E7D}\x{8E7E}\x{8E7F}\x{8E80}\x{8E81}' . + '\x{8E82}\x{8E83}\x{8E84}\x{8E85}\x{8E86}\x{8E87}\x{8E88}\x{8E89}\x{8E8A}' . + '\x{8E8B}\x{8E8C}\x{8E8D}\x{8E8E}\x{8E8F}\x{8E90}\x{8E91}\x{8E92}\x{8E93}' . + '\x{8E94}\x{8E95}\x{8E96}\x{8E97}\x{8E98}\x{8E9A}\x{8E9C}\x{8E9D}\x{8E9E}' . + '\x{8E9F}\x{8EA0}\x{8EA1}\x{8EA3}\x{8EA4}\x{8EA5}\x{8EA6}\x{8EA7}\x{8EA8}' . + '\x{8EA9}\x{8EAA}\x{8EAB}\x{8EAC}\x{8EAD}\x{8EAE}\x{8EAF}\x{8EB0}\x{8EB1}' . + '\x{8EB2}\x{8EB4}\x{8EB5}\x{8EB8}\x{8EB9}\x{8EBA}\x{8EBB}\x{8EBC}\x{8EBD}' . + '\x{8EBE}\x{8EBF}\x{8EC0}\x{8EC2}\x{8EC3}\x{8EC5}\x{8EC6}\x{8EC7}\x{8EC8}' . + '\x{8EC9}\x{8ECA}\x{8ECB}\x{8ECC}\x{8ECD}\x{8ECE}\x{8ECF}\x{8ED0}\x{8ED1}' . + '\x{8ED2}\x{8ED3}\x{8ED4}\x{8ED5}\x{8ED6}\x{8ED7}\x{8ED8}\x{8EDA}\x{8EDB}' . + '\x{8EDC}\x{8EDD}\x{8EDE}\x{8EDF}\x{8EE0}\x{8EE1}\x{8EE4}\x{8EE5}\x{8EE6}' . + '\x{8EE7}\x{8EE8}\x{8EE9}\x{8EEA}\x{8EEB}\x{8EEC}\x{8EED}\x{8EEE}\x{8EEF}' . + '\x{8EF1}\x{8EF2}\x{8EF3}\x{8EF4}\x{8EF5}\x{8EF6}\x{8EF7}\x{8EF8}\x{8EF9}' . + '\x{8EFA}\x{8EFB}\x{8EFC}\x{8EFD}\x{8EFE}\x{8EFF}\x{8F00}\x{8F01}\x{8F02}' . + '\x{8F03}\x{8F04}\x{8F05}\x{8F06}\x{8F07}\x{8F08}\x{8F09}\x{8F0A}\x{8F0B}' . + '\x{8F0D}\x{8F0E}\x{8F10}\x{8F11}\x{8F12}\x{8F13}\x{8F14}\x{8F15}\x{8F16}' . + '\x{8F17}\x{8F18}\x{8F1A}\x{8F1B}\x{8F1C}\x{8F1D}\x{8F1E}\x{8F1F}\x{8F20}' . + '\x{8F21}\x{8F22}\x{8F23}\x{8F24}\x{8F25}\x{8F26}\x{8F27}\x{8F28}\x{8F29}' . + '\x{8F2A}\x{8F2B}\x{8F2C}\x{8F2E}\x{8F2F}\x{8F30}\x{8F31}\x{8F32}\x{8F33}' . + '\x{8F34}\x{8F35}\x{8F36}\x{8F37}\x{8F38}\x{8F39}\x{8F3B}\x{8F3C}\x{8F3D}' . + '\x{8F3E}\x{8F3F}\x{8F40}\x{8F42}\x{8F43}\x{8F44}\x{8F45}\x{8F46}\x{8F47}' . + '\x{8F48}\x{8F49}\x{8F4A}\x{8F4B}\x{8F4C}\x{8F4D}\x{8F4E}\x{8F4F}\x{8F50}' . + '\x{8F51}\x{8F52}\x{8F53}\x{8F54}\x{8F55}\x{8F56}\x{8F57}\x{8F58}\x{8F59}' . + '\x{8F5A}\x{8F5B}\x{8F5D}\x{8F5E}\x{8F5F}\x{8F60}\x{8F61}\x{8F62}\x{8F63}' . + '\x{8F64}\x{8F65}\x{8F66}\x{8F67}\x{8F68}\x{8F69}\x{8F6A}\x{8F6B}\x{8F6C}' . + '\x{8F6D}\x{8F6E}\x{8F6F}\x{8F70}\x{8F71}\x{8F72}\x{8F73}\x{8F74}\x{8F75}' . + '\x{8F76}\x{8F77}\x{8F78}\x{8F79}\x{8F7A}\x{8F7B}\x{8F7C}\x{8F7D}\x{8F7E}' . + '\x{8F7F}\x{8F80}\x{8F81}\x{8F82}\x{8F83}\x{8F84}\x{8F85}\x{8F86}\x{8F87}' . + '\x{8F88}\x{8F89}\x{8F8A}\x{8F8B}\x{8F8C}\x{8F8D}\x{8F8E}\x{8F8F}\x{8F90}' . + '\x{8F91}\x{8F92}\x{8F93}\x{8F94}\x{8F95}\x{8F96}\x{8F97}\x{8F98}\x{8F99}' . + '\x{8F9A}\x{8F9B}\x{8F9C}\x{8F9E}\x{8F9F}\x{8FA0}\x{8FA1}\x{8FA2}\x{8FA3}' . + '\x{8FA5}\x{8FA6}\x{8FA7}\x{8FA8}\x{8FA9}\x{8FAA}\x{8FAB}\x{8FAC}\x{8FAD}' . + '\x{8FAE}\x{8FAF}\x{8FB0}\x{8FB1}\x{8FB2}\x{8FB4}\x{8FB5}\x{8FB6}\x{8FB7}' . + '\x{8FB8}\x{8FB9}\x{8FBB}\x{8FBC}\x{8FBD}\x{8FBE}\x{8FBF}\x{8FC0}\x{8FC1}' . + '\x{8FC2}\x{8FC4}\x{8FC5}\x{8FC6}\x{8FC7}\x{8FC8}\x{8FC9}\x{8FCB}\x{8FCC}' . + '\x{8FCD}\x{8FCE}\x{8FCF}\x{8FD0}\x{8FD1}\x{8FD2}\x{8FD3}\x{8FD4}\x{8FD5}' . + '\x{8FD6}\x{8FD7}\x{8FD8}\x{8FD9}\x{8FDA}\x{8FDB}\x{8FDC}\x{8FDD}\x{8FDE}' . + '\x{8FDF}\x{8FE0}\x{8FE1}\x{8FE2}\x{8FE3}\x{8FE4}\x{8FE5}\x{8FE6}\x{8FE8}' . + '\x{8FE9}\x{8FEA}\x{8FEB}\x{8FEC}\x{8FED}\x{8FEE}\x{8FEF}\x{8FF0}\x{8FF1}' . + '\x{8FF2}\x{8FF3}\x{8FF4}\x{8FF5}\x{8FF6}\x{8FF7}\x{8FF8}\x{8FF9}\x{8FFA}' . + '\x{8FFB}\x{8FFC}\x{8FFD}\x{8FFE}\x{8FFF}\x{9000}\x{9001}\x{9002}\x{9003}' . + '\x{9004}\x{9005}\x{9006}\x{9007}\x{9008}\x{9009}\x{900A}\x{900B}\x{900C}' . + '\x{900D}\x{900F}\x{9010}\x{9011}\x{9012}\x{9013}\x{9014}\x{9015}\x{9016}' . + '\x{9017}\x{9018}\x{9019}\x{901A}\x{901B}\x{901C}\x{901D}\x{901E}\x{901F}' . + '\x{9020}\x{9021}\x{9022}\x{9023}\x{9024}\x{9025}\x{9026}\x{9027}\x{9028}' . + '\x{9029}\x{902B}\x{902D}\x{902E}\x{902F}\x{9030}\x{9031}\x{9032}\x{9033}' . + '\x{9034}\x{9035}\x{9036}\x{9038}\x{903A}\x{903B}\x{903C}\x{903D}\x{903E}' . + '\x{903F}\x{9041}\x{9042}\x{9043}\x{9044}\x{9045}\x{9047}\x{9048}\x{9049}' . + '\x{904A}\x{904B}\x{904C}\x{904D}\x{904E}\x{904F}\x{9050}\x{9051}\x{9052}' . + '\x{9053}\x{9054}\x{9055}\x{9056}\x{9057}\x{9058}\x{9059}\x{905A}\x{905B}' . + '\x{905C}\x{905D}\x{905E}\x{905F}\x{9060}\x{9061}\x{9062}\x{9063}\x{9064}' . + '\x{9065}\x{9066}\x{9067}\x{9068}\x{9069}\x{906A}\x{906B}\x{906C}\x{906D}' . + '\x{906E}\x{906F}\x{9070}\x{9071}\x{9072}\x{9073}\x{9074}\x{9075}\x{9076}' . + '\x{9077}\x{9078}\x{9079}\x{907A}\x{907B}\x{907C}\x{907D}\x{907E}\x{907F}' . + '\x{9080}\x{9081}\x{9082}\x{9083}\x{9084}\x{9085}\x{9086}\x{9087}\x{9088}' . + '\x{9089}\x{908A}\x{908B}\x{908C}\x{908D}\x{908E}\x{908F}\x{9090}\x{9091}' . + '\x{9092}\x{9093}\x{9094}\x{9095}\x{9096}\x{9097}\x{9098}\x{9099}\x{909A}' . + '\x{909B}\x{909C}\x{909D}\x{909E}\x{909F}\x{90A0}\x{90A1}\x{90A2}\x{90A3}' . + '\x{90A4}\x{90A5}\x{90A6}\x{90A7}\x{90A8}\x{90A9}\x{90AA}\x{90AC}\x{90AD}' . + '\x{90AE}\x{90AF}\x{90B0}\x{90B1}\x{90B2}\x{90B3}\x{90B4}\x{90B5}\x{90B6}' . + '\x{90B7}\x{90B8}\x{90B9}\x{90BA}\x{90BB}\x{90BC}\x{90BD}\x{90BE}\x{90BF}' . + '\x{90C0}\x{90C1}\x{90C2}\x{90C3}\x{90C4}\x{90C5}\x{90C6}\x{90C7}\x{90C8}' . + '\x{90C9}\x{90CA}\x{90CB}\x{90CE}\x{90CF}\x{90D0}\x{90D1}\x{90D3}\x{90D4}' . + '\x{90D5}\x{90D6}\x{90D7}\x{90D8}\x{90D9}\x{90DA}\x{90DB}\x{90DC}\x{90DD}' . + '\x{90DE}\x{90DF}\x{90E0}\x{90E1}\x{90E2}\x{90E3}\x{90E4}\x{90E5}\x{90E6}' . + '\x{90E7}\x{90E8}\x{90E9}\x{90EA}\x{90EB}\x{90EC}\x{90ED}\x{90EE}\x{90EF}' . + '\x{90F0}\x{90F1}\x{90F2}\x{90F3}\x{90F4}\x{90F5}\x{90F7}\x{90F8}\x{90F9}' . + '\x{90FA}\x{90FB}\x{90FC}\x{90FD}\x{90FE}\x{90FF}\x{9100}\x{9101}\x{9102}' . + '\x{9103}\x{9104}\x{9105}\x{9106}\x{9107}\x{9108}\x{9109}\x{910B}\x{910C}' . + '\x{910D}\x{910E}\x{910F}\x{9110}\x{9111}\x{9112}\x{9113}\x{9114}\x{9115}' . + '\x{9116}\x{9117}\x{9118}\x{9119}\x{911A}\x{911B}\x{911C}\x{911D}\x{911E}' . + '\x{911F}\x{9120}\x{9121}\x{9122}\x{9123}\x{9124}\x{9125}\x{9126}\x{9127}' . + '\x{9128}\x{9129}\x{912A}\x{912B}\x{912C}\x{912D}\x{912E}\x{912F}\x{9130}' . + '\x{9131}\x{9132}\x{9133}\x{9134}\x{9135}\x{9136}\x{9137}\x{9138}\x{9139}' . + '\x{913A}\x{913B}\x{913E}\x{913F}\x{9140}\x{9141}\x{9142}\x{9143}\x{9144}' . + '\x{9145}\x{9146}\x{9147}\x{9148}\x{9149}\x{914A}\x{914B}\x{914C}\x{914D}' . + '\x{914E}\x{914F}\x{9150}\x{9151}\x{9152}\x{9153}\x{9154}\x{9155}\x{9156}' . + '\x{9157}\x{9158}\x{915A}\x{915B}\x{915C}\x{915D}\x{915E}\x{915F}\x{9160}' . + '\x{9161}\x{9162}\x{9163}\x{9164}\x{9165}\x{9166}\x{9167}\x{9168}\x{9169}' . + '\x{916A}\x{916B}\x{916C}\x{916D}\x{916E}\x{916F}\x{9170}\x{9171}\x{9172}' . + '\x{9173}\x{9174}\x{9175}\x{9176}\x{9177}\x{9178}\x{9179}\x{917A}\x{917C}' . + '\x{917D}\x{917E}\x{917F}\x{9180}\x{9181}\x{9182}\x{9183}\x{9184}\x{9185}' . + '\x{9186}\x{9187}\x{9188}\x{9189}\x{918A}\x{918B}\x{918C}\x{918D}\x{918E}' . + '\x{918F}\x{9190}\x{9191}\x{9192}\x{9193}\x{9194}\x{9196}\x{9199}\x{919A}' . + '\x{919B}\x{919C}\x{919D}\x{919E}\x{919F}\x{91A0}\x{91A1}\x{91A2}\x{91A3}' . + '\x{91A5}\x{91A6}\x{91A7}\x{91A8}\x{91AA}\x{91AB}\x{91AC}\x{91AD}\x{91AE}' . + '\x{91AF}\x{91B0}\x{91B1}\x{91B2}\x{91B3}\x{91B4}\x{91B5}\x{91B6}\x{91B7}' . + '\x{91B9}\x{91BA}\x{91BB}\x{91BC}\x{91BD}\x{91BE}\x{91C0}\x{91C1}\x{91C2}' . + '\x{91C3}\x{91C5}\x{91C6}\x{91C7}\x{91C9}\x{91CA}\x{91CB}\x{91CC}\x{91CD}' . + '\x{91CE}\x{91CF}\x{91D0}\x{91D1}\x{91D2}\x{91D3}\x{91D4}\x{91D5}\x{91D7}' . + '\x{91D8}\x{91D9}\x{91DA}\x{91DB}\x{91DC}\x{91DD}\x{91DE}\x{91DF}\x{91E2}' . + '\x{91E3}\x{91E4}\x{91E5}\x{91E6}\x{91E7}\x{91E8}\x{91E9}\x{91EA}\x{91EB}' . + '\x{91EC}\x{91ED}\x{91EE}\x{91F0}\x{91F1}\x{91F2}\x{91F3}\x{91F4}\x{91F5}' . + '\x{91F7}\x{91F8}\x{91F9}\x{91FA}\x{91FB}\x{91FD}\x{91FE}\x{91FF}\x{9200}' . + '\x{9201}\x{9202}\x{9203}\x{9204}\x{9205}\x{9206}\x{9207}\x{9208}\x{9209}' . + '\x{920A}\x{920B}\x{920C}\x{920D}\x{920E}\x{920F}\x{9210}\x{9211}\x{9212}' . + '\x{9214}\x{9215}\x{9216}\x{9217}\x{9218}\x{9219}\x{921A}\x{921B}\x{921C}' . + '\x{921D}\x{921E}\x{9220}\x{9221}\x{9223}\x{9224}\x{9225}\x{9226}\x{9227}' . + '\x{9228}\x{9229}\x{922A}\x{922B}\x{922D}\x{922E}\x{922F}\x{9230}\x{9231}' . + '\x{9232}\x{9233}\x{9234}\x{9235}\x{9236}\x{9237}\x{9238}\x{9239}\x{923A}' . + '\x{923B}\x{923C}\x{923D}\x{923E}\x{923F}\x{9240}\x{9241}\x{9242}\x{9245}' . + '\x{9246}\x{9247}\x{9248}\x{9249}\x{924A}\x{924B}\x{924C}\x{924D}\x{924E}' . + '\x{924F}\x{9250}\x{9251}\x{9252}\x{9253}\x{9254}\x{9255}\x{9256}\x{9257}' . + '\x{9258}\x{9259}\x{925A}\x{925B}\x{925C}\x{925D}\x{925E}\x{925F}\x{9260}' . + '\x{9261}\x{9262}\x{9263}\x{9264}\x{9265}\x{9266}\x{9267}\x{9268}\x{926B}' . + '\x{926C}\x{926D}\x{926E}\x{926F}\x{9270}\x{9272}\x{9273}\x{9274}\x{9275}' . + '\x{9276}\x{9277}\x{9278}\x{9279}\x{927A}\x{927B}\x{927C}\x{927D}\x{927E}' . + '\x{927F}\x{9280}\x{9282}\x{9283}\x{9285}\x{9286}\x{9287}\x{9288}\x{9289}' . + '\x{928A}\x{928B}\x{928C}\x{928D}\x{928E}\x{928F}\x{9290}\x{9291}\x{9292}' . + '\x{9293}\x{9294}\x{9295}\x{9296}\x{9297}\x{9298}\x{9299}\x{929A}\x{929B}' . + '\x{929C}\x{929D}\x{929F}\x{92A0}\x{92A1}\x{92A2}\x{92A3}\x{92A4}\x{92A5}' . + '\x{92A6}\x{92A7}\x{92A8}\x{92A9}\x{92AA}\x{92AB}\x{92AC}\x{92AD}\x{92AE}' . + '\x{92AF}\x{92B0}\x{92B1}\x{92B2}\x{92B3}\x{92B4}\x{92B5}\x{92B6}\x{92B7}' . + '\x{92B8}\x{92B9}\x{92BA}\x{92BB}\x{92BC}\x{92BE}\x{92BF}\x{92C0}\x{92C1}' . + '\x{92C2}\x{92C3}\x{92C4}\x{92C5}\x{92C6}\x{92C7}\x{92C8}\x{92C9}\x{92CA}' . + '\x{92CB}\x{92CC}\x{92CD}\x{92CE}\x{92CF}\x{92D0}\x{92D1}\x{92D2}\x{92D3}' . + '\x{92D5}\x{92D6}\x{92D7}\x{92D8}\x{92D9}\x{92DA}\x{92DC}\x{92DD}\x{92DE}' . + '\x{92DF}\x{92E0}\x{92E1}\x{92E3}\x{92E4}\x{92E5}\x{92E6}\x{92E7}\x{92E8}' . + '\x{92E9}\x{92EA}\x{92EB}\x{92EC}\x{92ED}\x{92EE}\x{92EF}\x{92F0}\x{92F1}' . + '\x{92F2}\x{92F3}\x{92F4}\x{92F5}\x{92F6}\x{92F7}\x{92F8}\x{92F9}\x{92FA}' . + '\x{92FB}\x{92FC}\x{92FD}\x{92FE}\x{92FF}\x{9300}\x{9301}\x{9302}\x{9303}' . + '\x{9304}\x{9305}\x{9306}\x{9307}\x{9308}\x{9309}\x{930A}\x{930B}\x{930C}' . + '\x{930D}\x{930E}\x{930F}\x{9310}\x{9311}\x{9312}\x{9313}\x{9314}\x{9315}' . + '\x{9316}\x{9317}\x{9318}\x{9319}\x{931A}\x{931B}\x{931D}\x{931E}\x{931F}' . + '\x{9320}\x{9321}\x{9322}\x{9323}\x{9324}\x{9325}\x{9326}\x{9327}\x{9328}' . + '\x{9329}\x{932A}\x{932B}\x{932D}\x{932E}\x{932F}\x{9332}\x{9333}\x{9334}' . + '\x{9335}\x{9336}\x{9337}\x{9338}\x{9339}\x{933A}\x{933B}\x{933C}\x{933D}' . + '\x{933E}\x{933F}\x{9340}\x{9341}\x{9342}\x{9343}\x{9344}\x{9345}\x{9346}' . + '\x{9347}\x{9348}\x{9349}\x{934A}\x{934B}\x{934C}\x{934D}\x{934E}\x{934F}' . + '\x{9350}\x{9351}\x{9352}\x{9353}\x{9354}\x{9355}\x{9356}\x{9357}\x{9358}' . + '\x{9359}\x{935A}\x{935B}\x{935C}\x{935D}\x{935E}\x{935F}\x{9360}\x{9361}' . + '\x{9363}\x{9364}\x{9365}\x{9366}\x{9367}\x{9369}\x{936A}\x{936C}\x{936D}' . + '\x{936E}\x{9370}\x{9371}\x{9372}\x{9374}\x{9375}\x{9376}\x{9377}\x{9379}' . + '\x{937A}\x{937B}\x{937C}\x{937D}\x{937E}\x{9380}\x{9382}\x{9383}\x{9384}' . + '\x{9385}\x{9386}\x{9387}\x{9388}\x{9389}\x{938A}\x{938C}\x{938D}\x{938E}' . + '\x{938F}\x{9390}\x{9391}\x{9392}\x{9393}\x{9394}\x{9395}\x{9396}\x{9397}' . + '\x{9398}\x{9399}\x{939A}\x{939B}\x{939D}\x{939E}\x{939F}\x{93A1}\x{93A2}' . + '\x{93A3}\x{93A4}\x{93A5}\x{93A6}\x{93A7}\x{93A8}\x{93A9}\x{93AA}\x{93AC}' . + '\x{93AD}\x{93AE}\x{93AF}\x{93B0}\x{93B1}\x{93B2}\x{93B3}\x{93B4}\x{93B5}' . + '\x{93B6}\x{93B7}\x{93B8}\x{93B9}\x{93BA}\x{93BC}\x{93BD}\x{93BE}\x{93BF}' . + '\x{93C0}\x{93C1}\x{93C2}\x{93C3}\x{93C4}\x{93C5}\x{93C6}\x{93C7}\x{93C8}' . + '\x{93C9}\x{93CA}\x{93CB}\x{93CC}\x{93CD}\x{93CE}\x{93CF}\x{93D0}\x{93D1}' . + '\x{93D2}\x{93D3}\x{93D4}\x{93D5}\x{93D6}\x{93D7}\x{93D8}\x{93D9}\x{93DA}' . + '\x{93DB}\x{93DC}\x{93DD}\x{93DE}\x{93DF}\x{93E1}\x{93E2}\x{93E3}\x{93E4}' . + '\x{93E6}\x{93E7}\x{93E8}\x{93E9}\x{93EA}\x{93EB}\x{93EC}\x{93ED}\x{93EE}' . + '\x{93EF}\x{93F0}\x{93F1}\x{93F2}\x{93F4}\x{93F5}\x{93F6}\x{93F7}\x{93F8}' . + '\x{93F9}\x{93FA}\x{93FB}\x{93FC}\x{93FD}\x{93FE}\x{93FF}\x{9400}\x{9401}' . + '\x{9403}\x{9404}\x{9405}\x{9406}\x{9407}\x{9408}\x{9409}\x{940A}\x{940B}' . + '\x{940C}\x{940D}\x{940E}\x{940F}\x{9410}\x{9411}\x{9412}\x{9413}\x{9414}' . + '\x{9415}\x{9416}\x{9418}\x{9419}\x{941B}\x{941D}\x{9420}\x{9422}\x{9423}' . + '\x{9425}\x{9426}\x{9427}\x{9428}\x{9429}\x{942A}\x{942B}\x{942C}\x{942D}' . + '\x{942E}\x{942F}\x{9430}\x{9431}\x{9432}\x{9433}\x{9434}\x{9435}\x{9436}' . + '\x{9437}\x{9438}\x{9439}\x{943A}\x{943B}\x{943C}\x{943D}\x{943E}\x{943F}' . + '\x{9440}\x{9441}\x{9442}\x{9444}\x{9445}\x{9446}\x{9447}\x{9448}\x{9449}' . + '\x{944A}\x{944B}\x{944C}\x{944D}\x{944F}\x{9450}\x{9451}\x{9452}\x{9453}' . + '\x{9454}\x{9455}\x{9456}\x{9457}\x{9458}\x{9459}\x{945B}\x{945C}\x{945D}' . + '\x{945E}\x{945F}\x{9460}\x{9461}\x{9462}\x{9463}\x{9464}\x{9465}\x{9466}' . + '\x{9467}\x{9468}\x{9469}\x{946A}\x{946B}\x{946D}\x{946E}\x{946F}\x{9470}' . + '\x{9471}\x{9472}\x{9473}\x{9474}\x{9475}\x{9476}\x{9477}\x{9478}\x{9479}' . + '\x{947A}\x{947C}\x{947D}\x{947E}\x{947F}\x{9480}\x{9481}\x{9482}\x{9483}' . + '\x{9484}\x{9485}\x{9486}\x{9487}\x{9488}\x{9489}\x{948A}\x{948B}\x{948C}' . + '\x{948D}\x{948E}\x{948F}\x{9490}\x{9491}\x{9492}\x{9493}\x{9494}\x{9495}' . + '\x{9496}\x{9497}\x{9498}\x{9499}\x{949A}\x{949B}\x{949C}\x{949D}\x{949E}' . + '\x{949F}\x{94A0}\x{94A1}\x{94A2}\x{94A3}\x{94A4}\x{94A5}\x{94A6}\x{94A7}' . + '\x{94A8}\x{94A9}\x{94AA}\x{94AB}\x{94AC}\x{94AD}\x{94AE}\x{94AF}\x{94B0}' . + '\x{94B1}\x{94B2}\x{94B3}\x{94B4}\x{94B5}\x{94B6}\x{94B7}\x{94B8}\x{94B9}' . + '\x{94BA}\x{94BB}\x{94BC}\x{94BD}\x{94BE}\x{94BF}\x{94C0}\x{94C1}\x{94C2}' . + '\x{94C3}\x{94C4}\x{94C5}\x{94C6}\x{94C7}\x{94C8}\x{94C9}\x{94CA}\x{94CB}' . + '\x{94CC}\x{94CD}\x{94CE}\x{94CF}\x{94D0}\x{94D1}\x{94D2}\x{94D3}\x{94D4}' . + '\x{94D5}\x{94D6}\x{94D7}\x{94D8}\x{94D9}\x{94DA}\x{94DB}\x{94DC}\x{94DD}' . + '\x{94DE}\x{94DF}\x{94E0}\x{94E1}\x{94E2}\x{94E3}\x{94E4}\x{94E5}\x{94E6}' . + '\x{94E7}\x{94E8}\x{94E9}\x{94EA}\x{94EB}\x{94EC}\x{94ED}\x{94EE}\x{94EF}' . + '\x{94F0}\x{94F1}\x{94F2}\x{94F3}\x{94F4}\x{94F5}\x{94F6}\x{94F7}\x{94F8}' . + '\x{94F9}\x{94FA}\x{94FB}\x{94FC}\x{94FD}\x{94FE}\x{94FF}\x{9500}\x{9501}' . + '\x{9502}\x{9503}\x{9504}\x{9505}\x{9506}\x{9507}\x{9508}\x{9509}\x{950A}' . + '\x{950B}\x{950C}\x{950D}\x{950E}\x{950F}\x{9510}\x{9511}\x{9512}\x{9513}' . + '\x{9514}\x{9515}\x{9516}\x{9517}\x{9518}\x{9519}\x{951A}\x{951B}\x{951C}' . + '\x{951D}\x{951E}\x{951F}\x{9520}\x{9521}\x{9522}\x{9523}\x{9524}\x{9525}' . + '\x{9526}\x{9527}\x{9528}\x{9529}\x{952A}\x{952B}\x{952C}\x{952D}\x{952E}' . + '\x{952F}\x{9530}\x{9531}\x{9532}\x{9533}\x{9534}\x{9535}\x{9536}\x{9537}' . + '\x{9538}\x{9539}\x{953A}\x{953B}\x{953C}\x{953D}\x{953E}\x{953F}\x{9540}' . + '\x{9541}\x{9542}\x{9543}\x{9544}\x{9545}\x{9546}\x{9547}\x{9548}\x{9549}' . + '\x{954A}\x{954B}\x{954C}\x{954D}\x{954E}\x{954F}\x{9550}\x{9551}\x{9552}' . + '\x{9553}\x{9554}\x{9555}\x{9556}\x{9557}\x{9558}\x{9559}\x{955A}\x{955B}' . + '\x{955C}\x{955D}\x{955E}\x{955F}\x{9560}\x{9561}\x{9562}\x{9563}\x{9564}' . + '\x{9565}\x{9566}\x{9567}\x{9568}\x{9569}\x{956A}\x{956B}\x{956C}\x{956D}' . + '\x{956E}\x{956F}\x{9570}\x{9571}\x{9572}\x{9573}\x{9574}\x{9575}\x{9576}' . + '\x{9577}\x{957A}\x{957B}\x{957C}\x{957D}\x{957F}\x{9580}\x{9581}\x{9582}' . + '\x{9583}\x{9584}\x{9586}\x{9587}\x{9588}\x{9589}\x{958A}\x{958B}\x{958C}' . + '\x{958D}\x{958E}\x{958F}\x{9590}\x{9591}\x{9592}\x{9593}\x{9594}\x{9595}' . + '\x{9596}\x{9598}\x{9599}\x{959A}\x{959B}\x{959C}\x{959D}\x{959E}\x{959F}' . + '\x{95A1}\x{95A2}\x{95A3}\x{95A4}\x{95A5}\x{95A6}\x{95A7}\x{95A8}\x{95A9}' . + '\x{95AA}\x{95AB}\x{95AC}\x{95AD}\x{95AE}\x{95AF}\x{95B0}\x{95B1}\x{95B2}' . + '\x{95B5}\x{95B6}\x{95B7}\x{95B9}\x{95BA}\x{95BB}\x{95BC}\x{95BD}\x{95BE}' . + '\x{95BF}\x{95C0}\x{95C2}\x{95C3}\x{95C4}\x{95C5}\x{95C6}\x{95C7}\x{95C8}' . + '\x{95C9}\x{95CA}\x{95CB}\x{95CC}\x{95CD}\x{95CE}\x{95CF}\x{95D0}\x{95D1}' . + '\x{95D2}\x{95D3}\x{95D4}\x{95D5}\x{95D6}\x{95D7}\x{95D8}\x{95DA}\x{95DB}' . + '\x{95DC}\x{95DE}\x{95DF}\x{95E0}\x{95E1}\x{95E2}\x{95E3}\x{95E4}\x{95E5}' . + '\x{95E6}\x{95E7}\x{95E8}\x{95E9}\x{95EA}\x{95EB}\x{95EC}\x{95ED}\x{95EE}' . + '\x{95EF}\x{95F0}\x{95F1}\x{95F2}\x{95F3}\x{95F4}\x{95F5}\x{95F6}\x{95F7}' . + '\x{95F8}\x{95F9}\x{95FA}\x{95FB}\x{95FC}\x{95FD}\x{95FE}\x{95FF}\x{9600}' . + '\x{9601}\x{9602}\x{9603}\x{9604}\x{9605}\x{9606}\x{9607}\x{9608}\x{9609}' . + '\x{960A}\x{960B}\x{960C}\x{960D}\x{960E}\x{960F}\x{9610}\x{9611}\x{9612}' . + '\x{9613}\x{9614}\x{9615}\x{9616}\x{9617}\x{9618}\x{9619}\x{961A}\x{961B}' . + '\x{961C}\x{961D}\x{961E}\x{961F}\x{9620}\x{9621}\x{9622}\x{9623}\x{9624}' . + '\x{9627}\x{9628}\x{962A}\x{962B}\x{962C}\x{962D}\x{962E}\x{962F}\x{9630}' . + '\x{9631}\x{9632}\x{9633}\x{9634}\x{9635}\x{9636}\x{9637}\x{9638}\x{9639}' . + '\x{963A}\x{963B}\x{963C}\x{963D}\x{963F}\x{9640}\x{9641}\x{9642}\x{9643}' . + '\x{9644}\x{9645}\x{9646}\x{9647}\x{9648}\x{9649}\x{964A}\x{964B}\x{964C}' . + '\x{964D}\x{964E}\x{964F}\x{9650}\x{9651}\x{9652}\x{9653}\x{9654}\x{9655}' . + '\x{9658}\x{9659}\x{965A}\x{965B}\x{965C}\x{965D}\x{965E}\x{965F}\x{9660}' . + '\x{9661}\x{9662}\x{9663}\x{9664}\x{9666}\x{9667}\x{9668}\x{9669}\x{966A}' . + '\x{966B}\x{966C}\x{966D}\x{966E}\x{966F}\x{9670}\x{9671}\x{9672}\x{9673}' . + '\x{9674}\x{9675}\x{9676}\x{9677}\x{9678}\x{967C}\x{967D}\x{967E}\x{9680}' . + '\x{9683}\x{9684}\x{9685}\x{9686}\x{9687}\x{9688}\x{9689}\x{968A}\x{968B}' . + '\x{968D}\x{968E}\x{968F}\x{9690}\x{9691}\x{9692}\x{9693}\x{9694}\x{9695}' . + '\x{9697}\x{9698}\x{9699}\x{969B}\x{969C}\x{969E}\x{96A0}\x{96A1}\x{96A2}' . + '\x{96A3}\x{96A4}\x{96A5}\x{96A6}\x{96A7}\x{96A8}\x{96A9}\x{96AA}\x{96AC}' . + '\x{96AD}\x{96AE}\x{96B0}\x{96B1}\x{96B3}\x{96B4}\x{96B6}\x{96B7}\x{96B8}' . + '\x{96B9}\x{96BA}\x{96BB}\x{96BC}\x{96BD}\x{96BE}\x{96BF}\x{96C0}\x{96C1}' . + '\x{96C2}\x{96C3}\x{96C4}\x{96C5}\x{96C6}\x{96C7}\x{96C8}\x{96C9}\x{96CA}' . + '\x{96CB}\x{96CC}\x{96CD}\x{96CE}\x{96CF}\x{96D0}\x{96D1}\x{96D2}\x{96D3}' . + '\x{96D4}\x{96D5}\x{96D6}\x{96D7}\x{96D8}\x{96D9}\x{96DA}\x{96DB}\x{96DC}' . + '\x{96DD}\x{96DE}\x{96DF}\x{96E0}\x{96E1}\x{96E2}\x{96E3}\x{96E5}\x{96E8}' . + '\x{96E9}\x{96EA}\x{96EB}\x{96EC}\x{96ED}\x{96EE}\x{96EF}\x{96F0}\x{96F1}' . + '\x{96F2}\x{96F3}\x{96F4}\x{96F5}\x{96F6}\x{96F7}\x{96F8}\x{96F9}\x{96FA}' . + '\x{96FB}\x{96FD}\x{96FE}\x{96FF}\x{9700}\x{9701}\x{9702}\x{9703}\x{9704}' . + '\x{9705}\x{9706}\x{9707}\x{9708}\x{9709}\x{970A}\x{970B}\x{970C}\x{970D}' . + '\x{970E}\x{970F}\x{9710}\x{9711}\x{9712}\x{9713}\x{9715}\x{9716}\x{9718}' . + '\x{9719}\x{971C}\x{971D}\x{971E}\x{971F}\x{9720}\x{9721}\x{9722}\x{9723}' . + '\x{9724}\x{9725}\x{9726}\x{9727}\x{9728}\x{9729}\x{972A}\x{972B}\x{972C}' . + '\x{972D}\x{972E}\x{972F}\x{9730}\x{9731}\x{9732}\x{9735}\x{9736}\x{9738}' . + '\x{9739}\x{973A}\x{973B}\x{973C}\x{973D}\x{973E}\x{973F}\x{9742}\x{9743}' . + '\x{9744}\x{9745}\x{9746}\x{9747}\x{9748}\x{9749}\x{974A}\x{974B}\x{974C}' . + '\x{974E}\x{974F}\x{9750}\x{9751}\x{9752}\x{9753}\x{9754}\x{9755}\x{9756}' . + '\x{9758}\x{9759}\x{975A}\x{975B}\x{975C}\x{975D}\x{975E}\x{975F}\x{9760}' . + '\x{9761}\x{9762}\x{9765}\x{9766}\x{9767}\x{9768}\x{9769}\x{976A}\x{976B}' . + '\x{976C}\x{976D}\x{976E}\x{976F}\x{9770}\x{9772}\x{9773}\x{9774}\x{9776}' . + '\x{9777}\x{9778}\x{9779}\x{977A}\x{977B}\x{977C}\x{977D}\x{977E}\x{977F}' . + '\x{9780}\x{9781}\x{9782}\x{9783}\x{9784}\x{9785}\x{9786}\x{9788}\x{978A}' . + '\x{978B}\x{978C}\x{978D}\x{978E}\x{978F}\x{9790}\x{9791}\x{9792}\x{9793}' . + '\x{9794}\x{9795}\x{9796}\x{9797}\x{9798}\x{9799}\x{979A}\x{979C}\x{979D}' . + '\x{979E}\x{979F}\x{97A0}\x{97A1}\x{97A2}\x{97A3}\x{97A4}\x{97A5}\x{97A6}' . + '\x{97A7}\x{97A8}\x{97AA}\x{97AB}\x{97AC}\x{97AD}\x{97AE}\x{97AF}\x{97B2}' . + '\x{97B3}\x{97B4}\x{97B6}\x{97B7}\x{97B8}\x{97B9}\x{97BA}\x{97BB}\x{97BC}' . + '\x{97BD}\x{97BF}\x{97C1}\x{97C2}\x{97C3}\x{97C4}\x{97C5}\x{97C6}\x{97C7}' . + '\x{97C8}\x{97C9}\x{97CA}\x{97CB}\x{97CC}\x{97CD}\x{97CE}\x{97CF}\x{97D0}' . + '\x{97D1}\x{97D3}\x{97D4}\x{97D5}\x{97D6}\x{97D7}\x{97D8}\x{97D9}\x{97DA}' . + '\x{97DB}\x{97DC}\x{97DD}\x{97DE}\x{97DF}\x{97E0}\x{97E1}\x{97E2}\x{97E3}' . + '\x{97E4}\x{97E5}\x{97E6}\x{97E7}\x{97E8}\x{97E9}\x{97EA}\x{97EB}\x{97EC}' . + '\x{97ED}\x{97EE}\x{97EF}\x{97F0}\x{97F1}\x{97F2}\x{97F3}\x{97F4}\x{97F5}' . + '\x{97F6}\x{97F7}\x{97F8}\x{97F9}\x{97FA}\x{97FB}\x{97FD}\x{97FE}\x{97FF}' . + '\x{9800}\x{9801}\x{9802}\x{9803}\x{9804}\x{9805}\x{9806}\x{9807}\x{9808}' . + '\x{9809}\x{980A}\x{980B}\x{980C}\x{980D}\x{980E}\x{980F}\x{9810}\x{9811}' . + '\x{9812}\x{9813}\x{9814}\x{9815}\x{9816}\x{9817}\x{9818}\x{9819}\x{981A}' . + '\x{981B}\x{981C}\x{981D}\x{981E}\x{9820}\x{9821}\x{9822}\x{9823}\x{9824}' . + '\x{9826}\x{9827}\x{9828}\x{9829}\x{982B}\x{982D}\x{982E}\x{982F}\x{9830}' . + '\x{9831}\x{9832}\x{9834}\x{9835}\x{9836}\x{9837}\x{9838}\x{9839}\x{983B}' . + '\x{983C}\x{983D}\x{983F}\x{9840}\x{9841}\x{9843}\x{9844}\x{9845}\x{9846}' . + '\x{9848}\x{9849}\x{984A}\x{984C}\x{984D}\x{984E}\x{984F}\x{9850}\x{9851}' . + '\x{9852}\x{9853}\x{9854}\x{9855}\x{9857}\x{9858}\x{9859}\x{985A}\x{985B}' . + '\x{985C}\x{985D}\x{985E}\x{985F}\x{9860}\x{9861}\x{9862}\x{9863}\x{9864}' . + '\x{9865}\x{9867}\x{9869}\x{986A}\x{986B}\x{986C}\x{986D}\x{986E}\x{986F}' . + '\x{9870}\x{9871}\x{9872}\x{9873}\x{9874}\x{9875}\x{9876}\x{9877}\x{9878}' . + '\x{9879}\x{987A}\x{987B}\x{987C}\x{987D}\x{987E}\x{987F}\x{9880}\x{9881}' . + '\x{9882}\x{9883}\x{9884}\x{9885}\x{9886}\x{9887}\x{9888}\x{9889}\x{988A}' . + '\x{988B}\x{988C}\x{988D}\x{988E}\x{988F}\x{9890}\x{9891}\x{9892}\x{9893}' . + '\x{9894}\x{9895}\x{9896}\x{9897}\x{9898}\x{9899}\x{989A}\x{989B}\x{989C}' . + '\x{989D}\x{989E}\x{989F}\x{98A0}\x{98A1}\x{98A2}\x{98A3}\x{98A4}\x{98A5}' . + '\x{98A6}\x{98A7}\x{98A8}\x{98A9}\x{98AA}\x{98AB}\x{98AC}\x{98AD}\x{98AE}' . + '\x{98AF}\x{98B0}\x{98B1}\x{98B2}\x{98B3}\x{98B4}\x{98B5}\x{98B6}\x{98B8}' . + '\x{98B9}\x{98BA}\x{98BB}\x{98BC}\x{98BD}\x{98BE}\x{98BF}\x{98C0}\x{98C1}' . + '\x{98C2}\x{98C3}\x{98C4}\x{98C5}\x{98C6}\x{98C8}\x{98C9}\x{98CB}\x{98CC}' . + '\x{98CD}\x{98CE}\x{98CF}\x{98D0}\x{98D1}\x{98D2}\x{98D3}\x{98D4}\x{98D5}' . + '\x{98D6}\x{98D7}\x{98D8}\x{98D9}\x{98DA}\x{98DB}\x{98DC}\x{98DD}\x{98DE}' . + '\x{98DF}\x{98E0}\x{98E2}\x{98E3}\x{98E5}\x{98E6}\x{98E7}\x{98E8}\x{98E9}' . + '\x{98EA}\x{98EB}\x{98ED}\x{98EF}\x{98F0}\x{98F2}\x{98F3}\x{98F4}\x{98F5}' . + '\x{98F6}\x{98F7}\x{98F9}\x{98FA}\x{98FC}\x{98FD}\x{98FE}\x{98FF}\x{9900}' . + '\x{9901}\x{9902}\x{9903}\x{9904}\x{9905}\x{9906}\x{9907}\x{9908}\x{9909}' . + '\x{990A}\x{990B}\x{990C}\x{990D}\x{990E}\x{990F}\x{9910}\x{9911}\x{9912}' . + '\x{9913}\x{9914}\x{9915}\x{9916}\x{9917}\x{9918}\x{991A}\x{991B}\x{991C}' . + '\x{991D}\x{991E}\x{991F}\x{9920}\x{9921}\x{9922}\x{9923}\x{9924}\x{9925}' . + '\x{9926}\x{9927}\x{9928}\x{9929}\x{992A}\x{992B}\x{992C}\x{992D}\x{992E}' . + '\x{992F}\x{9930}\x{9931}\x{9932}\x{9933}\x{9934}\x{9935}\x{9936}\x{9937}' . + '\x{9938}\x{9939}\x{993A}\x{993C}\x{993D}\x{993E}\x{993F}\x{9940}\x{9941}' . + '\x{9942}\x{9943}\x{9945}\x{9946}\x{9947}\x{9948}\x{9949}\x{994A}\x{994B}' . + '\x{994C}\x{994E}\x{994F}\x{9950}\x{9951}\x{9952}\x{9953}\x{9954}\x{9955}' . + '\x{9956}\x{9957}\x{9958}\x{9959}\x{995B}\x{995C}\x{995E}\x{995F}\x{9960}' . + '\x{9961}\x{9962}\x{9963}\x{9964}\x{9965}\x{9966}\x{9967}\x{9968}\x{9969}' . + '\x{996A}\x{996B}\x{996C}\x{996D}\x{996E}\x{996F}\x{9970}\x{9971}\x{9972}' . + '\x{9973}\x{9974}\x{9975}\x{9976}\x{9977}\x{9978}\x{9979}\x{997A}\x{997B}' . + '\x{997C}\x{997D}\x{997E}\x{997F}\x{9980}\x{9981}\x{9982}\x{9983}\x{9984}' . + '\x{9985}\x{9986}\x{9987}\x{9988}\x{9989}\x{998A}\x{998B}\x{998C}\x{998D}' . + '\x{998E}\x{998F}\x{9990}\x{9991}\x{9992}\x{9993}\x{9994}\x{9995}\x{9996}' . + '\x{9997}\x{9998}\x{9999}\x{999A}\x{999B}\x{999C}\x{999D}\x{999E}\x{999F}' . + '\x{99A0}\x{99A1}\x{99A2}\x{99A3}\x{99A4}\x{99A5}\x{99A6}\x{99A7}\x{99A8}' . + '\x{99A9}\x{99AA}\x{99AB}\x{99AC}\x{99AD}\x{99AE}\x{99AF}\x{99B0}\x{99B1}' . + '\x{99B2}\x{99B3}\x{99B4}\x{99B5}\x{99B6}\x{99B7}\x{99B8}\x{99B9}\x{99BA}' . + '\x{99BB}\x{99BC}\x{99BD}\x{99BE}\x{99C0}\x{99C1}\x{99C2}\x{99C3}\x{99C4}' . + '\x{99C6}\x{99C7}\x{99C8}\x{99C9}\x{99CA}\x{99CB}\x{99CC}\x{99CD}\x{99CE}' . + '\x{99CF}\x{99D0}\x{99D1}\x{99D2}\x{99D3}\x{99D4}\x{99D5}\x{99D6}\x{99D7}' . + '\x{99D8}\x{99D9}\x{99DA}\x{99DB}\x{99DC}\x{99DD}\x{99DE}\x{99DF}\x{99E1}' . + '\x{99E2}\x{99E3}\x{99E4}\x{99E5}\x{99E7}\x{99E8}\x{99E9}\x{99EA}\x{99EC}' . + '\x{99ED}\x{99EE}\x{99EF}\x{99F0}\x{99F1}\x{99F2}\x{99F3}\x{99F4}\x{99F6}' . + '\x{99F7}\x{99F8}\x{99F9}\x{99FA}\x{99FB}\x{99FC}\x{99FD}\x{99FE}\x{99FF}' . + '\x{9A00}\x{9A01}\x{9A02}\x{9A03}\x{9A04}\x{9A05}\x{9A06}\x{9A07}\x{9A08}' . + '\x{9A09}\x{9A0A}\x{9A0B}\x{9A0C}\x{9A0D}\x{9A0E}\x{9A0F}\x{9A11}\x{9A14}' . + '\x{9A15}\x{9A16}\x{9A19}\x{9A1A}\x{9A1B}\x{9A1C}\x{9A1D}\x{9A1E}\x{9A1F}' . + '\x{9A20}\x{9A21}\x{9A22}\x{9A23}\x{9A24}\x{9A25}\x{9A26}\x{9A27}\x{9A29}' . + '\x{9A2A}\x{9A2B}\x{9A2C}\x{9A2D}\x{9A2E}\x{9A2F}\x{9A30}\x{9A31}\x{9A32}' . + '\x{9A33}\x{9A34}\x{9A35}\x{9A36}\x{9A37}\x{9A38}\x{9A39}\x{9A3A}\x{9A3C}' . + '\x{9A3D}\x{9A3E}\x{9A3F}\x{9A40}\x{9A41}\x{9A42}\x{9A43}\x{9A44}\x{9A45}' . + '\x{9A46}\x{9A47}\x{9A48}\x{9A49}\x{9A4A}\x{9A4B}\x{9A4C}\x{9A4D}\x{9A4E}' . + '\x{9A4F}\x{9A50}\x{9A52}\x{9A53}\x{9A54}\x{9A55}\x{9A56}\x{9A57}\x{9A59}' . + '\x{9A5A}\x{9A5B}\x{9A5C}\x{9A5E}\x{9A5F}\x{9A60}\x{9A61}\x{9A62}\x{9A64}' . + '\x{9A65}\x{9A66}\x{9A67}\x{9A68}\x{9A69}\x{9A6A}\x{9A6B}\x{9A6C}\x{9A6D}' . + '\x{9A6E}\x{9A6F}\x{9A70}\x{9A71}\x{9A72}\x{9A73}\x{9A74}\x{9A75}\x{9A76}' . + '\x{9A77}\x{9A78}\x{9A79}\x{9A7A}\x{9A7B}\x{9A7C}\x{9A7D}\x{9A7E}\x{9A7F}' . + '\x{9A80}\x{9A81}\x{9A82}\x{9A83}\x{9A84}\x{9A85}\x{9A86}\x{9A87}\x{9A88}' . + '\x{9A89}\x{9A8A}\x{9A8B}\x{9A8C}\x{9A8D}\x{9A8E}\x{9A8F}\x{9A90}\x{9A91}' . + '\x{9A92}\x{9A93}\x{9A94}\x{9A95}\x{9A96}\x{9A97}\x{9A98}\x{9A99}\x{9A9A}' . + '\x{9A9B}\x{9A9C}\x{9A9D}\x{9A9E}\x{9A9F}\x{9AA0}\x{9AA1}\x{9AA2}\x{9AA3}' . + '\x{9AA4}\x{9AA5}\x{9AA6}\x{9AA7}\x{9AA8}\x{9AAA}\x{9AAB}\x{9AAC}\x{9AAD}' . + '\x{9AAE}\x{9AAF}\x{9AB0}\x{9AB1}\x{9AB2}\x{9AB3}\x{9AB4}\x{9AB5}\x{9AB6}' . + '\x{9AB7}\x{9AB8}\x{9AB9}\x{9ABA}\x{9ABB}\x{9ABC}\x{9ABE}\x{9ABF}\x{9AC0}' . + '\x{9AC1}\x{9AC2}\x{9AC3}\x{9AC4}\x{9AC5}\x{9AC6}\x{9AC7}\x{9AC9}\x{9ACA}' . + '\x{9ACB}\x{9ACC}\x{9ACD}\x{9ACE}\x{9ACF}\x{9AD0}\x{9AD1}\x{9AD2}\x{9AD3}' . + '\x{9AD4}\x{9AD5}\x{9AD6}\x{9AD8}\x{9AD9}\x{9ADA}\x{9ADB}\x{9ADC}\x{9ADD}' . + '\x{9ADE}\x{9ADF}\x{9AE1}\x{9AE2}\x{9AE3}\x{9AE5}\x{9AE6}\x{9AE7}\x{9AEA}' . + '\x{9AEB}\x{9AEC}\x{9AED}\x{9AEE}\x{9AEF}\x{9AF1}\x{9AF2}\x{9AF3}\x{9AF4}' . + '\x{9AF5}\x{9AF6}\x{9AF7}\x{9AF8}\x{9AF9}\x{9AFA}\x{9AFB}\x{9AFC}\x{9AFD}' . + '\x{9AFE}\x{9AFF}\x{9B01}\x{9B03}\x{9B04}\x{9B05}\x{9B06}\x{9B07}\x{9B08}' . + '\x{9B0A}\x{9B0B}\x{9B0C}\x{9B0D}\x{9B0E}\x{9B0F}\x{9B10}\x{9B11}\x{9B12}' . + '\x{9B13}\x{9B15}\x{9B16}\x{9B17}\x{9B18}\x{9B19}\x{9B1A}\x{9B1C}\x{9B1D}' . + '\x{9B1E}\x{9B1F}\x{9B20}\x{9B21}\x{9B22}\x{9B23}\x{9B24}\x{9B25}\x{9B26}' . + '\x{9B27}\x{9B28}\x{9B29}\x{9B2A}\x{9B2B}\x{9B2C}\x{9B2D}\x{9B2E}\x{9B2F}' . + '\x{9B30}\x{9B31}\x{9B32}\x{9B33}\x{9B35}\x{9B36}\x{9B37}\x{9B38}\x{9B39}' . + '\x{9B3A}\x{9B3B}\x{9B3C}\x{9B3E}\x{9B3F}\x{9B41}\x{9B42}\x{9B43}\x{9B44}' . + '\x{9B45}\x{9B46}\x{9B47}\x{9B48}\x{9B49}\x{9B4A}\x{9B4B}\x{9B4C}\x{9B4D}' . + '\x{9B4E}\x{9B4F}\x{9B51}\x{9B52}\x{9B53}\x{9B54}\x{9B55}\x{9B56}\x{9B58}' . + '\x{9B59}\x{9B5A}\x{9B5B}\x{9B5C}\x{9B5D}\x{9B5E}\x{9B5F}\x{9B60}\x{9B61}' . + '\x{9B63}\x{9B64}\x{9B65}\x{9B66}\x{9B67}\x{9B68}\x{9B69}\x{9B6A}\x{9B6B}' . + '\x{9B6C}\x{9B6D}\x{9B6E}\x{9B6F}\x{9B70}\x{9B71}\x{9B73}\x{9B74}\x{9B75}' . + '\x{9B76}\x{9B77}\x{9B78}\x{9B79}\x{9B7A}\x{9B7B}\x{9B7C}\x{9B7D}\x{9B7E}' . + '\x{9B7F}\x{9B80}\x{9B81}\x{9B82}\x{9B83}\x{9B84}\x{9B85}\x{9B86}\x{9B87}' . + '\x{9B88}\x{9B8A}\x{9B8B}\x{9B8D}\x{9B8E}\x{9B8F}\x{9B90}\x{9B91}\x{9B92}' . + '\x{9B93}\x{9B94}\x{9B95}\x{9B96}\x{9B97}\x{9B98}\x{9B9A}\x{9B9B}\x{9B9C}' . + '\x{9B9D}\x{9B9E}\x{9B9F}\x{9BA0}\x{9BA1}\x{9BA2}\x{9BA3}\x{9BA4}\x{9BA5}' . + '\x{9BA6}\x{9BA7}\x{9BA8}\x{9BA9}\x{9BAA}\x{9BAB}\x{9BAC}\x{9BAD}\x{9BAE}' . + '\x{9BAF}\x{9BB0}\x{9BB1}\x{9BB2}\x{9BB3}\x{9BB4}\x{9BB5}\x{9BB6}\x{9BB7}' . + '\x{9BB8}\x{9BB9}\x{9BBA}\x{9BBB}\x{9BBC}\x{9BBD}\x{9BBE}\x{9BBF}\x{9BC0}' . + '\x{9BC1}\x{9BC3}\x{9BC4}\x{9BC5}\x{9BC6}\x{9BC7}\x{9BC8}\x{9BC9}\x{9BCA}' . + '\x{9BCB}\x{9BCC}\x{9BCD}\x{9BCE}\x{9BCF}\x{9BD0}\x{9BD1}\x{9BD2}\x{9BD3}' . + '\x{9BD4}\x{9BD5}\x{9BD6}\x{9BD7}\x{9BD8}\x{9BD9}\x{9BDA}\x{9BDB}\x{9BDC}' . + '\x{9BDD}\x{9BDE}\x{9BDF}\x{9BE0}\x{9BE1}\x{9BE2}\x{9BE3}\x{9BE4}\x{9BE5}' . + '\x{9BE6}\x{9BE7}\x{9BE8}\x{9BE9}\x{9BEA}\x{9BEB}\x{9BEC}\x{9BED}\x{9BEE}' . + '\x{9BEF}\x{9BF0}\x{9BF1}\x{9BF2}\x{9BF3}\x{9BF4}\x{9BF5}\x{9BF7}\x{9BF8}' . + '\x{9BF9}\x{9BFA}\x{9BFB}\x{9BFC}\x{9BFD}\x{9BFE}\x{9BFF}\x{9C02}\x{9C05}' . + '\x{9C06}\x{9C07}\x{9C08}\x{9C09}\x{9C0A}\x{9C0B}\x{9C0C}\x{9C0D}\x{9C0E}' . + '\x{9C0F}\x{9C10}\x{9C11}\x{9C12}\x{9C13}\x{9C14}\x{9C15}\x{9C16}\x{9C17}' . + '\x{9C18}\x{9C19}\x{9C1A}\x{9C1B}\x{9C1C}\x{9C1D}\x{9C1E}\x{9C1F}\x{9C20}' . + '\x{9C21}\x{9C22}\x{9C23}\x{9C24}\x{9C25}\x{9C26}\x{9C27}\x{9C28}\x{9C29}' . + '\x{9C2A}\x{9C2B}\x{9C2C}\x{9C2D}\x{9C2F}\x{9C30}\x{9C31}\x{9C32}\x{9C33}' . + '\x{9C34}\x{9C35}\x{9C36}\x{9C37}\x{9C38}\x{9C39}\x{9C3A}\x{9C3B}\x{9C3C}' . + '\x{9C3D}\x{9C3E}\x{9C3F}\x{9C40}\x{9C41}\x{9C43}\x{9C44}\x{9C45}\x{9C46}' . + '\x{9C47}\x{9C48}\x{9C49}\x{9C4A}\x{9C4B}\x{9C4C}\x{9C4D}\x{9C4E}\x{9C50}' . + '\x{9C52}\x{9C53}\x{9C54}\x{9C55}\x{9C56}\x{9C57}\x{9C58}\x{9C59}\x{9C5A}' . + '\x{9C5B}\x{9C5C}\x{9C5D}\x{9C5E}\x{9C5F}\x{9C60}\x{9C62}\x{9C63}\x{9C65}' . + '\x{9C66}\x{9C67}\x{9C68}\x{9C69}\x{9C6A}\x{9C6B}\x{9C6C}\x{9C6D}\x{9C6E}' . + '\x{9C6F}\x{9C70}\x{9C71}\x{9C72}\x{9C73}\x{9C74}\x{9C75}\x{9C77}\x{9C78}' . + '\x{9C79}\x{9C7A}\x{9C7C}\x{9C7D}\x{9C7E}\x{9C7F}\x{9C80}\x{9C81}\x{9C82}' . + '\x{9C83}\x{9C84}\x{9C85}\x{9C86}\x{9C87}\x{9C88}\x{9C89}\x{9C8A}\x{9C8B}' . + '\x{9C8C}\x{9C8D}\x{9C8E}\x{9C8F}\x{9C90}\x{9C91}\x{9C92}\x{9C93}\x{9C94}' . + '\x{9C95}\x{9C96}\x{9C97}\x{9C98}\x{9C99}\x{9C9A}\x{9C9B}\x{9C9C}\x{9C9D}' . + '\x{9C9E}\x{9C9F}\x{9CA0}\x{9CA1}\x{9CA2}\x{9CA3}\x{9CA4}\x{9CA5}\x{9CA6}' . + '\x{9CA7}\x{9CA8}\x{9CA9}\x{9CAA}\x{9CAB}\x{9CAC}\x{9CAD}\x{9CAE}\x{9CAF}' . + '\x{9CB0}\x{9CB1}\x{9CB2}\x{9CB3}\x{9CB4}\x{9CB5}\x{9CB6}\x{9CB7}\x{9CB8}' . + '\x{9CB9}\x{9CBA}\x{9CBB}\x{9CBC}\x{9CBD}\x{9CBE}\x{9CBF}\x{9CC0}\x{9CC1}' . + '\x{9CC2}\x{9CC3}\x{9CC4}\x{9CC5}\x{9CC6}\x{9CC7}\x{9CC8}\x{9CC9}\x{9CCA}' . + '\x{9CCB}\x{9CCC}\x{9CCD}\x{9CCE}\x{9CCF}\x{9CD0}\x{9CD1}\x{9CD2}\x{9CD3}' . + '\x{9CD4}\x{9CD5}\x{9CD6}\x{9CD7}\x{9CD8}\x{9CD9}\x{9CDA}\x{9CDB}\x{9CDC}' . + '\x{9CDD}\x{9CDE}\x{9CDF}\x{9CE0}\x{9CE1}\x{9CE2}\x{9CE3}\x{9CE4}\x{9CE5}' . + '\x{9CE6}\x{9CE7}\x{9CE8}\x{9CE9}\x{9CEA}\x{9CEB}\x{9CEC}\x{9CED}\x{9CEE}' . + '\x{9CEF}\x{9CF0}\x{9CF1}\x{9CF2}\x{9CF3}\x{9CF4}\x{9CF5}\x{9CF6}\x{9CF7}' . + '\x{9CF8}\x{9CF9}\x{9CFA}\x{9CFB}\x{9CFC}\x{9CFD}\x{9CFE}\x{9CFF}\x{9D00}' . + '\x{9D01}\x{9D02}\x{9D03}\x{9D04}\x{9D05}\x{9D06}\x{9D07}\x{9D08}\x{9D09}' . + '\x{9D0A}\x{9D0B}\x{9D0F}\x{9D10}\x{9D12}\x{9D13}\x{9D14}\x{9D15}\x{9D16}' . + '\x{9D17}\x{9D18}\x{9D19}\x{9D1A}\x{9D1B}\x{9D1C}\x{9D1D}\x{9D1E}\x{9D1F}' . + '\x{9D20}\x{9D21}\x{9D22}\x{9D23}\x{9D24}\x{9D25}\x{9D26}\x{9D28}\x{9D29}' . + '\x{9D2B}\x{9D2D}\x{9D2E}\x{9D2F}\x{9D30}\x{9D31}\x{9D32}\x{9D33}\x{9D34}' . + '\x{9D36}\x{9D37}\x{9D38}\x{9D39}\x{9D3A}\x{9D3B}\x{9D3D}\x{9D3E}\x{9D3F}' . + '\x{9D40}\x{9D41}\x{9D42}\x{9D43}\x{9D45}\x{9D46}\x{9D47}\x{9D48}\x{9D49}' . + '\x{9D4A}\x{9D4B}\x{9D4C}\x{9D4D}\x{9D4E}\x{9D4F}\x{9D50}\x{9D51}\x{9D52}' . + '\x{9D53}\x{9D54}\x{9D55}\x{9D56}\x{9D57}\x{9D58}\x{9D59}\x{9D5A}\x{9D5B}' . + '\x{9D5C}\x{9D5D}\x{9D5E}\x{9D5F}\x{9D60}\x{9D61}\x{9D62}\x{9D63}\x{9D64}' . + '\x{9D65}\x{9D66}\x{9D67}\x{9D68}\x{9D69}\x{9D6A}\x{9D6B}\x{9D6C}\x{9D6E}' . + '\x{9D6F}\x{9D70}\x{9D71}\x{9D72}\x{9D73}\x{9D74}\x{9D75}\x{9D76}\x{9D77}' . + '\x{9D78}\x{9D79}\x{9D7A}\x{9D7B}\x{9D7C}\x{9D7D}\x{9D7E}\x{9D7F}\x{9D80}' . + '\x{9D81}\x{9D82}\x{9D83}\x{9D84}\x{9D85}\x{9D86}\x{9D87}\x{9D88}\x{9D89}' . + '\x{9D8A}\x{9D8B}\x{9D8C}\x{9D8D}\x{9D8E}\x{9D90}\x{9D91}\x{9D92}\x{9D93}' . + '\x{9D94}\x{9D96}\x{9D97}\x{9D98}\x{9D99}\x{9D9A}\x{9D9B}\x{9D9C}\x{9D9D}' . + '\x{9D9E}\x{9D9F}\x{9DA0}\x{9DA1}\x{9DA2}\x{9DA3}\x{9DA4}\x{9DA5}\x{9DA6}' . + '\x{9DA7}\x{9DA8}\x{9DA9}\x{9DAA}\x{9DAB}\x{9DAC}\x{9DAD}\x{9DAF}\x{9DB0}' . + '\x{9DB1}\x{9DB2}\x{9DB3}\x{9DB4}\x{9DB5}\x{9DB6}\x{9DB7}\x{9DB8}\x{9DB9}' . + '\x{9DBA}\x{9DBB}\x{9DBC}\x{9DBE}\x{9DBF}\x{9DC1}\x{9DC2}\x{9DC3}\x{9DC4}' . + '\x{9DC5}\x{9DC7}\x{9DC8}\x{9DC9}\x{9DCA}\x{9DCB}\x{9DCC}\x{9DCD}\x{9DCE}' . + '\x{9DCF}\x{9DD0}\x{9DD1}\x{9DD2}\x{9DD3}\x{9DD4}\x{9DD5}\x{9DD6}\x{9DD7}' . + '\x{9DD8}\x{9DD9}\x{9DDA}\x{9DDB}\x{9DDC}\x{9DDD}\x{9DDE}\x{9DDF}\x{9DE0}' . + '\x{9DE1}\x{9DE2}\x{9DE3}\x{9DE4}\x{9DE5}\x{9DE6}\x{9DE7}\x{9DE8}\x{9DE9}' . + '\x{9DEB}\x{9DEC}\x{9DED}\x{9DEE}\x{9DEF}\x{9DF0}\x{9DF1}\x{9DF2}\x{9DF3}' . + '\x{9DF4}\x{9DF5}\x{9DF6}\x{9DF7}\x{9DF8}\x{9DF9}\x{9DFA}\x{9DFB}\x{9DFD}' . + '\x{9DFE}\x{9DFF}\x{9E00}\x{9E01}\x{9E02}\x{9E03}\x{9E04}\x{9E05}\x{9E06}' . + '\x{9E07}\x{9E08}\x{9E09}\x{9E0A}\x{9E0B}\x{9E0C}\x{9E0D}\x{9E0F}\x{9E10}' . + '\x{9E11}\x{9E12}\x{9E13}\x{9E14}\x{9E15}\x{9E17}\x{9E18}\x{9E19}\x{9E1A}' . + '\x{9E1B}\x{9E1D}\x{9E1E}\x{9E1F}\x{9E20}\x{9E21}\x{9E22}\x{9E23}\x{9E24}' . + '\x{9E25}\x{9E26}\x{9E27}\x{9E28}\x{9E29}\x{9E2A}\x{9E2B}\x{9E2C}\x{9E2D}' . + '\x{9E2E}\x{9E2F}\x{9E30}\x{9E31}\x{9E32}\x{9E33}\x{9E34}\x{9E35}\x{9E36}' . + '\x{9E37}\x{9E38}\x{9E39}\x{9E3A}\x{9E3B}\x{9E3C}\x{9E3D}\x{9E3E}\x{9E3F}' . + '\x{9E40}\x{9E41}\x{9E42}\x{9E43}\x{9E44}\x{9E45}\x{9E46}\x{9E47}\x{9E48}' . + '\x{9E49}\x{9E4A}\x{9E4B}\x{9E4C}\x{9E4D}\x{9E4E}\x{9E4F}\x{9E50}\x{9E51}' . + '\x{9E52}\x{9E53}\x{9E54}\x{9E55}\x{9E56}\x{9E57}\x{9E58}\x{9E59}\x{9E5A}' . + '\x{9E5B}\x{9E5C}\x{9E5D}\x{9E5E}\x{9E5F}\x{9E60}\x{9E61}\x{9E62}\x{9E63}' . + '\x{9E64}\x{9E65}\x{9E66}\x{9E67}\x{9E68}\x{9E69}\x{9E6A}\x{9E6B}\x{9E6C}' . + '\x{9E6D}\x{9E6E}\x{9E6F}\x{9E70}\x{9E71}\x{9E72}\x{9E73}\x{9E74}\x{9E75}' . + '\x{9E76}\x{9E77}\x{9E79}\x{9E7A}\x{9E7C}\x{9E7D}\x{9E7E}\x{9E7F}\x{9E80}' . + '\x{9E81}\x{9E82}\x{9E83}\x{9E84}\x{9E85}\x{9E86}\x{9E87}\x{9E88}\x{9E89}' . + '\x{9E8A}\x{9E8B}\x{9E8C}\x{9E8D}\x{9E8E}\x{9E91}\x{9E92}\x{9E93}\x{9E94}' . + '\x{9E96}\x{9E97}\x{9E99}\x{9E9A}\x{9E9B}\x{9E9C}\x{9E9D}\x{9E9F}\x{9EA0}' . + '\x{9EA1}\x{9EA3}\x{9EA4}\x{9EA5}\x{9EA6}\x{9EA7}\x{9EA8}\x{9EA9}\x{9EAA}' . + '\x{9EAD}\x{9EAE}\x{9EAF}\x{9EB0}\x{9EB2}\x{9EB3}\x{9EB4}\x{9EB5}\x{9EB6}' . + '\x{9EB7}\x{9EB8}\x{9EBB}\x{9EBC}\x{9EBD}\x{9EBE}\x{9EBF}\x{9EC0}\x{9EC1}' . + '\x{9EC2}\x{9EC3}\x{9EC4}\x{9EC5}\x{9EC6}\x{9EC7}\x{9EC8}\x{9EC9}\x{9ECA}' . + '\x{9ECB}\x{9ECC}\x{9ECD}\x{9ECE}\x{9ECF}\x{9ED0}\x{9ED1}\x{9ED2}\x{9ED3}' . + '\x{9ED4}\x{9ED5}\x{9ED6}\x{9ED7}\x{9ED8}\x{9ED9}\x{9EDA}\x{9EDB}\x{9EDC}' . + '\x{9EDD}\x{9EDE}\x{9EDF}\x{9EE0}\x{9EE1}\x{9EE2}\x{9EE3}\x{9EE4}\x{9EE5}' . + '\x{9EE6}\x{9EE7}\x{9EE8}\x{9EE9}\x{9EEA}\x{9EEB}\x{9EED}\x{9EEE}\x{9EEF}' . + '\x{9EF0}\x{9EF2}\x{9EF3}\x{9EF4}\x{9EF5}\x{9EF6}\x{9EF7}\x{9EF8}\x{9EF9}' . + '\x{9EFA}\x{9EFB}\x{9EFC}\x{9EFD}\x{9EFE}\x{9EFF}\x{9F00}\x{9F01}\x{9F02}' . + '\x{9F04}\x{9F05}\x{9F06}\x{9F07}\x{9F08}\x{9F09}\x{9F0A}\x{9F0B}\x{9F0C}' . + '\x{9F0D}\x{9F0E}\x{9F0F}\x{9F10}\x{9F12}\x{9F13}\x{9F15}\x{9F16}\x{9F17}' . + '\x{9F18}\x{9F19}\x{9F1A}\x{9F1B}\x{9F1C}\x{9F1D}\x{9F1E}\x{9F1F}\x{9F20}' . + '\x{9F22}\x{9F23}\x{9F24}\x{9F25}\x{9F27}\x{9F28}\x{9F29}\x{9F2A}\x{9F2B}' . + '\x{9F2C}\x{9F2D}\x{9F2E}\x{9F2F}\x{9F30}\x{9F31}\x{9F32}\x{9F33}\x{9F34}' . + '\x{9F35}\x{9F36}\x{9F37}\x{9F38}\x{9F39}\x{9F3A}\x{9F3B}\x{9F3C}\x{9F3D}' . + '\x{9F3E}\x{9F3F}\x{9F40}\x{9F41}\x{9F42}\x{9F43}\x{9F44}\x{9F46}\x{9F47}' . + '\x{9F48}\x{9F49}\x{9F4A}\x{9F4B}\x{9F4C}\x{9F4D}\x{9F4E}\x{9F4F}\x{9F50}' . + '\x{9F51}\x{9F52}\x{9F54}\x{9F55}\x{9F56}\x{9F57}\x{9F58}\x{9F59}\x{9F5A}' . + '\x{9F5B}\x{9F5C}\x{9F5D}\x{9F5E}\x{9F5F}\x{9F60}\x{9F61}\x{9F63}\x{9F64}' . + '\x{9F65}\x{9F66}\x{9F67}\x{9F68}\x{9F69}\x{9F6A}\x{9F6B}\x{9F6C}\x{9F6E}' . + '\x{9F6F}\x{9F70}\x{9F71}\x{9F72}\x{9F73}\x{9F74}\x{9F75}\x{9F76}\x{9F77}' . + '\x{9F78}\x{9F79}\x{9F7A}\x{9F7B}\x{9F7C}\x{9F7D}\x{9F7E}\x{9F7F}\x{9F80}' . + '\x{9F81}\x{9F82}\x{9F83}\x{9F84}\x{9F85}\x{9F86}\x{9F87}\x{9F88}\x{9F89}' . + '\x{9F8A}\x{9F8B}\x{9F8C}\x{9F8D}\x{9F8E}\x{9F8F}\x{9F90}\x{9F91}\x{9F92}' . + '\x{9F93}\x{9F94}\x{9F95}\x{9F96}\x{9F97}\x{9F98}\x{9F99}\x{9F9A}\x{9F9B}' . + '\x{9F9C}\x{9F9D}\x{9F9E}\x{9F9F}\x{9FA0}\x{9FA2}\x{9FA4}\x{9FA5}]{1,20}$/iu', +]; diff --git a/lib/laminas/laminas-validator/src/Hostname/Cn.php b/lib/laminas/laminas-validator/src/Hostname/Cn.php new file mode 100644 index 000000000..cab93d4b2 --- /dev/null +++ b/lib/laminas/laminas-validator/src/Hostname/Cn.php @@ -0,0 +1,2184 @@ + '/^[\x{002d}0-9a-z\x{3447}\x{3473}\x{359E}\x{360E}\x{361A}\x{3918}\x{396E}\x{39CF}\x{39D0}' . + '\x{39DF}\x{3A73}\x{3B4E}\x{3C6E}\x{3CE0}\x{4056}\x{415F}\x{4337}\x{43AC}' . + '\x{43B1}\x{43DD}\x{44D6}\x{464C}\x{4661}\x{4723}\x{4729}\x{477C}\x{478D}' . + '\x{4947}\x{497A}\x{497D}\x{4982}\x{4983}\x{4985}\x{4986}\x{499B}\x{499F}' . + '\x{49B6}\x{49B7}\x{4C77}\x{4C9F}\x{4CA0}\x{4CA1}\x{4CA2}\x{4CA3}\x{4D13}' . + '\x{4D14}\x{4D15}\x{4D16}\x{4D17}\x{4D18}\x{4D19}\x{4DAE}\x{4E00}\x{4E01}' . + '\x{4E02}\x{4E03}\x{4E04}\x{4E05}\x{4E06}\x{4E07}\x{4E08}\x{4E09}\x{4E0A}' . + '\x{4E0B}\x{4E0C}\x{4E0D}\x{4E0E}\x{4E0F}\x{4E10}\x{4E11}\x{4E13}\x{4E14}' . + '\x{4E15}\x{4E16}\x{4E17}\x{4E18}\x{4E19}\x{4E1A}\x{4E1B}\x{4E1C}\x{4E1D}' . + '\x{4E1E}\x{4E1F}\x{4E20}\x{4E21}\x{4E22}\x{4E23}\x{4E24}\x{4E25}\x{4E26}' . + '\x{4E27}\x{4E28}\x{4E2A}\x{4E2B}\x{4E2C}\x{4E2D}\x{4E2E}\x{4E2F}\x{4E30}' . + '\x{4E31}\x{4E32}\x{4E33}\x{4E34}\x{4E35}\x{4E36}\x{4E37}\x{4E38}\x{4E39}' . + '\x{4E3A}\x{4E3B}\x{4E3C}\x{4E3D}\x{4E3E}\x{4E3F}\x{4E40}\x{4E41}\x{4E42}' . + '\x{4E43}\x{4E44}\x{4E45}\x{4E46}\x{4E47}\x{4E48}\x{4E49}\x{4E4A}\x{4E4B}' . + '\x{4E4C}\x{4E4D}\x{4E4E}\x{4E4F}\x{4E50}\x{4E51}\x{4E52}\x{4E53}\x{4E54}' . + '\x{4E56}\x{4E57}\x{4E58}\x{4E59}\x{4E5A}\x{4E5B}\x{4E5C}\x{4E5D}\x{4E5E}' . + '\x{4E5F}\x{4E60}\x{4E61}\x{4E62}\x{4E63}\x{4E64}\x{4E65}\x{4E66}\x{4E67}' . + '\x{4E69}\x{4E6A}\x{4E6B}\x{4E6C}\x{4E6D}\x{4E6E}\x{4E6F}\x{4E70}\x{4E71}' . + '\x{4E72}\x{4E73}\x{4E74}\x{4E75}\x{4E76}\x{4E77}\x{4E78}\x{4E7A}\x{4E7B}' . + '\x{4E7C}\x{4E7D}\x{4E7E}\x{4E7F}\x{4E80}\x{4E81}\x{4E82}\x{4E83}\x{4E84}' . + '\x{4E85}\x{4E86}\x{4E87}\x{4E88}\x{4E89}\x{4E8B}\x{4E8C}\x{4E8D}\x{4E8E}' . + '\x{4E8F}\x{4E90}\x{4E91}\x{4E92}\x{4E93}\x{4E94}\x{4E95}\x{4E97}\x{4E98}' . + '\x{4E99}\x{4E9A}\x{4E9B}\x{4E9C}\x{4E9D}\x{4E9E}\x{4E9F}\x{4EA0}\x{4EA1}' . + '\x{4EA2}\x{4EA4}\x{4EA5}\x{4EA6}\x{4EA7}\x{4EA8}\x{4EA9}\x{4EAA}\x{4EAB}' . + '\x{4EAC}\x{4EAD}\x{4EAE}\x{4EAF}\x{4EB0}\x{4EB1}\x{4EB2}\x{4EB3}\x{4EB4}' . + '\x{4EB5}\x{4EB6}\x{4EB7}\x{4EB8}\x{4EB9}\x{4EBA}\x{4EBB}\x{4EBD}\x{4EBE}' . + '\x{4EBF}\x{4EC0}\x{4EC1}\x{4EC2}\x{4EC3}\x{4EC4}\x{4EC5}\x{4EC6}\x{4EC7}' . + '\x{4EC8}\x{4EC9}\x{4ECA}\x{4ECB}\x{4ECD}\x{4ECE}\x{4ECF}\x{4ED0}\x{4ED1}' . + '\x{4ED2}\x{4ED3}\x{4ED4}\x{4ED5}\x{4ED6}\x{4ED7}\x{4ED8}\x{4ED9}\x{4EDA}' . + '\x{4EDB}\x{4EDC}\x{4EDD}\x{4EDE}\x{4EDF}\x{4EE0}\x{4EE1}\x{4EE2}\x{4EE3}' . + '\x{4EE4}\x{4EE5}\x{4EE6}\x{4EE8}\x{4EE9}\x{4EEA}\x{4EEB}\x{4EEC}\x{4EEF}' . + '\x{4EF0}\x{4EF1}\x{4EF2}\x{4EF3}\x{4EF4}\x{4EF5}\x{4EF6}\x{4EF7}\x{4EFB}' . + '\x{4EFD}\x{4EFF}\x{4F00}\x{4F01}\x{4F02}\x{4F03}\x{4F04}\x{4F05}\x{4F06}' . + '\x{4F08}\x{4F09}\x{4F0A}\x{4F0B}\x{4F0C}\x{4F0D}\x{4F0E}\x{4F0F}\x{4F10}' . + '\x{4F11}\x{4F12}\x{4F13}\x{4F14}\x{4F15}\x{4F17}\x{4F18}\x{4F19}\x{4F1A}' . + '\x{4F1B}\x{4F1C}\x{4F1D}\x{4F1E}\x{4F1F}\x{4F20}\x{4F21}\x{4F22}\x{4F23}' . + '\x{4F24}\x{4F25}\x{4F26}\x{4F27}\x{4F29}\x{4F2A}\x{4F2B}\x{4F2C}\x{4F2D}' . + '\x{4F2E}\x{4F2F}\x{4F30}\x{4F32}\x{4F33}\x{4F34}\x{4F36}\x{4F38}\x{4F39}' . + '\x{4F3A}\x{4F3B}\x{4F3C}\x{4F3D}\x{4F3E}\x{4F3F}\x{4F41}\x{4F42}\x{4F43}' . + '\x{4F45}\x{4F46}\x{4F47}\x{4F48}\x{4F49}\x{4F4A}\x{4F4B}\x{4F4C}\x{4F4D}' . + '\x{4F4E}\x{4F4F}\x{4F50}\x{4F51}\x{4F52}\x{4F53}\x{4F54}\x{4F55}\x{4F56}' . + '\x{4F57}\x{4F58}\x{4F59}\x{4F5A}\x{4F5B}\x{4F5C}\x{4F5D}\x{4F5E}\x{4F5F}' . + '\x{4F60}\x{4F61}\x{4F62}\x{4F63}\x{4F64}\x{4F65}\x{4F66}\x{4F67}\x{4F68}' . + '\x{4F69}\x{4F6A}\x{4F6B}\x{4F6C}\x{4F6D}\x{4F6E}\x{4F6F}\x{4F70}\x{4F72}' . + '\x{4F73}\x{4F74}\x{4F75}\x{4F76}\x{4F77}\x{4F78}\x{4F79}\x{4F7A}\x{4F7B}' . + '\x{4F7C}\x{4F7D}\x{4F7E}\x{4F7F}\x{4F80}\x{4F81}\x{4F82}\x{4F83}\x{4F84}' . + '\x{4F85}\x{4F86}\x{4F87}\x{4F88}\x{4F89}\x{4F8A}\x{4F8B}\x{4F8D}\x{4F8F}' . + '\x{4F90}\x{4F91}\x{4F92}\x{4F93}\x{4F94}\x{4F95}\x{4F96}\x{4F97}\x{4F98}' . + '\x{4F99}\x{4F9A}\x{4F9B}\x{4F9C}\x{4F9D}\x{4F9E}\x{4F9F}\x{4FA0}\x{4FA1}' . + '\x{4FA3}\x{4FA4}\x{4FA5}\x{4FA6}\x{4FA7}\x{4FA8}\x{4FA9}\x{4FAA}\x{4FAB}' . + '\x{4FAC}\x{4FAE}\x{4FAF}\x{4FB0}\x{4FB1}\x{4FB2}\x{4FB3}\x{4FB4}\x{4FB5}' . + '\x{4FB6}\x{4FB7}\x{4FB8}\x{4FB9}\x{4FBA}\x{4FBB}\x{4FBC}\x{4FBE}\x{4FBF}' . + '\x{4FC0}\x{4FC1}\x{4FC2}\x{4FC3}\x{4FC4}\x{4FC5}\x{4FC7}\x{4FC9}\x{4FCA}' . + '\x{4FCB}\x{4FCD}\x{4FCE}\x{4FCF}\x{4FD0}\x{4FD1}\x{4FD2}\x{4FD3}\x{4FD4}' . + '\x{4FD5}\x{4FD6}\x{4FD7}\x{4FD8}\x{4FD9}\x{4FDA}\x{4FDB}\x{4FDC}\x{4FDD}' . + '\x{4FDE}\x{4FDF}\x{4FE0}\x{4FE1}\x{4FE3}\x{4FE4}\x{4FE5}\x{4FE6}\x{4FE7}' . + '\x{4FE8}\x{4FE9}\x{4FEA}\x{4FEB}\x{4FEC}\x{4FED}\x{4FEE}\x{4FEF}\x{4FF0}' . + '\x{4FF1}\x{4FF2}\x{4FF3}\x{4FF4}\x{4FF5}\x{4FF6}\x{4FF7}\x{4FF8}\x{4FF9}' . + '\x{4FFA}\x{4FFB}\x{4FFE}\x{4FFF}\x{5000}\x{5001}\x{5002}\x{5003}\x{5004}' . + '\x{5005}\x{5006}\x{5007}\x{5008}\x{5009}\x{500A}\x{500B}\x{500C}\x{500D}' . + '\x{500E}\x{500F}\x{5011}\x{5012}\x{5013}\x{5014}\x{5015}\x{5016}\x{5017}' . + '\x{5018}\x{5019}\x{501A}\x{501B}\x{501C}\x{501D}\x{501E}\x{501F}\x{5020}' . + '\x{5021}\x{5022}\x{5023}\x{5024}\x{5025}\x{5026}\x{5027}\x{5028}\x{5029}' . + '\x{502A}\x{502B}\x{502C}\x{502D}\x{502E}\x{502F}\x{5030}\x{5031}\x{5032}' . + '\x{5033}\x{5035}\x{5036}\x{5037}\x{5039}\x{503A}\x{503B}\x{503C}\x{503E}' . + '\x{503F}\x{5040}\x{5041}\x{5043}\x{5044}\x{5045}\x{5046}\x{5047}\x{5048}' . + '\x{5049}\x{504A}\x{504B}\x{504C}\x{504D}\x{504E}\x{504F}\x{5051}\x{5053}' . + '\x{5054}\x{5055}\x{5056}\x{5057}\x{5059}\x{505A}\x{505B}\x{505C}\x{505D}' . + '\x{505E}\x{505F}\x{5060}\x{5061}\x{5062}\x{5063}\x{5064}\x{5065}\x{5066}' . + '\x{5067}\x{5068}\x{5069}\x{506A}\x{506B}\x{506C}\x{506D}\x{506E}\x{506F}' . + '\x{5070}\x{5071}\x{5072}\x{5073}\x{5074}\x{5075}\x{5076}\x{5077}\x{5078}' . + '\x{5079}\x{507A}\x{507B}\x{507D}\x{507E}\x{507F}\x{5080}\x{5082}\x{5083}' . + '\x{5084}\x{5085}\x{5086}\x{5087}\x{5088}\x{5089}\x{508A}\x{508B}\x{508C}' . + '\x{508D}\x{508E}\x{508F}\x{5090}\x{5091}\x{5092}\x{5094}\x{5095}\x{5096}' . + '\x{5098}\x{5099}\x{509A}\x{509B}\x{509C}\x{509D}\x{509E}\x{50A2}\x{50A3}' . + '\x{50A4}\x{50A5}\x{50A6}\x{50A7}\x{50A8}\x{50A9}\x{50AA}\x{50AB}\x{50AC}' . + '\x{50AD}\x{50AE}\x{50AF}\x{50B0}\x{50B1}\x{50B2}\x{50B3}\x{50B4}\x{50B5}' . + '\x{50B6}\x{50B7}\x{50B8}\x{50BA}\x{50BB}\x{50BC}\x{50BD}\x{50BE}\x{50BF}' . + '\x{50C0}\x{50C1}\x{50C2}\x{50C4}\x{50C5}\x{50C6}\x{50C7}\x{50C8}\x{50C9}' . + '\x{50CA}\x{50CB}\x{50CC}\x{50CD}\x{50CE}\x{50CF}\x{50D0}\x{50D1}\x{50D2}' . + '\x{50D3}\x{50D4}\x{50D5}\x{50D6}\x{50D7}\x{50D9}\x{50DA}\x{50DB}\x{50DC}' . + '\x{50DD}\x{50DE}\x{50E0}\x{50E3}\x{50E4}\x{50E5}\x{50E6}\x{50E7}\x{50E8}' . + '\x{50E9}\x{50EA}\x{50EC}\x{50ED}\x{50EE}\x{50EF}\x{50F0}\x{50F1}\x{50F2}' . + '\x{50F3}\x{50F5}\x{50F6}\x{50F8}\x{50F9}\x{50FA}\x{50FB}\x{50FC}\x{50FD}' . + '\x{50FE}\x{50FF}\x{5100}\x{5101}\x{5102}\x{5103}\x{5104}\x{5105}\x{5106}' . + '\x{5107}\x{5108}\x{5109}\x{510A}\x{510B}\x{510C}\x{510D}\x{510E}\x{510F}' . + '\x{5110}\x{5111}\x{5112}\x{5113}\x{5114}\x{5115}\x{5116}\x{5117}\x{5118}' . + '\x{5119}\x{511A}\x{511C}\x{511D}\x{511E}\x{511F}\x{5120}\x{5121}\x{5122}' . + '\x{5123}\x{5124}\x{5125}\x{5126}\x{5127}\x{5129}\x{512A}\x{512C}\x{512D}' . + '\x{512E}\x{512F}\x{5130}\x{5131}\x{5132}\x{5133}\x{5134}\x{5135}\x{5136}' . + '\x{5137}\x{5138}\x{5139}\x{513A}\x{513B}\x{513C}\x{513D}\x{513E}\x{513F}' . + '\x{5140}\x{5141}\x{5143}\x{5144}\x{5145}\x{5146}\x{5147}\x{5148}\x{5149}' . + '\x{514B}\x{514C}\x{514D}\x{514E}\x{5150}\x{5151}\x{5152}\x{5154}\x{5155}' . + '\x{5156}\x{5157}\x{5159}\x{515A}\x{515B}\x{515C}\x{515D}\x{515E}\x{515F}' . + '\x{5161}\x{5162}\x{5163}\x{5165}\x{5166}\x{5167}\x{5168}\x{5169}\x{516A}' . + '\x{516B}\x{516C}\x{516D}\x{516E}\x{516F}\x{5170}\x{5171}\x{5173}\x{5174}' . + '\x{5175}\x{5176}\x{5177}\x{5178}\x{5179}\x{517A}\x{517B}\x{517C}\x{517D}' . + '\x{517F}\x{5180}\x{5181}\x{5182}\x{5185}\x{5186}\x{5187}\x{5188}\x{5189}' . + '\x{518A}\x{518B}\x{518C}\x{518D}\x{518F}\x{5190}\x{5191}\x{5192}\x{5193}' . + '\x{5194}\x{5195}\x{5196}\x{5197}\x{5198}\x{5199}\x{519A}\x{519B}\x{519C}' . + '\x{519D}\x{519E}\x{519F}\x{51A0}\x{51A2}\x{51A4}\x{51A5}\x{51A6}\x{51A7}' . + '\x{51A8}\x{51AA}\x{51AB}\x{51AC}\x{51AE}\x{51AF}\x{51B0}\x{51B1}\x{51B2}' . + '\x{51B3}\x{51B5}\x{51B6}\x{51B7}\x{51B9}\x{51BB}\x{51BC}\x{51BD}\x{51BE}' . + '\x{51BF}\x{51C0}\x{51C1}\x{51C3}\x{51C4}\x{51C5}\x{51C6}\x{51C7}\x{51C8}' . + '\x{51C9}\x{51CA}\x{51CB}\x{51CC}\x{51CD}\x{51CE}\x{51CF}\x{51D0}\x{51D1}' . + '\x{51D4}\x{51D5}\x{51D6}\x{51D7}\x{51D8}\x{51D9}\x{51DA}\x{51DB}\x{51DC}' . + '\x{51DD}\x{51DE}\x{51E0}\x{51E1}\x{51E2}\x{51E3}\x{51E4}\x{51E5}\x{51E7}' . + '\x{51E8}\x{51E9}\x{51EA}\x{51EB}\x{51ED}\x{51EF}\x{51F0}\x{51F1}\x{51F3}' . + '\x{51F4}\x{51F5}\x{51F6}\x{51F7}\x{51F8}\x{51F9}\x{51FA}\x{51FB}\x{51FC}' . + '\x{51FD}\x{51FE}\x{51FF}\x{5200}\x{5201}\x{5202}\x{5203}\x{5204}\x{5205}' . + '\x{5206}\x{5207}\x{5208}\x{5209}\x{520A}\x{520B}\x{520C}\x{520D}\x{520E}' . + '\x{520F}\x{5210}\x{5211}\x{5212}\x{5213}\x{5214}\x{5215}\x{5216}\x{5217}' . + '\x{5218}\x{5219}\x{521A}\x{521B}\x{521C}\x{521D}\x{521E}\x{521F}\x{5220}' . + '\x{5221}\x{5222}\x{5223}\x{5224}\x{5225}\x{5226}\x{5228}\x{5229}\x{522A}' . + '\x{522B}\x{522C}\x{522D}\x{522E}\x{522F}\x{5230}\x{5231}\x{5232}\x{5233}' . + '\x{5234}\x{5235}\x{5236}\x{5237}\x{5238}\x{5239}\x{523A}\x{523B}\x{523C}' . + '\x{523D}\x{523E}\x{523F}\x{5240}\x{5241}\x{5242}\x{5243}\x{5244}\x{5245}' . + '\x{5246}\x{5247}\x{5248}\x{5249}\x{524A}\x{524B}\x{524C}\x{524D}\x{524E}' . + '\x{5250}\x{5251}\x{5252}\x{5254}\x{5255}\x{5256}\x{5257}\x{5258}\x{5259}' . + '\x{525A}\x{525B}\x{525C}\x{525D}\x{525E}\x{525F}\x{5260}\x{5261}\x{5262}' . + '\x{5263}\x{5264}\x{5265}\x{5267}\x{5268}\x{5269}\x{526A}\x{526B}\x{526C}' . + '\x{526D}\x{526E}\x{526F}\x{5270}\x{5272}\x{5273}\x{5274}\x{5275}\x{5276}' . + '\x{5277}\x{5278}\x{527A}\x{527B}\x{527C}\x{527D}\x{527E}\x{527F}\x{5280}' . + '\x{5281}\x{5282}\x{5283}\x{5284}\x{5286}\x{5287}\x{5288}\x{5289}\x{528A}' . + '\x{528B}\x{528C}\x{528D}\x{528F}\x{5290}\x{5291}\x{5292}\x{5293}\x{5294}' . + '\x{5295}\x{5296}\x{5297}\x{5298}\x{5299}\x{529A}\x{529B}\x{529C}\x{529D}' . + '\x{529E}\x{529F}\x{52A0}\x{52A1}\x{52A2}\x{52A3}\x{52A5}\x{52A6}\x{52A7}' . + '\x{52A8}\x{52A9}\x{52AA}\x{52AB}\x{52AC}\x{52AD}\x{52AE}\x{52AF}\x{52B0}' . + '\x{52B1}\x{52B2}\x{52B3}\x{52B4}\x{52B5}\x{52B6}\x{52B7}\x{52B8}\x{52B9}' . + '\x{52BA}\x{52BB}\x{52BC}\x{52BD}\x{52BE}\x{52BF}\x{52C0}\x{52C1}\x{52C2}' . + '\x{52C3}\x{52C6}\x{52C7}\x{52C9}\x{52CA}\x{52CB}\x{52CD}\x{52CF}\x{52D0}' . + '\x{52D2}\x{52D3}\x{52D5}\x{52D6}\x{52D7}\x{52D8}\x{52D9}\x{52DA}\x{52DB}' . + '\x{52DC}\x{52DD}\x{52DE}\x{52DF}\x{52E0}\x{52E2}\x{52E3}\x{52E4}\x{52E6}' . + '\x{52E7}\x{52E8}\x{52E9}\x{52EA}\x{52EB}\x{52EC}\x{52ED}\x{52EF}\x{52F0}' . + '\x{52F1}\x{52F2}\x{52F3}\x{52F4}\x{52F5}\x{52F6}\x{52F7}\x{52F8}\x{52F9}' . + '\x{52FA}\x{52FB}\x{52FC}\x{52FD}\x{52FE}\x{52FF}\x{5300}\x{5301}\x{5302}' . + '\x{5305}\x{5306}\x{5307}\x{5308}\x{5309}\x{530A}\x{530B}\x{530C}\x{530D}' . + '\x{530E}\x{530F}\x{5310}\x{5311}\x{5312}\x{5313}\x{5314}\x{5315}\x{5316}' . + '\x{5317}\x{5319}\x{531A}\x{531C}\x{531D}\x{531F}\x{5320}\x{5321}\x{5322}' . + '\x{5323}\x{5324}\x{5325}\x{5326}\x{5328}\x{532A}\x{532B}\x{532C}\x{532D}' . + '\x{532E}\x{532F}\x{5330}\x{5331}\x{5333}\x{5334}\x{5337}\x{5339}\x{533A}' . + '\x{533B}\x{533C}\x{533D}\x{533E}\x{533F}\x{5340}\x{5341}\x{5343}\x{5344}' . + '\x{5345}\x{5346}\x{5347}\x{5348}\x{5349}\x{534A}\x{534B}\x{534C}\x{534D}' . + '\x{534E}\x{534F}\x{5350}\x{5351}\x{5352}\x{5353}\x{5354}\x{5355}\x{5356}' . + '\x{5357}\x{5358}\x{5359}\x{535A}\x{535C}\x{535E}\x{535F}\x{5360}\x{5361}' . + '\x{5362}\x{5363}\x{5364}\x{5365}\x{5366}\x{5367}\x{5369}\x{536B}\x{536C}' . + '\x{536E}\x{536F}\x{5370}\x{5371}\x{5372}\x{5373}\x{5374}\x{5375}\x{5376}' . + '\x{5377}\x{5378}\x{5379}\x{537A}\x{537B}\x{537C}\x{537D}\x{537E}\x{537F}' . + '\x{5381}\x{5382}\x{5383}\x{5384}\x{5385}\x{5386}\x{5387}\x{5388}\x{5389}' . + '\x{538A}\x{538B}\x{538C}\x{538D}\x{538E}\x{538F}\x{5390}\x{5391}\x{5392}' . + '\x{5393}\x{5394}\x{5395}\x{5396}\x{5397}\x{5398}\x{5399}\x{539A}\x{539B}' . + '\x{539C}\x{539D}\x{539E}\x{539F}\x{53A0}\x{53A2}\x{53A3}\x{53A4}\x{53A5}' . + '\x{53A6}\x{53A7}\x{53A8}\x{53A9}\x{53AC}\x{53AD}\x{53AE}\x{53B0}\x{53B1}' . + '\x{53B2}\x{53B3}\x{53B4}\x{53B5}\x{53B6}\x{53B7}\x{53B8}\x{53B9}\x{53BB}' . + '\x{53BC}\x{53BD}\x{53BE}\x{53BF}\x{53C0}\x{53C1}\x{53C2}\x{53C3}\x{53C4}' . + '\x{53C6}\x{53C7}\x{53C8}\x{53C9}\x{53CA}\x{53CB}\x{53CC}\x{53CD}\x{53CE}' . + '\x{53D0}\x{53D1}\x{53D2}\x{53D3}\x{53D4}\x{53D5}\x{53D6}\x{53D7}\x{53D8}' . + '\x{53D9}\x{53DB}\x{53DC}\x{53DF}\x{53E0}\x{53E1}\x{53E2}\x{53E3}\x{53E4}' . + '\x{53E5}\x{53E6}\x{53E8}\x{53E9}\x{53EA}\x{53EB}\x{53EC}\x{53ED}\x{53EE}' . + '\x{53EF}\x{53F0}\x{53F1}\x{53F2}\x{53F3}\x{53F4}\x{53F5}\x{53F6}\x{53F7}' . + '\x{53F8}\x{53F9}\x{53FA}\x{53FB}\x{53FC}\x{53FD}\x{53FE}\x{5401}\x{5402}' . + '\x{5403}\x{5404}\x{5405}\x{5406}\x{5407}\x{5408}\x{5409}\x{540A}\x{540B}' . + '\x{540C}\x{540D}\x{540E}\x{540F}\x{5410}\x{5411}\x{5412}\x{5413}\x{5414}' . + '\x{5415}\x{5416}\x{5417}\x{5418}\x{5419}\x{541B}\x{541C}\x{541D}\x{541E}' . + '\x{541F}\x{5420}\x{5421}\x{5423}\x{5424}\x{5425}\x{5426}\x{5427}\x{5428}' . + '\x{5429}\x{542A}\x{542B}\x{542C}\x{542D}\x{542E}\x{542F}\x{5430}\x{5431}' . + '\x{5432}\x{5433}\x{5434}\x{5435}\x{5436}\x{5437}\x{5438}\x{5439}\x{543A}' . + '\x{543B}\x{543C}\x{543D}\x{543E}\x{543F}\x{5440}\x{5441}\x{5442}\x{5443}' . + '\x{5444}\x{5445}\x{5446}\x{5447}\x{5448}\x{5449}\x{544A}\x{544B}\x{544D}' . + '\x{544E}\x{544F}\x{5450}\x{5451}\x{5452}\x{5453}\x{5454}\x{5455}\x{5456}' . + '\x{5457}\x{5458}\x{5459}\x{545A}\x{545B}\x{545C}\x{545E}\x{545F}\x{5460}' . + '\x{5461}\x{5462}\x{5463}\x{5464}\x{5465}\x{5466}\x{5467}\x{5468}\x{546A}' . + '\x{546B}\x{546C}\x{546D}\x{546E}\x{546F}\x{5470}\x{5471}\x{5472}\x{5473}' . + '\x{5474}\x{5475}\x{5476}\x{5477}\x{5478}\x{5479}\x{547A}\x{547B}\x{547C}' . + '\x{547D}\x{547E}\x{547F}\x{5480}\x{5481}\x{5482}\x{5483}\x{5484}\x{5485}' . + '\x{5486}\x{5487}\x{5488}\x{5489}\x{548B}\x{548C}\x{548D}\x{548E}\x{548F}' . + '\x{5490}\x{5491}\x{5492}\x{5493}\x{5494}\x{5495}\x{5496}\x{5497}\x{5498}' . + '\x{5499}\x{549A}\x{549B}\x{549C}\x{549D}\x{549E}\x{549F}\x{54A0}\x{54A1}' . + '\x{54A2}\x{54A3}\x{54A4}\x{54A5}\x{54A6}\x{54A7}\x{54A8}\x{54A9}\x{54AA}' . + '\x{54AB}\x{54AC}\x{54AD}\x{54AE}\x{54AF}\x{54B0}\x{54B1}\x{54B2}\x{54B3}' . + '\x{54B4}\x{54B6}\x{54B7}\x{54B8}\x{54B9}\x{54BA}\x{54BB}\x{54BC}\x{54BD}' . + '\x{54BE}\x{54BF}\x{54C0}\x{54C1}\x{54C2}\x{54C3}\x{54C4}\x{54C5}\x{54C6}' . + '\x{54C7}\x{54C8}\x{54C9}\x{54CA}\x{54CB}\x{54CC}\x{54CD}\x{54CE}\x{54CF}' . + '\x{54D0}\x{54D1}\x{54D2}\x{54D3}\x{54D4}\x{54D5}\x{54D6}\x{54D7}\x{54D8}' . + '\x{54D9}\x{54DA}\x{54DB}\x{54DC}\x{54DD}\x{54DE}\x{54DF}\x{54E0}\x{54E1}' . + '\x{54E2}\x{54E3}\x{54E4}\x{54E5}\x{54E6}\x{54E7}\x{54E8}\x{54E9}\x{54EA}' . + '\x{54EB}\x{54EC}\x{54ED}\x{54EE}\x{54EF}\x{54F0}\x{54F1}\x{54F2}\x{54F3}' . + '\x{54F4}\x{54F5}\x{54F7}\x{54F8}\x{54F9}\x{54FA}\x{54FB}\x{54FC}\x{54FD}' . + '\x{54FE}\x{54FF}\x{5500}\x{5501}\x{5502}\x{5503}\x{5504}\x{5505}\x{5506}' . + '\x{5507}\x{5508}\x{5509}\x{550A}\x{550B}\x{550C}\x{550D}\x{550E}\x{550F}' . + '\x{5510}\x{5511}\x{5512}\x{5513}\x{5514}\x{5516}\x{5517}\x{551A}\x{551B}' . + '\x{551C}\x{551D}\x{551E}\x{551F}\x{5520}\x{5521}\x{5522}\x{5523}\x{5524}' . + '\x{5525}\x{5526}\x{5527}\x{5528}\x{5529}\x{552A}\x{552B}\x{552C}\x{552D}' . + '\x{552E}\x{552F}\x{5530}\x{5531}\x{5532}\x{5533}\x{5534}\x{5535}\x{5536}' . + '\x{5537}\x{5538}\x{5539}\x{553A}\x{553B}\x{553C}\x{553D}\x{553E}\x{553F}' . + '\x{5540}\x{5541}\x{5542}\x{5543}\x{5544}\x{5545}\x{5546}\x{5548}\x{5549}' . + '\x{554A}\x{554B}\x{554C}\x{554D}\x{554E}\x{554F}\x{5550}\x{5551}\x{5552}' . + '\x{5553}\x{5554}\x{5555}\x{5556}\x{5557}\x{5558}\x{5559}\x{555A}\x{555B}' . + '\x{555C}\x{555D}\x{555E}\x{555F}\x{5561}\x{5562}\x{5563}\x{5564}\x{5565}' . + '\x{5566}\x{5567}\x{5568}\x{5569}\x{556A}\x{556B}\x{556C}\x{556D}\x{556E}' . + '\x{556F}\x{5570}\x{5571}\x{5572}\x{5573}\x{5574}\x{5575}\x{5576}\x{5577}' . + '\x{5578}\x{5579}\x{557B}\x{557C}\x{557D}\x{557E}\x{557F}\x{5580}\x{5581}' . + '\x{5582}\x{5583}\x{5584}\x{5585}\x{5586}\x{5587}\x{5588}\x{5589}\x{558A}' . + '\x{558B}\x{558C}\x{558D}\x{558E}\x{558F}\x{5590}\x{5591}\x{5592}\x{5593}' . + '\x{5594}\x{5595}\x{5596}\x{5597}\x{5598}\x{5599}\x{559A}\x{559B}\x{559C}' . + '\x{559D}\x{559E}\x{559F}\x{55A0}\x{55A1}\x{55A2}\x{55A3}\x{55A4}\x{55A5}' . + '\x{55A6}\x{55A7}\x{55A8}\x{55A9}\x{55AA}\x{55AB}\x{55AC}\x{55AD}\x{55AE}' . + '\x{55AF}\x{55B0}\x{55B1}\x{55B2}\x{55B3}\x{55B4}\x{55B5}\x{55B6}\x{55B7}' . + '\x{55B8}\x{55B9}\x{55BA}\x{55BB}\x{55BC}\x{55BD}\x{55BE}\x{55BF}\x{55C0}' . + '\x{55C1}\x{55C2}\x{55C3}\x{55C4}\x{55C5}\x{55C6}\x{55C7}\x{55C8}\x{55C9}' . + '\x{55CA}\x{55CB}\x{55CC}\x{55CD}\x{55CE}\x{55CF}\x{55D0}\x{55D1}\x{55D2}' . + '\x{55D3}\x{55D4}\x{55D5}\x{55D6}\x{55D7}\x{55D8}\x{55D9}\x{55DA}\x{55DB}' . + '\x{55DC}\x{55DD}\x{55DE}\x{55DF}\x{55E1}\x{55E2}\x{55E3}\x{55E4}\x{55E5}' . + '\x{55E6}\x{55E7}\x{55E8}\x{55E9}\x{55EA}\x{55EB}\x{55EC}\x{55ED}\x{55EE}' . + '\x{55EF}\x{55F0}\x{55F1}\x{55F2}\x{55F3}\x{55F4}\x{55F5}\x{55F6}\x{55F7}' . + '\x{55F9}\x{55FA}\x{55FB}\x{55FC}\x{55FD}\x{55FE}\x{55FF}\x{5600}\x{5601}' . + '\x{5602}\x{5603}\x{5604}\x{5606}\x{5607}\x{5608}\x{5609}\x{560C}\x{560D}' . + '\x{560E}\x{560F}\x{5610}\x{5611}\x{5612}\x{5613}\x{5614}\x{5615}\x{5616}' . + '\x{5617}\x{5618}\x{5619}\x{561A}\x{561B}\x{561C}\x{561D}\x{561E}\x{561F}' . + '\x{5621}\x{5622}\x{5623}\x{5624}\x{5625}\x{5626}\x{5627}\x{5628}\x{5629}' . + '\x{562A}\x{562C}\x{562D}\x{562E}\x{562F}\x{5630}\x{5631}\x{5632}\x{5633}' . + '\x{5634}\x{5635}\x{5636}\x{5638}\x{5639}\x{563A}\x{563B}\x{563D}\x{563E}' . + '\x{563F}\x{5640}\x{5641}\x{5642}\x{5643}\x{5645}\x{5646}\x{5647}\x{5648}' . + '\x{5649}\x{564A}\x{564C}\x{564D}\x{564E}\x{564F}\x{5650}\x{5652}\x{5653}' . + '\x{5654}\x{5655}\x{5657}\x{5658}\x{5659}\x{565A}\x{565B}\x{565C}\x{565D}' . + '\x{565E}\x{5660}\x{5662}\x{5663}\x{5664}\x{5665}\x{5666}\x{5667}\x{5668}' . + '\x{5669}\x{566A}\x{566B}\x{566C}\x{566D}\x{566E}\x{566F}\x{5670}\x{5671}' . + '\x{5672}\x{5673}\x{5674}\x{5676}\x{5677}\x{5678}\x{5679}\x{567A}\x{567B}' . + '\x{567C}\x{567E}\x{567F}\x{5680}\x{5681}\x{5682}\x{5683}\x{5684}\x{5685}' . + '\x{5686}\x{5687}\x{568A}\x{568C}\x{568D}\x{568E}\x{568F}\x{5690}\x{5691}' . + '\x{5692}\x{5693}\x{5694}\x{5695}\x{5697}\x{5698}\x{5699}\x{569A}\x{569B}' . + '\x{569C}\x{569D}\x{569F}\x{56A0}\x{56A1}\x{56A3}\x{56A4}\x{56A5}\x{56A6}' . + '\x{56A7}\x{56A8}\x{56A9}\x{56AA}\x{56AB}\x{56AC}\x{56AD}\x{56AE}\x{56AF}' . + '\x{56B0}\x{56B1}\x{56B2}\x{56B3}\x{56B4}\x{56B5}\x{56B6}\x{56B7}\x{56B8}' . + '\x{56B9}\x{56BB}\x{56BC}\x{56BD}\x{56BE}\x{56BF}\x{56C0}\x{56C1}\x{56C2}' . + '\x{56C3}\x{56C4}\x{56C5}\x{56C6}\x{56C7}\x{56C8}\x{56C9}\x{56CA}\x{56CB}' . + '\x{56CC}\x{56CD}\x{56CE}\x{56D0}\x{56D1}\x{56D2}\x{56D3}\x{56D4}\x{56D5}' . + '\x{56D6}\x{56D7}\x{56D8}\x{56DA}\x{56DB}\x{56DC}\x{56DD}\x{56DE}\x{56DF}' . + '\x{56E0}\x{56E1}\x{56E2}\x{56E3}\x{56E4}\x{56E5}\x{56E7}\x{56E8}\x{56E9}' . + '\x{56EA}\x{56EB}\x{56EC}\x{56ED}\x{56EE}\x{56EF}\x{56F0}\x{56F1}\x{56F2}' . + '\x{56F3}\x{56F4}\x{56F5}\x{56F7}\x{56F9}\x{56FA}\x{56FD}\x{56FE}\x{56FF}' . + '\x{5700}\x{5701}\x{5702}\x{5703}\x{5704}\x{5706}\x{5707}\x{5708}\x{5709}' . + '\x{570A}\x{570B}\x{570C}\x{570D}\x{570E}\x{570F}\x{5710}\x{5712}\x{5713}' . + '\x{5714}\x{5715}\x{5716}\x{5718}\x{5719}\x{571A}\x{571B}\x{571C}\x{571D}' . + '\x{571E}\x{571F}\x{5720}\x{5722}\x{5723}\x{5725}\x{5726}\x{5727}\x{5728}' . + '\x{5729}\x{572A}\x{572B}\x{572C}\x{572D}\x{572E}\x{572F}\x{5730}\x{5731}' . + '\x{5732}\x{5733}\x{5734}\x{5735}\x{5736}\x{5737}\x{5738}\x{5739}\x{573A}' . + '\x{573B}\x{573C}\x{573E}\x{573F}\x{5740}\x{5741}\x{5742}\x{5744}\x{5745}' . + '\x{5746}\x{5747}\x{5749}\x{574A}\x{574B}\x{574C}\x{574D}\x{574E}\x{574F}' . + '\x{5750}\x{5751}\x{5752}\x{5753}\x{5754}\x{5757}\x{5759}\x{575A}\x{575B}' . + '\x{575C}\x{575D}\x{575E}\x{575F}\x{5760}\x{5761}\x{5762}\x{5764}\x{5765}' . + '\x{5766}\x{5767}\x{5768}\x{5769}\x{576A}\x{576B}\x{576C}\x{576D}\x{576F}' . + '\x{5770}\x{5771}\x{5772}\x{5773}\x{5774}\x{5775}\x{5776}\x{5777}\x{5779}' . + '\x{577A}\x{577B}\x{577C}\x{577D}\x{577E}\x{577F}\x{5780}\x{5782}\x{5783}' . + '\x{5784}\x{5785}\x{5786}\x{5788}\x{5789}\x{578A}\x{578B}\x{578C}\x{578D}' . + '\x{578E}\x{578F}\x{5790}\x{5791}\x{5792}\x{5793}\x{5794}\x{5795}\x{5797}' . + '\x{5798}\x{5799}\x{579A}\x{579B}\x{579C}\x{579D}\x{579E}\x{579F}\x{57A0}' . + '\x{57A1}\x{57A2}\x{57A3}\x{57A4}\x{57A5}\x{57A6}\x{57A7}\x{57A9}\x{57AA}' . + '\x{57AB}\x{57AC}\x{57AD}\x{57AE}\x{57AF}\x{57B0}\x{57B1}\x{57B2}\x{57B3}' . + '\x{57B4}\x{57B5}\x{57B6}\x{57B7}\x{57B8}\x{57B9}\x{57BA}\x{57BB}\x{57BC}' . + '\x{57BD}\x{57BE}\x{57BF}\x{57C0}\x{57C1}\x{57C2}\x{57C3}\x{57C4}\x{57C5}' . + '\x{57C6}\x{57C7}\x{57C8}\x{57C9}\x{57CB}\x{57CC}\x{57CD}\x{57CE}\x{57CF}' . + '\x{57D0}\x{57D2}\x{57D3}\x{57D4}\x{57D5}\x{57D6}\x{57D8}\x{57D9}\x{57DA}' . + '\x{57DC}\x{57DD}\x{57DF}\x{57E0}\x{57E1}\x{57E2}\x{57E3}\x{57E4}\x{57E5}' . + '\x{57E6}\x{57E7}\x{57E8}\x{57E9}\x{57EA}\x{57EB}\x{57EC}\x{57ED}\x{57EE}' . + '\x{57EF}\x{57F0}\x{57F1}\x{57F2}\x{57F3}\x{57F4}\x{57F5}\x{57F6}\x{57F7}' . + '\x{57F8}\x{57F9}\x{57FA}\x{57FB}\x{57FC}\x{57FD}\x{57FE}\x{57FF}\x{5800}' . + '\x{5801}\x{5802}\x{5803}\x{5804}\x{5805}\x{5806}\x{5807}\x{5808}\x{5809}' . + '\x{580A}\x{580B}\x{580C}\x{580D}\x{580E}\x{580F}\x{5810}\x{5811}\x{5812}' . + '\x{5813}\x{5814}\x{5815}\x{5816}\x{5819}\x{581A}\x{581B}\x{581C}\x{581D}' . + '\x{581E}\x{581F}\x{5820}\x{5821}\x{5822}\x{5823}\x{5824}\x{5825}\x{5826}' . + '\x{5827}\x{5828}\x{5829}\x{582A}\x{582B}\x{582C}\x{582D}\x{582E}\x{582F}' . + '\x{5830}\x{5831}\x{5832}\x{5833}\x{5834}\x{5835}\x{5836}\x{5837}\x{5838}' . + '\x{5839}\x{583A}\x{583B}\x{583C}\x{583D}\x{583E}\x{583F}\x{5840}\x{5842}' . + '\x{5843}\x{5844}\x{5845}\x{5846}\x{5847}\x{5848}\x{5849}\x{584A}\x{584B}' . + '\x{584C}\x{584D}\x{584E}\x{584F}\x{5851}\x{5852}\x{5853}\x{5854}\x{5855}' . + '\x{5857}\x{5858}\x{5859}\x{585A}\x{585B}\x{585C}\x{585D}\x{585E}\x{585F}' . + '\x{5861}\x{5862}\x{5863}\x{5864}\x{5865}\x{5868}\x{5869}\x{586A}\x{586B}' . + '\x{586C}\x{586D}\x{586E}\x{586F}\x{5870}\x{5871}\x{5872}\x{5873}\x{5874}' . + '\x{5875}\x{5876}\x{5878}\x{5879}\x{587A}\x{587B}\x{587C}\x{587D}\x{587E}' . + '\x{587F}\x{5880}\x{5881}\x{5882}\x{5883}\x{5884}\x{5885}\x{5886}\x{5887}' . + '\x{5888}\x{5889}\x{588A}\x{588B}\x{588C}\x{588D}\x{588E}\x{588F}\x{5890}' . + '\x{5891}\x{5892}\x{5893}\x{5894}\x{5896}\x{5897}\x{5898}\x{5899}\x{589A}' . + '\x{589B}\x{589C}\x{589D}\x{589E}\x{589F}\x{58A0}\x{58A1}\x{58A2}\x{58A3}' . + '\x{58A4}\x{58A5}\x{58A6}\x{58A7}\x{58A8}\x{58A9}\x{58AB}\x{58AC}\x{58AD}' . + '\x{58AE}\x{58AF}\x{58B0}\x{58B1}\x{58B2}\x{58B3}\x{58B4}\x{58B7}\x{58B8}' . + '\x{58B9}\x{58BA}\x{58BB}\x{58BC}\x{58BD}\x{58BE}\x{58BF}\x{58C1}\x{58C2}' . + '\x{58C5}\x{58C6}\x{58C7}\x{58C8}\x{58C9}\x{58CA}\x{58CB}\x{58CE}\x{58CF}' . + '\x{58D1}\x{58D2}\x{58D3}\x{58D4}\x{58D5}\x{58D6}\x{58D7}\x{58D8}\x{58D9}' . + '\x{58DA}\x{58DB}\x{58DD}\x{58DE}\x{58DF}\x{58E0}\x{58E2}\x{58E3}\x{58E4}' . + '\x{58E5}\x{58E7}\x{58E8}\x{58E9}\x{58EA}\x{58EB}\x{58EC}\x{58ED}\x{58EE}' . + '\x{58EF}\x{58F0}\x{58F1}\x{58F2}\x{58F3}\x{58F4}\x{58F6}\x{58F7}\x{58F8}' . + '\x{58F9}\x{58FA}\x{58FB}\x{58FC}\x{58FD}\x{58FE}\x{58FF}\x{5900}\x{5902}' . + '\x{5903}\x{5904}\x{5906}\x{5907}\x{5909}\x{590A}\x{590B}\x{590C}\x{590D}' . + '\x{590E}\x{590F}\x{5910}\x{5912}\x{5914}\x{5915}\x{5916}\x{5917}\x{5918}' . + '\x{5919}\x{591A}\x{591B}\x{591C}\x{591D}\x{591E}\x{591F}\x{5920}\x{5921}' . + '\x{5922}\x{5924}\x{5925}\x{5926}\x{5927}\x{5928}\x{5929}\x{592A}\x{592B}' . + '\x{592C}\x{592D}\x{592E}\x{592F}\x{5930}\x{5931}\x{5932}\x{5934}\x{5935}' . + '\x{5937}\x{5938}\x{5939}\x{593A}\x{593B}\x{593C}\x{593D}\x{593E}\x{593F}' . + '\x{5940}\x{5941}\x{5942}\x{5943}\x{5944}\x{5945}\x{5946}\x{5947}\x{5948}' . + '\x{5949}\x{594A}\x{594B}\x{594C}\x{594D}\x{594E}\x{594F}\x{5950}\x{5951}' . + '\x{5952}\x{5953}\x{5954}\x{5955}\x{5956}\x{5957}\x{5958}\x{595A}\x{595C}' . + '\x{595D}\x{595E}\x{595F}\x{5960}\x{5961}\x{5962}\x{5963}\x{5964}\x{5965}' . + '\x{5966}\x{5967}\x{5968}\x{5969}\x{596A}\x{596B}\x{596C}\x{596D}\x{596E}' . + '\x{596F}\x{5970}\x{5971}\x{5972}\x{5973}\x{5974}\x{5975}\x{5976}\x{5977}' . + '\x{5978}\x{5979}\x{597A}\x{597B}\x{597C}\x{597D}\x{597E}\x{597F}\x{5980}' . + '\x{5981}\x{5982}\x{5983}\x{5984}\x{5985}\x{5986}\x{5987}\x{5988}\x{5989}' . + '\x{598A}\x{598B}\x{598C}\x{598D}\x{598E}\x{598F}\x{5990}\x{5991}\x{5992}' . + '\x{5993}\x{5994}\x{5995}\x{5996}\x{5997}\x{5998}\x{5999}\x{599A}\x{599C}' . + '\x{599D}\x{599E}\x{599F}\x{59A0}\x{59A1}\x{59A2}\x{59A3}\x{59A4}\x{59A5}' . + '\x{59A6}\x{59A7}\x{59A8}\x{59A9}\x{59AA}\x{59AB}\x{59AC}\x{59AD}\x{59AE}' . + '\x{59AF}\x{59B0}\x{59B1}\x{59B2}\x{59B3}\x{59B4}\x{59B5}\x{59B6}\x{59B8}' . + '\x{59B9}\x{59BA}\x{59BB}\x{59BC}\x{59BD}\x{59BE}\x{59BF}\x{59C0}\x{59C1}' . + '\x{59C2}\x{59C3}\x{59C4}\x{59C5}\x{59C6}\x{59C7}\x{59C8}\x{59C9}\x{59CA}' . + '\x{59CB}\x{59CC}\x{59CD}\x{59CE}\x{59CF}\x{59D0}\x{59D1}\x{59D2}\x{59D3}' . + '\x{59D4}\x{59D5}\x{59D6}\x{59D7}\x{59D8}\x{59D9}\x{59DA}\x{59DB}\x{59DC}' . + '\x{59DD}\x{59DE}\x{59DF}\x{59E0}\x{59E1}\x{59E2}\x{59E3}\x{59E4}\x{59E5}' . + '\x{59E6}\x{59E8}\x{59E9}\x{59EA}\x{59EB}\x{59EC}\x{59ED}\x{59EE}\x{59EF}' . + '\x{59F0}\x{59F1}\x{59F2}\x{59F3}\x{59F4}\x{59F5}\x{59F6}\x{59F7}\x{59F8}' . + '\x{59F9}\x{59FA}\x{59FB}\x{59FC}\x{59FD}\x{59FE}\x{59FF}\x{5A00}\x{5A01}' . + '\x{5A02}\x{5A03}\x{5A04}\x{5A05}\x{5A06}\x{5A07}\x{5A08}\x{5A09}\x{5A0A}' . + '\x{5A0B}\x{5A0C}\x{5A0D}\x{5A0E}\x{5A0F}\x{5A10}\x{5A11}\x{5A12}\x{5A13}' . + '\x{5A14}\x{5A15}\x{5A16}\x{5A17}\x{5A18}\x{5A19}\x{5A1A}\x{5A1B}\x{5A1C}' . + '\x{5A1D}\x{5A1E}\x{5A1F}\x{5A20}\x{5A21}\x{5A22}\x{5A23}\x{5A25}\x{5A27}' . + '\x{5A28}\x{5A29}\x{5A2A}\x{5A2B}\x{5A2D}\x{5A2E}\x{5A2F}\x{5A31}\x{5A32}' . + '\x{5A33}\x{5A34}\x{5A35}\x{5A36}\x{5A37}\x{5A38}\x{5A39}\x{5A3A}\x{5A3B}' . + '\x{5A3C}\x{5A3D}\x{5A3E}\x{5A3F}\x{5A40}\x{5A41}\x{5A42}\x{5A43}\x{5A44}' . + '\x{5A45}\x{5A46}\x{5A47}\x{5A48}\x{5A49}\x{5A4A}\x{5A4B}\x{5A4C}\x{5A4D}' . + '\x{5A4E}\x{5A4F}\x{5A50}\x{5A51}\x{5A52}\x{5A53}\x{5A55}\x{5A56}\x{5A57}' . + '\x{5A58}\x{5A5A}\x{5A5B}\x{5A5C}\x{5A5D}\x{5A5E}\x{5A5F}\x{5A60}\x{5A61}' . + '\x{5A62}\x{5A63}\x{5A64}\x{5A65}\x{5A66}\x{5A67}\x{5A68}\x{5A69}\x{5A6A}' . + '\x{5A6B}\x{5A6C}\x{5A6D}\x{5A6E}\x{5A70}\x{5A72}\x{5A73}\x{5A74}\x{5A75}' . + '\x{5A76}\x{5A77}\x{5A78}\x{5A79}\x{5A7A}\x{5A7B}\x{5A7C}\x{5A7D}\x{5A7E}' . + '\x{5A7F}\x{5A80}\x{5A81}\x{5A82}\x{5A83}\x{5A84}\x{5A85}\x{5A86}\x{5A88}' . + '\x{5A89}\x{5A8A}\x{5A8B}\x{5A8C}\x{5A8E}\x{5A8F}\x{5A90}\x{5A91}\x{5A92}' . + '\x{5A93}\x{5A94}\x{5A95}\x{5A96}\x{5A97}\x{5A98}\x{5A99}\x{5A9A}\x{5A9B}' . + '\x{5A9C}\x{5A9D}\x{5A9E}\x{5A9F}\x{5AA0}\x{5AA1}\x{5AA2}\x{5AA3}\x{5AA4}' . + '\x{5AA5}\x{5AA6}\x{5AA7}\x{5AA8}\x{5AA9}\x{5AAA}\x{5AAC}\x{5AAD}\x{5AAE}' . + '\x{5AAF}\x{5AB0}\x{5AB1}\x{5AB2}\x{5AB3}\x{5AB4}\x{5AB5}\x{5AB6}\x{5AB7}' . + '\x{5AB8}\x{5AB9}\x{5ABA}\x{5ABB}\x{5ABC}\x{5ABD}\x{5ABE}\x{5ABF}\x{5AC0}' . + '\x{5AC1}\x{5AC2}\x{5AC3}\x{5AC4}\x{5AC5}\x{5AC6}\x{5AC7}\x{5AC8}\x{5AC9}' . + '\x{5ACA}\x{5ACB}\x{5ACC}\x{5ACD}\x{5ACE}\x{5ACF}\x{5AD1}\x{5AD2}\x{5AD4}' . + '\x{5AD5}\x{5AD6}\x{5AD7}\x{5AD8}\x{5AD9}\x{5ADA}\x{5ADB}\x{5ADC}\x{5ADD}' . + '\x{5ADE}\x{5ADF}\x{5AE0}\x{5AE1}\x{5AE2}\x{5AE3}\x{5AE4}\x{5AE5}\x{5AE6}' . + '\x{5AE7}\x{5AE8}\x{5AE9}\x{5AEA}\x{5AEB}\x{5AEC}\x{5AED}\x{5AEE}\x{5AF1}' . + '\x{5AF2}\x{5AF3}\x{5AF4}\x{5AF5}\x{5AF6}\x{5AF7}\x{5AF8}\x{5AF9}\x{5AFA}' . + '\x{5AFB}\x{5AFC}\x{5AFD}\x{5AFE}\x{5AFF}\x{5B00}\x{5B01}\x{5B02}\x{5B03}' . + '\x{5B04}\x{5B05}\x{5B06}\x{5B07}\x{5B08}\x{5B09}\x{5B0B}\x{5B0C}\x{5B0E}' . + '\x{5B0F}\x{5B10}\x{5B11}\x{5B12}\x{5B13}\x{5B14}\x{5B15}\x{5B16}\x{5B17}' . + '\x{5B18}\x{5B19}\x{5B1A}\x{5B1B}\x{5B1C}\x{5B1D}\x{5B1E}\x{5B1F}\x{5B20}' . + '\x{5B21}\x{5B22}\x{5B23}\x{5B24}\x{5B25}\x{5B26}\x{5B27}\x{5B28}\x{5B29}' . + '\x{5B2A}\x{5B2B}\x{5B2C}\x{5B2D}\x{5B2E}\x{5B2F}\x{5B30}\x{5B31}\x{5B32}' . + '\x{5B33}\x{5B34}\x{5B35}\x{5B36}\x{5B37}\x{5B38}\x{5B3A}\x{5B3B}\x{5B3C}' . + '\x{5B3D}\x{5B3E}\x{5B3F}\x{5B40}\x{5B41}\x{5B42}\x{5B43}\x{5B44}\x{5B45}' . + '\x{5B47}\x{5B48}\x{5B49}\x{5B4A}\x{5B4B}\x{5B4C}\x{5B4D}\x{5B4E}\x{5B50}' . + '\x{5B51}\x{5B53}\x{5B54}\x{5B55}\x{5B56}\x{5B57}\x{5B58}\x{5B59}\x{5B5A}' . + '\x{5B5B}\x{5B5C}\x{5B5D}\x{5B5E}\x{5B5F}\x{5B62}\x{5B63}\x{5B64}\x{5B65}' . + '\x{5B66}\x{5B67}\x{5B68}\x{5B69}\x{5B6A}\x{5B6B}\x{5B6C}\x{5B6D}\x{5B6E}' . + '\x{5B70}\x{5B71}\x{5B72}\x{5B73}\x{5B74}\x{5B75}\x{5B76}\x{5B77}\x{5B78}' . + '\x{5B7A}\x{5B7B}\x{5B7C}\x{5B7D}\x{5B7F}\x{5B80}\x{5B81}\x{5B82}\x{5B83}' . + '\x{5B84}\x{5B85}\x{5B87}\x{5B88}\x{5B89}\x{5B8A}\x{5B8B}\x{5B8C}\x{5B8D}' . + '\x{5B8E}\x{5B8F}\x{5B91}\x{5B92}\x{5B93}\x{5B94}\x{5B95}\x{5B96}\x{5B97}' . + '\x{5B98}\x{5B99}\x{5B9A}\x{5B9B}\x{5B9C}\x{5B9D}\x{5B9E}\x{5B9F}\x{5BA0}' . + '\x{5BA1}\x{5BA2}\x{5BA3}\x{5BA4}\x{5BA5}\x{5BA6}\x{5BA7}\x{5BA8}\x{5BAA}' . + '\x{5BAB}\x{5BAC}\x{5BAD}\x{5BAE}\x{5BAF}\x{5BB0}\x{5BB1}\x{5BB3}\x{5BB4}' . + '\x{5BB5}\x{5BB6}\x{5BB8}\x{5BB9}\x{5BBA}\x{5BBB}\x{5BBD}\x{5BBE}\x{5BBF}' . + '\x{5BC0}\x{5BC1}\x{5BC2}\x{5BC3}\x{5BC4}\x{5BC5}\x{5BC6}\x{5BC7}\x{5BCA}' . + '\x{5BCB}\x{5BCC}\x{5BCD}\x{5BCE}\x{5BCF}\x{5BD0}\x{5BD1}\x{5BD2}\x{5BD3}' . + '\x{5BD4}\x{5BD5}\x{5BD6}\x{5BD8}\x{5BD9}\x{5BDB}\x{5BDC}\x{5BDD}\x{5BDE}' . + '\x{5BDF}\x{5BE0}\x{5BE1}\x{5BE2}\x{5BE3}\x{5BE4}\x{5BE5}\x{5BE6}\x{5BE7}' . + '\x{5BE8}\x{5BE9}\x{5BEA}\x{5BEB}\x{5BEC}\x{5BED}\x{5BEE}\x{5BEF}\x{5BF0}' . + '\x{5BF1}\x{5BF2}\x{5BF3}\x{5BF4}\x{5BF5}\x{5BF6}\x{5BF7}\x{5BF8}\x{5BF9}' . + '\x{5BFA}\x{5BFB}\x{5BFC}\x{5BFD}\x{5BFF}\x{5C01}\x{5C03}\x{5C04}\x{5C05}' . + '\x{5C06}\x{5C07}\x{5C08}\x{5C09}\x{5C0A}\x{5C0B}\x{5C0C}\x{5C0D}\x{5C0E}' . + '\x{5C0F}\x{5C10}\x{5C11}\x{5C12}\x{5C13}\x{5C14}\x{5C15}\x{5C16}\x{5C17}' . + '\x{5C18}\x{5C19}\x{5C1A}\x{5C1C}\x{5C1D}\x{5C1E}\x{5C1F}\x{5C20}\x{5C21}' . + '\x{5C22}\x{5C24}\x{5C25}\x{5C27}\x{5C28}\x{5C2A}\x{5C2B}\x{5C2C}\x{5C2D}' . + '\x{5C2E}\x{5C2F}\x{5C30}\x{5C31}\x{5C32}\x{5C33}\x{5C34}\x{5C35}\x{5C37}' . + '\x{5C38}\x{5C39}\x{5C3A}\x{5C3B}\x{5C3C}\x{5C3D}\x{5C3E}\x{5C3F}\x{5C40}' . + '\x{5C41}\x{5C42}\x{5C43}\x{5C44}\x{5C45}\x{5C46}\x{5C47}\x{5C48}\x{5C49}' . + '\x{5C4A}\x{5C4B}\x{5C4C}\x{5C4D}\x{5C4E}\x{5C4F}\x{5C50}\x{5C51}\x{5C52}' . + '\x{5C53}\x{5C54}\x{5C55}\x{5C56}\x{5C57}\x{5C58}\x{5C59}\x{5C5B}\x{5C5C}' . + '\x{5C5D}\x{5C5E}\x{5C5F}\x{5C60}\x{5C61}\x{5C62}\x{5C63}\x{5C64}\x{5C65}' . + '\x{5C66}\x{5C67}\x{5C68}\x{5C69}\x{5C6A}\x{5C6B}\x{5C6C}\x{5C6D}\x{5C6E}' . + '\x{5C6F}\x{5C70}\x{5C71}\x{5C72}\x{5C73}\x{5C74}\x{5C75}\x{5C76}\x{5C77}' . + '\x{5C78}\x{5C79}\x{5C7A}\x{5C7B}\x{5C7C}\x{5C7D}\x{5C7E}\x{5C7F}\x{5C80}' . + '\x{5C81}\x{5C82}\x{5C83}\x{5C84}\x{5C86}\x{5C87}\x{5C88}\x{5C89}\x{5C8A}' . + '\x{5C8B}\x{5C8C}\x{5C8D}\x{5C8E}\x{5C8F}\x{5C90}\x{5C91}\x{5C92}\x{5C93}' . + '\x{5C94}\x{5C95}\x{5C96}\x{5C97}\x{5C98}\x{5C99}\x{5C9A}\x{5C9B}\x{5C9C}' . + '\x{5C9D}\x{5C9E}\x{5C9F}\x{5CA0}\x{5CA1}\x{5CA2}\x{5CA3}\x{5CA4}\x{5CA5}' . + '\x{5CA6}\x{5CA7}\x{5CA8}\x{5CA9}\x{5CAA}\x{5CAB}\x{5CAC}\x{5CAD}\x{5CAE}' . + '\x{5CAF}\x{5CB0}\x{5CB1}\x{5CB2}\x{5CB3}\x{5CB5}\x{5CB6}\x{5CB7}\x{5CB8}' . + '\x{5CBA}\x{5CBB}\x{5CBC}\x{5CBD}\x{5CBE}\x{5CBF}\x{5CC1}\x{5CC2}\x{5CC3}' . + '\x{5CC4}\x{5CC5}\x{5CC6}\x{5CC7}\x{5CC8}\x{5CC9}\x{5CCA}\x{5CCB}\x{5CCC}' . + '\x{5CCD}\x{5CCE}\x{5CCF}\x{5CD0}\x{5CD1}\x{5CD2}\x{5CD3}\x{5CD4}\x{5CD6}' . + '\x{5CD7}\x{5CD8}\x{5CD9}\x{5CDA}\x{5CDB}\x{5CDC}\x{5CDE}\x{5CDF}\x{5CE0}' . + '\x{5CE1}\x{5CE2}\x{5CE3}\x{5CE4}\x{5CE5}\x{5CE6}\x{5CE7}\x{5CE8}\x{5CE9}' . + '\x{5CEA}\x{5CEB}\x{5CEC}\x{5CED}\x{5CEE}\x{5CEF}\x{5CF0}\x{5CF1}\x{5CF2}' . + '\x{5CF3}\x{5CF4}\x{5CF6}\x{5CF7}\x{5CF8}\x{5CF9}\x{5CFA}\x{5CFB}\x{5CFC}' . + '\x{5CFD}\x{5CFE}\x{5CFF}\x{5D00}\x{5D01}\x{5D02}\x{5D03}\x{5D04}\x{5D05}' . + '\x{5D06}\x{5D07}\x{5D08}\x{5D09}\x{5D0A}\x{5D0B}\x{5D0C}\x{5D0D}\x{5D0E}' . + '\x{5D0F}\x{5D10}\x{5D11}\x{5D12}\x{5D13}\x{5D14}\x{5D15}\x{5D16}\x{5D17}' . + '\x{5D18}\x{5D19}\x{5D1A}\x{5D1B}\x{5D1C}\x{5D1D}\x{5D1E}\x{5D1F}\x{5D20}' . + '\x{5D21}\x{5D22}\x{5D23}\x{5D24}\x{5D25}\x{5D26}\x{5D27}\x{5D28}\x{5D29}' . + '\x{5D2A}\x{5D2C}\x{5D2D}\x{5D2E}\x{5D30}\x{5D31}\x{5D32}\x{5D33}\x{5D34}' . + '\x{5D35}\x{5D36}\x{5D37}\x{5D38}\x{5D39}\x{5D3A}\x{5D3C}\x{5D3D}\x{5D3E}' . + '\x{5D3F}\x{5D40}\x{5D41}\x{5D42}\x{5D43}\x{5D44}\x{5D45}\x{5D46}\x{5D47}' . + '\x{5D48}\x{5D49}\x{5D4A}\x{5D4B}\x{5D4C}\x{5D4D}\x{5D4E}\x{5D4F}\x{5D50}' . + '\x{5D51}\x{5D52}\x{5D54}\x{5D55}\x{5D56}\x{5D58}\x{5D59}\x{5D5A}\x{5D5B}' . + '\x{5D5D}\x{5D5E}\x{5D5F}\x{5D61}\x{5D62}\x{5D63}\x{5D64}\x{5D65}\x{5D66}' . + '\x{5D67}\x{5D68}\x{5D69}\x{5D6A}\x{5D6B}\x{5D6C}\x{5D6D}\x{5D6E}\x{5D6F}' . + '\x{5D70}\x{5D71}\x{5D72}\x{5D73}\x{5D74}\x{5D75}\x{5D76}\x{5D77}\x{5D78}' . + '\x{5D79}\x{5D7A}\x{5D7B}\x{5D7C}\x{5D7D}\x{5D7E}\x{5D7F}\x{5D80}\x{5D81}' . + '\x{5D82}\x{5D84}\x{5D85}\x{5D86}\x{5D87}\x{5D88}\x{5D89}\x{5D8A}\x{5D8B}' . + '\x{5D8C}\x{5D8D}\x{5D8E}\x{5D8F}\x{5D90}\x{5D91}\x{5D92}\x{5D93}\x{5D94}' . + '\x{5D95}\x{5D97}\x{5D98}\x{5D99}\x{5D9A}\x{5D9B}\x{5D9C}\x{5D9D}\x{5D9E}' . + '\x{5D9F}\x{5DA0}\x{5DA1}\x{5DA2}\x{5DA5}\x{5DA6}\x{5DA7}\x{5DA8}\x{5DA9}' . + '\x{5DAA}\x{5DAC}\x{5DAD}\x{5DAE}\x{5DAF}\x{5DB0}\x{5DB1}\x{5DB2}\x{5DB4}' . + '\x{5DB5}\x{5DB6}\x{5DB7}\x{5DB8}\x{5DBA}\x{5DBB}\x{5DBC}\x{5DBD}\x{5DBE}' . + '\x{5DBF}\x{5DC0}\x{5DC1}\x{5DC2}\x{5DC3}\x{5DC5}\x{5DC6}\x{5DC7}\x{5DC8}' . + '\x{5DC9}\x{5DCA}\x{5DCB}\x{5DCC}\x{5DCD}\x{5DCE}\x{5DCF}\x{5DD0}\x{5DD1}' . + '\x{5DD2}\x{5DD3}\x{5DD4}\x{5DD5}\x{5DD6}\x{5DD8}\x{5DD9}\x{5DDB}\x{5DDD}' . + '\x{5DDE}\x{5DDF}\x{5DE0}\x{5DE1}\x{5DE2}\x{5DE3}\x{5DE4}\x{5DE5}\x{5DE6}' . + '\x{5DE7}\x{5DE8}\x{5DE9}\x{5DEA}\x{5DEB}\x{5DEC}\x{5DED}\x{5DEE}\x{5DEF}' . + '\x{5DF0}\x{5DF1}\x{5DF2}\x{5DF3}\x{5DF4}\x{5DF5}\x{5DF7}\x{5DF8}\x{5DF9}' . + '\x{5DFA}\x{5DFB}\x{5DFC}\x{5DFD}\x{5DFE}\x{5DFF}\x{5E00}\x{5E01}\x{5E02}' . + '\x{5E03}\x{5E04}\x{5E05}\x{5E06}\x{5E07}\x{5E08}\x{5E09}\x{5E0A}\x{5E0B}' . + '\x{5E0C}\x{5E0D}\x{5E0E}\x{5E0F}\x{5E10}\x{5E11}\x{5E13}\x{5E14}\x{5E15}' . + '\x{5E16}\x{5E17}\x{5E18}\x{5E19}\x{5E1A}\x{5E1B}\x{5E1C}\x{5E1D}\x{5E1E}' . + '\x{5E1F}\x{5E20}\x{5E21}\x{5E22}\x{5E23}\x{5E24}\x{5E25}\x{5E26}\x{5E27}' . + '\x{5E28}\x{5E29}\x{5E2A}\x{5E2B}\x{5E2C}\x{5E2D}\x{5E2E}\x{5E2F}\x{5E30}' . + '\x{5E31}\x{5E32}\x{5E33}\x{5E34}\x{5E35}\x{5E36}\x{5E37}\x{5E38}\x{5E39}' . + '\x{5E3A}\x{5E3B}\x{5E3C}\x{5E3D}\x{5E3E}\x{5E40}\x{5E41}\x{5E42}\x{5E43}' . + '\x{5E44}\x{5E45}\x{5E46}\x{5E47}\x{5E49}\x{5E4A}\x{5E4B}\x{5E4C}\x{5E4D}' . + '\x{5E4E}\x{5E4F}\x{5E50}\x{5E52}\x{5E53}\x{5E54}\x{5E55}\x{5E56}\x{5E57}' . + '\x{5E58}\x{5E59}\x{5E5A}\x{5E5B}\x{5E5C}\x{5E5D}\x{5E5E}\x{5E5F}\x{5E60}' . + '\x{5E61}\x{5E62}\x{5E63}\x{5E64}\x{5E65}\x{5E66}\x{5E67}\x{5E68}\x{5E69}' . + '\x{5E6A}\x{5E6B}\x{5E6C}\x{5E6D}\x{5E6E}\x{5E6F}\x{5E70}\x{5E71}\x{5E72}' . + '\x{5E73}\x{5E74}\x{5E75}\x{5E76}\x{5E77}\x{5E78}\x{5E79}\x{5E7A}\x{5E7B}' . + '\x{5E7C}\x{5E7D}\x{5E7E}\x{5E7F}\x{5E80}\x{5E81}\x{5E82}\x{5E83}\x{5E84}' . + '\x{5E85}\x{5E86}\x{5E87}\x{5E88}\x{5E89}\x{5E8A}\x{5E8B}\x{5E8C}\x{5E8D}' . + '\x{5E8E}\x{5E8F}\x{5E90}\x{5E91}\x{5E93}\x{5E94}\x{5E95}\x{5E96}\x{5E97}' . + '\x{5E98}\x{5E99}\x{5E9A}\x{5E9B}\x{5E9C}\x{5E9D}\x{5E9E}\x{5E9F}\x{5EA0}' . + '\x{5EA1}\x{5EA2}\x{5EA3}\x{5EA4}\x{5EA5}\x{5EA6}\x{5EA7}\x{5EA8}\x{5EA9}' . + '\x{5EAA}\x{5EAB}\x{5EAC}\x{5EAD}\x{5EAE}\x{5EAF}\x{5EB0}\x{5EB1}\x{5EB2}' . + '\x{5EB3}\x{5EB4}\x{5EB5}\x{5EB6}\x{5EB7}\x{5EB8}\x{5EB9}\x{5EBB}\x{5EBC}' . + '\x{5EBD}\x{5EBE}\x{5EBF}\x{5EC1}\x{5EC2}\x{5EC3}\x{5EC4}\x{5EC5}\x{5EC6}' . + '\x{5EC7}\x{5EC8}\x{5EC9}\x{5ECA}\x{5ECB}\x{5ECC}\x{5ECD}\x{5ECE}\x{5ECF}' . + '\x{5ED0}\x{5ED1}\x{5ED2}\x{5ED3}\x{5ED4}\x{5ED5}\x{5ED6}\x{5ED7}\x{5ED8}' . + '\x{5ED9}\x{5EDA}\x{5EDB}\x{5EDC}\x{5EDD}\x{5EDE}\x{5EDF}\x{5EE0}\x{5EE1}' . + '\x{5EE2}\x{5EE3}\x{5EE4}\x{5EE5}\x{5EE6}\x{5EE7}\x{5EE8}\x{5EE9}\x{5EEA}' . + '\x{5EEC}\x{5EED}\x{5EEE}\x{5EEF}\x{5EF0}\x{5EF1}\x{5EF2}\x{5EF3}\x{5EF4}' . + '\x{5EF5}\x{5EF6}\x{5EF7}\x{5EF8}\x{5EFA}\x{5EFB}\x{5EFC}\x{5EFD}\x{5EFE}' . + '\x{5EFF}\x{5F00}\x{5F01}\x{5F02}\x{5F03}\x{5F04}\x{5F05}\x{5F06}\x{5F07}' . + '\x{5F08}\x{5F0A}\x{5F0B}\x{5F0C}\x{5F0D}\x{5F0F}\x{5F11}\x{5F12}\x{5F13}' . + '\x{5F14}\x{5F15}\x{5F16}\x{5F17}\x{5F18}\x{5F19}\x{5F1A}\x{5F1B}\x{5F1C}' . + '\x{5F1D}\x{5F1E}\x{5F1F}\x{5F20}\x{5F21}\x{5F22}\x{5F23}\x{5F24}\x{5F25}' . + '\x{5F26}\x{5F27}\x{5F28}\x{5F29}\x{5F2A}\x{5F2B}\x{5F2C}\x{5F2D}\x{5F2E}' . + '\x{5F2F}\x{5F30}\x{5F31}\x{5F32}\x{5F33}\x{5F34}\x{5F35}\x{5F36}\x{5F37}' . + '\x{5F38}\x{5F39}\x{5F3A}\x{5F3C}\x{5F3E}\x{5F3F}\x{5F40}\x{5F41}\x{5F42}' . + '\x{5F43}\x{5F44}\x{5F45}\x{5F46}\x{5F47}\x{5F48}\x{5F49}\x{5F4A}\x{5F4B}' . + '\x{5F4C}\x{5F4D}\x{5F4E}\x{5F4F}\x{5F50}\x{5F51}\x{5F52}\x{5F53}\x{5F54}' . + '\x{5F55}\x{5F56}\x{5F57}\x{5F58}\x{5F59}\x{5F5A}\x{5F5B}\x{5F5C}\x{5F5D}' . + '\x{5F5E}\x{5F5F}\x{5F60}\x{5F61}\x{5F62}\x{5F63}\x{5F64}\x{5F65}\x{5F66}' . + '\x{5F67}\x{5F68}\x{5F69}\x{5F6A}\x{5F6B}\x{5F6C}\x{5F6D}\x{5F6E}\x{5F6F}' . + '\x{5F70}\x{5F71}\x{5F72}\x{5F73}\x{5F74}\x{5F75}\x{5F76}\x{5F77}\x{5F78}' . + '\x{5F79}\x{5F7A}\x{5F7B}\x{5F7C}\x{5F7D}\x{5F7E}\x{5F7F}\x{5F80}\x{5F81}' . + '\x{5F82}\x{5F83}\x{5F84}\x{5F85}\x{5F86}\x{5F87}\x{5F88}\x{5F89}\x{5F8A}' . + '\x{5F8B}\x{5F8C}\x{5F8D}\x{5F8E}\x{5F90}\x{5F91}\x{5F92}\x{5F93}\x{5F94}' . + '\x{5F95}\x{5F96}\x{5F97}\x{5F98}\x{5F99}\x{5F9B}\x{5F9C}\x{5F9D}\x{5F9E}' . + '\x{5F9F}\x{5FA0}\x{5FA1}\x{5FA2}\x{5FA5}\x{5FA6}\x{5FA7}\x{5FA8}\x{5FA9}' . + '\x{5FAA}\x{5FAB}\x{5FAC}\x{5FAD}\x{5FAE}\x{5FAF}\x{5FB1}\x{5FB2}\x{5FB3}' . + '\x{5FB4}\x{5FB5}\x{5FB6}\x{5FB7}\x{5FB8}\x{5FB9}\x{5FBA}\x{5FBB}\x{5FBC}' . + '\x{5FBD}\x{5FBE}\x{5FBF}\x{5FC0}\x{5FC1}\x{5FC3}\x{5FC4}\x{5FC5}\x{5FC6}' . + '\x{5FC7}\x{5FC8}\x{5FC9}\x{5FCA}\x{5FCB}\x{5FCC}\x{5FCD}\x{5FCF}\x{5FD0}' . + '\x{5FD1}\x{5FD2}\x{5FD3}\x{5FD4}\x{5FD5}\x{5FD6}\x{5FD7}\x{5FD8}\x{5FD9}' . + '\x{5FDA}\x{5FDC}\x{5FDD}\x{5FDE}\x{5FE0}\x{5FE1}\x{5FE3}\x{5FE4}\x{5FE5}' . + '\x{5FE6}\x{5FE7}\x{5FE8}\x{5FE9}\x{5FEA}\x{5FEB}\x{5FED}\x{5FEE}\x{5FEF}' . + '\x{5FF0}\x{5FF1}\x{5FF2}\x{5FF3}\x{5FF4}\x{5FF5}\x{5FF6}\x{5FF7}\x{5FF8}' . + '\x{5FF9}\x{5FFA}\x{5FFB}\x{5FFD}\x{5FFE}\x{5FFF}\x{6000}\x{6001}\x{6002}' . + '\x{6003}\x{6004}\x{6005}\x{6006}\x{6007}\x{6008}\x{6009}\x{600A}\x{600B}' . + '\x{600C}\x{600D}\x{600E}\x{600F}\x{6010}\x{6011}\x{6012}\x{6013}\x{6014}' . + '\x{6015}\x{6016}\x{6017}\x{6018}\x{6019}\x{601A}\x{601B}\x{601C}\x{601D}' . + '\x{601E}\x{601F}\x{6020}\x{6021}\x{6022}\x{6024}\x{6025}\x{6026}\x{6027}' . + '\x{6028}\x{6029}\x{602A}\x{602B}\x{602C}\x{602D}\x{602E}\x{602F}\x{6030}' . + '\x{6031}\x{6032}\x{6033}\x{6034}\x{6035}\x{6036}\x{6037}\x{6038}\x{6039}' . + '\x{603A}\x{603B}\x{603C}\x{603D}\x{603E}\x{603F}\x{6040}\x{6041}\x{6042}' . + '\x{6043}\x{6044}\x{6045}\x{6046}\x{6047}\x{6048}\x{6049}\x{604A}\x{604B}' . + '\x{604C}\x{604D}\x{604E}\x{604F}\x{6050}\x{6051}\x{6052}\x{6053}\x{6054}' . + '\x{6055}\x{6057}\x{6058}\x{6059}\x{605A}\x{605B}\x{605C}\x{605D}\x{605E}' . + '\x{605F}\x{6062}\x{6063}\x{6064}\x{6065}\x{6066}\x{6067}\x{6068}\x{6069}' . + '\x{606A}\x{606B}\x{606C}\x{606D}\x{606E}\x{606F}\x{6070}\x{6072}\x{6073}' . + '\x{6075}\x{6076}\x{6077}\x{6078}\x{6079}\x{607A}\x{607B}\x{607C}\x{607D}' . + '\x{607E}\x{607F}\x{6080}\x{6081}\x{6082}\x{6083}\x{6084}\x{6085}\x{6086}' . + '\x{6087}\x{6088}\x{6089}\x{608A}\x{608B}\x{608C}\x{608D}\x{608E}\x{608F}' . + '\x{6090}\x{6092}\x{6094}\x{6095}\x{6096}\x{6097}\x{6098}\x{6099}\x{609A}' . + '\x{609B}\x{609C}\x{609D}\x{609E}\x{609F}\x{60A0}\x{60A1}\x{60A2}\x{60A3}' . + '\x{60A4}\x{60A6}\x{60A7}\x{60A8}\x{60AA}\x{60AB}\x{60AC}\x{60AD}\x{60AE}' . + '\x{60AF}\x{60B0}\x{60B1}\x{60B2}\x{60B3}\x{60B4}\x{60B5}\x{60B6}\x{60B7}' . + '\x{60B8}\x{60B9}\x{60BA}\x{60BB}\x{60BC}\x{60BD}\x{60BE}\x{60BF}\x{60C0}' . + '\x{60C1}\x{60C2}\x{60C3}\x{60C4}\x{60C5}\x{60C6}\x{60C7}\x{60C8}\x{60C9}' . + '\x{60CA}\x{60CB}\x{60CC}\x{60CD}\x{60CE}\x{60CF}\x{60D0}\x{60D1}\x{60D3}' . + '\x{60D4}\x{60D5}\x{60D7}\x{60D8}\x{60D9}\x{60DA}\x{60DB}\x{60DC}\x{60DD}' . + '\x{60DF}\x{60E0}\x{60E1}\x{60E2}\x{60E4}\x{60E6}\x{60E7}\x{60E8}\x{60E9}' . + '\x{60EA}\x{60EB}\x{60EC}\x{60ED}\x{60EE}\x{60EF}\x{60F0}\x{60F1}\x{60F2}' . + '\x{60F3}\x{60F4}\x{60F5}\x{60F6}\x{60F7}\x{60F8}\x{60F9}\x{60FA}\x{60FB}' . + '\x{60FC}\x{60FE}\x{60FF}\x{6100}\x{6101}\x{6103}\x{6104}\x{6105}\x{6106}' . + '\x{6108}\x{6109}\x{610A}\x{610B}\x{610C}\x{610D}\x{610E}\x{610F}\x{6110}' . + '\x{6112}\x{6113}\x{6114}\x{6115}\x{6116}\x{6117}\x{6118}\x{6119}\x{611A}' . + '\x{611B}\x{611C}\x{611D}\x{611F}\x{6120}\x{6122}\x{6123}\x{6124}\x{6125}' . + '\x{6126}\x{6127}\x{6128}\x{6129}\x{612A}\x{612B}\x{612C}\x{612D}\x{612E}' . + '\x{612F}\x{6130}\x{6132}\x{6134}\x{6136}\x{6137}\x{613A}\x{613B}\x{613C}' . + '\x{613D}\x{613E}\x{613F}\x{6140}\x{6141}\x{6142}\x{6143}\x{6144}\x{6145}' . + '\x{6146}\x{6147}\x{6148}\x{6149}\x{614A}\x{614B}\x{614C}\x{614D}\x{614E}' . + '\x{614F}\x{6150}\x{6151}\x{6152}\x{6153}\x{6154}\x{6155}\x{6156}\x{6157}' . + '\x{6158}\x{6159}\x{615A}\x{615B}\x{615C}\x{615D}\x{615E}\x{615F}\x{6161}' . + '\x{6162}\x{6163}\x{6164}\x{6165}\x{6166}\x{6167}\x{6168}\x{6169}\x{616A}' . + '\x{616B}\x{616C}\x{616D}\x{616E}\x{6170}\x{6171}\x{6172}\x{6173}\x{6174}' . + '\x{6175}\x{6176}\x{6177}\x{6178}\x{6179}\x{617A}\x{617C}\x{617E}\x{6180}' . + '\x{6181}\x{6182}\x{6183}\x{6184}\x{6185}\x{6187}\x{6188}\x{6189}\x{618A}' . + '\x{618B}\x{618C}\x{618D}\x{618E}\x{618F}\x{6190}\x{6191}\x{6192}\x{6193}' . + '\x{6194}\x{6195}\x{6196}\x{6198}\x{6199}\x{619A}\x{619B}\x{619D}\x{619E}' . + '\x{619F}\x{61A0}\x{61A1}\x{61A2}\x{61A3}\x{61A4}\x{61A5}\x{61A6}\x{61A7}' . + '\x{61A8}\x{61A9}\x{61AA}\x{61AB}\x{61AC}\x{61AD}\x{61AE}\x{61AF}\x{61B0}' . + '\x{61B1}\x{61B2}\x{61B3}\x{61B4}\x{61B5}\x{61B6}\x{61B7}\x{61B8}\x{61BA}' . + '\x{61BC}\x{61BD}\x{61BE}\x{61BF}\x{61C0}\x{61C1}\x{61C2}\x{61C3}\x{61C4}' . + '\x{61C5}\x{61C6}\x{61C7}\x{61C8}\x{61C9}\x{61CA}\x{61CB}\x{61CC}\x{61CD}' . + '\x{61CE}\x{61CF}\x{61D0}\x{61D1}\x{61D2}\x{61D4}\x{61D6}\x{61D7}\x{61D8}' . + '\x{61D9}\x{61DA}\x{61DB}\x{61DC}\x{61DD}\x{61DE}\x{61DF}\x{61E0}\x{61E1}' . + '\x{61E2}\x{61E3}\x{61E4}\x{61E5}\x{61E6}\x{61E7}\x{61E8}\x{61E9}\x{61EA}' . + '\x{61EB}\x{61ED}\x{61EE}\x{61F0}\x{61F1}\x{61F2}\x{61F3}\x{61F5}\x{61F6}' . + '\x{61F7}\x{61F8}\x{61F9}\x{61FA}\x{61FB}\x{61FC}\x{61FD}\x{61FE}\x{61FF}' . + '\x{6200}\x{6201}\x{6202}\x{6203}\x{6204}\x{6206}\x{6207}\x{6208}\x{6209}' . + '\x{620A}\x{620B}\x{620C}\x{620D}\x{620E}\x{620F}\x{6210}\x{6211}\x{6212}' . + '\x{6213}\x{6214}\x{6215}\x{6216}\x{6217}\x{6218}\x{6219}\x{621A}\x{621B}' . + '\x{621C}\x{621D}\x{621E}\x{621F}\x{6220}\x{6221}\x{6222}\x{6223}\x{6224}' . + '\x{6225}\x{6226}\x{6227}\x{6228}\x{6229}\x{622A}\x{622B}\x{622C}\x{622D}' . + '\x{622E}\x{622F}\x{6230}\x{6231}\x{6232}\x{6233}\x{6234}\x{6236}\x{6237}' . + '\x{6238}\x{623A}\x{623B}\x{623C}\x{623D}\x{623E}\x{623F}\x{6240}\x{6241}' . + '\x{6242}\x{6243}\x{6244}\x{6245}\x{6246}\x{6247}\x{6248}\x{6249}\x{624A}' . + '\x{624B}\x{624C}\x{624D}\x{624E}\x{624F}\x{6250}\x{6251}\x{6252}\x{6253}' . + '\x{6254}\x{6255}\x{6256}\x{6258}\x{6259}\x{625A}\x{625B}\x{625C}\x{625D}' . + '\x{625E}\x{625F}\x{6260}\x{6261}\x{6262}\x{6263}\x{6264}\x{6265}\x{6266}' . + '\x{6267}\x{6268}\x{6269}\x{626A}\x{626B}\x{626C}\x{626D}\x{626E}\x{626F}' . + '\x{6270}\x{6271}\x{6272}\x{6273}\x{6274}\x{6275}\x{6276}\x{6277}\x{6278}' . + '\x{6279}\x{627A}\x{627B}\x{627C}\x{627D}\x{627E}\x{627F}\x{6280}\x{6281}' . + '\x{6283}\x{6284}\x{6285}\x{6286}\x{6287}\x{6288}\x{6289}\x{628A}\x{628B}' . + '\x{628C}\x{628E}\x{628F}\x{6290}\x{6291}\x{6292}\x{6293}\x{6294}\x{6295}' . + '\x{6296}\x{6297}\x{6298}\x{6299}\x{629A}\x{629B}\x{629C}\x{629E}\x{629F}' . + '\x{62A0}\x{62A1}\x{62A2}\x{62A3}\x{62A4}\x{62A5}\x{62A7}\x{62A8}\x{62A9}' . + '\x{62AA}\x{62AB}\x{62AC}\x{62AD}\x{62AE}\x{62AF}\x{62B0}\x{62B1}\x{62B2}' . + '\x{62B3}\x{62B4}\x{62B5}\x{62B6}\x{62B7}\x{62B8}\x{62B9}\x{62BA}\x{62BB}' . + '\x{62BC}\x{62BD}\x{62BE}\x{62BF}\x{62C0}\x{62C1}\x{62C2}\x{62C3}\x{62C4}' . + '\x{62C5}\x{62C6}\x{62C7}\x{62C8}\x{62C9}\x{62CA}\x{62CB}\x{62CC}\x{62CD}' . + '\x{62CE}\x{62CF}\x{62D0}\x{62D1}\x{62D2}\x{62D3}\x{62D4}\x{62D5}\x{62D6}' . + '\x{62D7}\x{62D8}\x{62D9}\x{62DA}\x{62DB}\x{62DC}\x{62DD}\x{62DF}\x{62E0}' . + '\x{62E1}\x{62E2}\x{62E3}\x{62E4}\x{62E5}\x{62E6}\x{62E7}\x{62E8}\x{62E9}' . + '\x{62EB}\x{62EC}\x{62ED}\x{62EE}\x{62EF}\x{62F0}\x{62F1}\x{62F2}\x{62F3}' . + '\x{62F4}\x{62F5}\x{62F6}\x{62F7}\x{62F8}\x{62F9}\x{62FA}\x{62FB}\x{62FC}' . + '\x{62FD}\x{62FE}\x{62FF}\x{6300}\x{6301}\x{6302}\x{6303}\x{6304}\x{6305}' . + '\x{6306}\x{6307}\x{6308}\x{6309}\x{630B}\x{630C}\x{630D}\x{630E}\x{630F}' . + '\x{6310}\x{6311}\x{6312}\x{6313}\x{6314}\x{6315}\x{6316}\x{6318}\x{6319}' . + '\x{631A}\x{631B}\x{631C}\x{631D}\x{631E}\x{631F}\x{6320}\x{6321}\x{6322}' . + '\x{6323}\x{6324}\x{6325}\x{6326}\x{6327}\x{6328}\x{6329}\x{632A}\x{632B}' . + '\x{632C}\x{632D}\x{632E}\x{632F}\x{6330}\x{6332}\x{6333}\x{6334}\x{6336}' . + '\x{6338}\x{6339}\x{633A}\x{633B}\x{633C}\x{633D}\x{633E}\x{6340}\x{6341}' . + '\x{6342}\x{6343}\x{6344}\x{6345}\x{6346}\x{6347}\x{6348}\x{6349}\x{634A}' . + '\x{634B}\x{634C}\x{634D}\x{634E}\x{634F}\x{6350}\x{6351}\x{6352}\x{6353}' . + '\x{6354}\x{6355}\x{6356}\x{6357}\x{6358}\x{6359}\x{635A}\x{635C}\x{635D}' . + '\x{635E}\x{635F}\x{6360}\x{6361}\x{6362}\x{6363}\x{6364}\x{6365}\x{6366}' . + '\x{6367}\x{6368}\x{6369}\x{636A}\x{636B}\x{636C}\x{636D}\x{636E}\x{636F}' . + '\x{6370}\x{6371}\x{6372}\x{6373}\x{6374}\x{6375}\x{6376}\x{6377}\x{6378}' . + '\x{6379}\x{637A}\x{637B}\x{637C}\x{637D}\x{637E}\x{6380}\x{6381}\x{6382}' . + '\x{6383}\x{6384}\x{6385}\x{6386}\x{6387}\x{6388}\x{6389}\x{638A}\x{638C}' . + '\x{638D}\x{638E}\x{638F}\x{6390}\x{6391}\x{6392}\x{6394}\x{6395}\x{6396}' . + '\x{6397}\x{6398}\x{6399}\x{639A}\x{639B}\x{639C}\x{639D}\x{639E}\x{639F}' . + '\x{63A0}\x{63A1}\x{63A2}\x{63A3}\x{63A4}\x{63A5}\x{63A6}\x{63A7}\x{63A8}' . + '\x{63A9}\x{63AA}\x{63AB}\x{63AC}\x{63AD}\x{63AE}\x{63AF}\x{63B0}\x{63B1}' . + '\x{63B2}\x{63B3}\x{63B4}\x{63B5}\x{63B6}\x{63B7}\x{63B8}\x{63B9}\x{63BA}' . + '\x{63BC}\x{63BD}\x{63BE}\x{63BF}\x{63C0}\x{63C1}\x{63C2}\x{63C3}\x{63C4}' . + '\x{63C5}\x{63C6}\x{63C7}\x{63C8}\x{63C9}\x{63CA}\x{63CB}\x{63CC}\x{63CD}' . + '\x{63CE}\x{63CF}\x{63D0}\x{63D2}\x{63D3}\x{63D4}\x{63D5}\x{63D6}\x{63D7}' . + '\x{63D8}\x{63D9}\x{63DA}\x{63DB}\x{63DC}\x{63DD}\x{63DE}\x{63DF}\x{63E0}' . + '\x{63E1}\x{63E2}\x{63E3}\x{63E4}\x{63E5}\x{63E6}\x{63E7}\x{63E8}\x{63E9}' . + '\x{63EA}\x{63EB}\x{63EC}\x{63ED}\x{63EE}\x{63EF}\x{63F0}\x{63F1}\x{63F2}' . + '\x{63F3}\x{63F4}\x{63F5}\x{63F6}\x{63F7}\x{63F8}\x{63F9}\x{63FA}\x{63FB}' . + '\x{63FC}\x{63FD}\x{63FE}\x{63FF}\x{6400}\x{6401}\x{6402}\x{6403}\x{6404}' . + '\x{6405}\x{6406}\x{6408}\x{6409}\x{640A}\x{640B}\x{640C}\x{640D}\x{640E}' . + '\x{640F}\x{6410}\x{6411}\x{6412}\x{6413}\x{6414}\x{6415}\x{6416}\x{6417}' . + '\x{6418}\x{6419}\x{641A}\x{641B}\x{641C}\x{641D}\x{641E}\x{641F}\x{6420}' . + '\x{6421}\x{6422}\x{6423}\x{6424}\x{6425}\x{6426}\x{6427}\x{6428}\x{6429}' . + '\x{642A}\x{642B}\x{642C}\x{642D}\x{642E}\x{642F}\x{6430}\x{6431}\x{6432}' . + '\x{6433}\x{6434}\x{6435}\x{6436}\x{6437}\x{6438}\x{6439}\x{643A}\x{643D}' . + '\x{643E}\x{643F}\x{6440}\x{6441}\x{6443}\x{6444}\x{6445}\x{6446}\x{6447}' . + '\x{6448}\x{644A}\x{644B}\x{644C}\x{644D}\x{644E}\x{644F}\x{6450}\x{6451}' . + '\x{6452}\x{6453}\x{6454}\x{6455}\x{6456}\x{6457}\x{6458}\x{6459}\x{645B}' . + '\x{645C}\x{645D}\x{645E}\x{645F}\x{6460}\x{6461}\x{6462}\x{6463}\x{6464}' . + '\x{6465}\x{6466}\x{6467}\x{6468}\x{6469}\x{646A}\x{646B}\x{646C}\x{646D}' . + '\x{646E}\x{646F}\x{6470}\x{6471}\x{6472}\x{6473}\x{6474}\x{6475}\x{6476}' . + '\x{6477}\x{6478}\x{6479}\x{647A}\x{647B}\x{647C}\x{647D}\x{647F}\x{6480}' . + '\x{6481}\x{6482}\x{6483}\x{6484}\x{6485}\x{6487}\x{6488}\x{6489}\x{648A}' . + '\x{648B}\x{648C}\x{648D}\x{648E}\x{648F}\x{6490}\x{6491}\x{6492}\x{6493}' . + '\x{6494}\x{6495}\x{6496}\x{6497}\x{6498}\x{6499}\x{649A}\x{649B}\x{649C}' . + '\x{649D}\x{649E}\x{649F}\x{64A0}\x{64A2}\x{64A3}\x{64A4}\x{64A5}\x{64A6}' . + '\x{64A7}\x{64A8}\x{64A9}\x{64AA}\x{64AB}\x{64AC}\x{64AD}\x{64AE}\x{64B0}' . + '\x{64B1}\x{64B2}\x{64B3}\x{64B4}\x{64B5}\x{64B7}\x{64B8}\x{64B9}\x{64BA}' . + '\x{64BB}\x{64BC}\x{64BD}\x{64BE}\x{64BF}\x{64C0}\x{64C1}\x{64C2}\x{64C3}' . + '\x{64C4}\x{64C5}\x{64C6}\x{64C7}\x{64C9}\x{64CA}\x{64CB}\x{64CC}\x{64CD}' . + '\x{64CE}\x{64CF}\x{64D0}\x{64D1}\x{64D2}\x{64D3}\x{64D4}\x{64D6}\x{64D7}' . + '\x{64D8}\x{64D9}\x{64DA}\x{64DB}\x{64DC}\x{64DD}\x{64DE}\x{64DF}\x{64E0}' . + '\x{64E2}\x{64E3}\x{64E4}\x{64E6}\x{64E7}\x{64E8}\x{64E9}\x{64EA}\x{64EB}' . + '\x{64EC}\x{64ED}\x{64EF}\x{64F0}\x{64F1}\x{64F2}\x{64F3}\x{64F4}\x{64F6}' . + '\x{64F7}\x{64F8}\x{64FA}\x{64FB}\x{64FC}\x{64FD}\x{64FE}\x{64FF}\x{6500}' . + '\x{6501}\x{6503}\x{6504}\x{6505}\x{6506}\x{6507}\x{6508}\x{6509}\x{650B}' . + '\x{650C}\x{650D}\x{650E}\x{650F}\x{6510}\x{6511}\x{6512}\x{6513}\x{6514}' . + '\x{6515}\x{6516}\x{6517}\x{6518}\x{6519}\x{651A}\x{651B}\x{651C}\x{651D}' . + '\x{651E}\x{6520}\x{6521}\x{6522}\x{6523}\x{6524}\x{6525}\x{6526}\x{6527}' . + '\x{6529}\x{652A}\x{652B}\x{652C}\x{652D}\x{652E}\x{652F}\x{6530}\x{6531}' . + '\x{6532}\x{6533}\x{6534}\x{6535}\x{6536}\x{6537}\x{6538}\x{6539}\x{653A}' . + '\x{653B}\x{653C}\x{653D}\x{653E}\x{653F}\x{6541}\x{6543}\x{6544}\x{6545}' . + '\x{6546}\x{6547}\x{6548}\x{6549}\x{654A}\x{654B}\x{654C}\x{654D}\x{654E}' . + '\x{654F}\x{6550}\x{6551}\x{6552}\x{6553}\x{6554}\x{6555}\x{6556}\x{6557}' . + '\x{6558}\x{6559}\x{655B}\x{655C}\x{655D}\x{655E}\x{6560}\x{6561}\x{6562}' . + '\x{6563}\x{6564}\x{6565}\x{6566}\x{6567}\x{6568}\x{6569}\x{656A}\x{656B}' . + '\x{656C}\x{656E}\x{656F}\x{6570}\x{6571}\x{6572}\x{6573}\x{6574}\x{6575}' . + '\x{6576}\x{6577}\x{6578}\x{6579}\x{657A}\x{657B}\x{657C}\x{657E}\x{657F}' . + '\x{6580}\x{6581}\x{6582}\x{6583}\x{6584}\x{6585}\x{6586}\x{6587}\x{6588}' . + '\x{6589}\x{658B}\x{658C}\x{658D}\x{658E}\x{658F}\x{6590}\x{6591}\x{6592}' . + '\x{6593}\x{6594}\x{6595}\x{6596}\x{6597}\x{6598}\x{6599}\x{659B}\x{659C}' . + '\x{659D}\x{659E}\x{659F}\x{65A0}\x{65A1}\x{65A2}\x{65A3}\x{65A4}\x{65A5}' . + '\x{65A6}\x{65A7}\x{65A8}\x{65A9}\x{65AA}\x{65AB}\x{65AC}\x{65AD}\x{65AE}' . + '\x{65AF}\x{65B0}\x{65B1}\x{65B2}\x{65B3}\x{65B4}\x{65B6}\x{65B7}\x{65B8}' . + '\x{65B9}\x{65BA}\x{65BB}\x{65BC}\x{65BD}\x{65BF}\x{65C0}\x{65C1}\x{65C2}' . + '\x{65C3}\x{65C4}\x{65C5}\x{65C6}\x{65C7}\x{65CA}\x{65CB}\x{65CC}\x{65CD}' . + '\x{65CE}\x{65CF}\x{65D0}\x{65D2}\x{65D3}\x{65D4}\x{65D5}\x{65D6}\x{65D7}' . + '\x{65DA}\x{65DB}\x{65DD}\x{65DE}\x{65DF}\x{65E0}\x{65E1}\x{65E2}\x{65E3}' . + '\x{65E5}\x{65E6}\x{65E7}\x{65E8}\x{65E9}\x{65EB}\x{65EC}\x{65ED}\x{65EE}' . + '\x{65EF}\x{65F0}\x{65F1}\x{65F2}\x{65F3}\x{65F4}\x{65F5}\x{65F6}\x{65F7}' . + '\x{65F8}\x{65FA}\x{65FB}\x{65FC}\x{65FD}\x{6600}\x{6601}\x{6602}\x{6603}' . + '\x{6604}\x{6605}\x{6606}\x{6607}\x{6608}\x{6609}\x{660A}\x{660B}\x{660C}' . + '\x{660D}\x{660E}\x{660F}\x{6610}\x{6611}\x{6612}\x{6613}\x{6614}\x{6615}' . + '\x{6616}\x{6618}\x{6619}\x{661A}\x{661B}\x{661C}\x{661D}\x{661F}\x{6620}' . + '\x{6621}\x{6622}\x{6623}\x{6624}\x{6625}\x{6626}\x{6627}\x{6628}\x{6629}' . + '\x{662A}\x{662B}\x{662D}\x{662E}\x{662F}\x{6630}\x{6631}\x{6632}\x{6633}' . + '\x{6634}\x{6635}\x{6636}\x{6639}\x{663A}\x{663C}\x{663D}\x{663E}\x{6640}' . + '\x{6641}\x{6642}\x{6643}\x{6644}\x{6645}\x{6646}\x{6647}\x{6649}\x{664A}' . + '\x{664B}\x{664C}\x{664E}\x{664F}\x{6650}\x{6651}\x{6652}\x{6653}\x{6654}' . + '\x{6655}\x{6656}\x{6657}\x{6658}\x{6659}\x{665A}\x{665B}\x{665C}\x{665D}' . + '\x{665E}\x{665F}\x{6661}\x{6662}\x{6664}\x{6665}\x{6666}\x{6668}\x{6669}' . + '\x{666A}\x{666B}\x{666C}\x{666D}\x{666E}\x{666F}\x{6670}\x{6671}\x{6672}' . + '\x{6673}\x{6674}\x{6675}\x{6676}\x{6677}\x{6678}\x{6679}\x{667A}\x{667B}' . + '\x{667C}\x{667D}\x{667E}\x{667F}\x{6680}\x{6681}\x{6682}\x{6683}\x{6684}' . + '\x{6685}\x{6686}\x{6687}\x{6688}\x{6689}\x{668A}\x{668B}\x{668C}\x{668D}' . + '\x{668E}\x{668F}\x{6690}\x{6691}\x{6693}\x{6694}\x{6695}\x{6696}\x{6697}' . + '\x{6698}\x{6699}\x{669A}\x{669B}\x{669D}\x{669F}\x{66A0}\x{66A1}\x{66A2}' . + '\x{66A3}\x{66A4}\x{66A5}\x{66A6}\x{66A7}\x{66A8}\x{66A9}\x{66AA}\x{66AB}' . + '\x{66AE}\x{66AF}\x{66B0}\x{66B1}\x{66B2}\x{66B3}\x{66B4}\x{66B5}\x{66B6}' . + '\x{66B7}\x{66B8}\x{66B9}\x{66BA}\x{66BB}\x{66BC}\x{66BD}\x{66BE}\x{66BF}' . + '\x{66C0}\x{66C1}\x{66C2}\x{66C3}\x{66C4}\x{66C5}\x{66C6}\x{66C7}\x{66C8}' . + '\x{66C9}\x{66CA}\x{66CB}\x{66CC}\x{66CD}\x{66CE}\x{66CF}\x{66D1}\x{66D2}' . + '\x{66D4}\x{66D5}\x{66D6}\x{66D8}\x{66D9}\x{66DA}\x{66DB}\x{66DC}\x{66DD}' . + '\x{66DE}\x{66E0}\x{66E1}\x{66E2}\x{66E3}\x{66E4}\x{66E5}\x{66E6}\x{66E7}' . + '\x{66E8}\x{66E9}\x{66EA}\x{66EB}\x{66EC}\x{66ED}\x{66EE}\x{66F0}\x{66F1}' . + '\x{66F2}\x{66F3}\x{66F4}\x{66F5}\x{66F6}\x{66F7}\x{66F8}\x{66F9}\x{66FA}' . + '\x{66FB}\x{66FC}\x{66FE}\x{66FF}\x{6700}\x{6701}\x{6703}\x{6704}\x{6705}' . + '\x{6706}\x{6708}\x{6709}\x{670A}\x{670B}\x{670C}\x{670D}\x{670E}\x{670F}' . + '\x{6710}\x{6711}\x{6712}\x{6713}\x{6714}\x{6715}\x{6716}\x{6717}\x{6718}' . + '\x{671A}\x{671B}\x{671C}\x{671D}\x{671E}\x{671F}\x{6720}\x{6721}\x{6722}' . + '\x{6723}\x{6725}\x{6726}\x{6727}\x{6728}\x{672A}\x{672B}\x{672C}\x{672D}' . + '\x{672E}\x{672F}\x{6730}\x{6731}\x{6732}\x{6733}\x{6734}\x{6735}\x{6736}' . + '\x{6737}\x{6738}\x{6739}\x{673A}\x{673B}\x{673C}\x{673D}\x{673E}\x{673F}' . + '\x{6740}\x{6741}\x{6742}\x{6743}\x{6744}\x{6745}\x{6746}\x{6747}\x{6748}' . + '\x{6749}\x{674A}\x{674B}\x{674C}\x{674D}\x{674E}\x{674F}\x{6750}\x{6751}' . + '\x{6752}\x{6753}\x{6754}\x{6755}\x{6756}\x{6757}\x{6758}\x{6759}\x{675A}' . + '\x{675B}\x{675C}\x{675D}\x{675E}\x{675F}\x{6760}\x{6761}\x{6762}\x{6763}' . + '\x{6764}\x{6765}\x{6766}\x{6768}\x{6769}\x{676A}\x{676B}\x{676C}\x{676D}' . + '\x{676E}\x{676F}\x{6770}\x{6771}\x{6772}\x{6773}\x{6774}\x{6775}\x{6776}' . + '\x{6777}\x{6778}\x{6779}\x{677A}\x{677B}\x{677C}\x{677D}\x{677E}\x{677F}' . + '\x{6780}\x{6781}\x{6782}\x{6783}\x{6784}\x{6785}\x{6786}\x{6787}\x{6789}' . + '\x{678A}\x{678B}\x{678C}\x{678D}\x{678E}\x{678F}\x{6790}\x{6791}\x{6792}' . + '\x{6793}\x{6794}\x{6795}\x{6797}\x{6798}\x{6799}\x{679A}\x{679B}\x{679C}' . + '\x{679D}\x{679E}\x{679F}\x{67A0}\x{67A1}\x{67A2}\x{67A3}\x{67A4}\x{67A5}' . + '\x{67A6}\x{67A7}\x{67A8}\x{67AA}\x{67AB}\x{67AC}\x{67AD}\x{67AE}\x{67AF}' . + '\x{67B0}\x{67B1}\x{67B2}\x{67B3}\x{67B4}\x{67B5}\x{67B6}\x{67B7}\x{67B8}' . + '\x{67B9}\x{67BA}\x{67BB}\x{67BC}\x{67BE}\x{67C0}\x{67C1}\x{67C2}\x{67C3}' . + '\x{67C4}\x{67C5}\x{67C6}\x{67C7}\x{67C8}\x{67C9}\x{67CA}\x{67CB}\x{67CC}' . + '\x{67CD}\x{67CE}\x{67CF}\x{67D0}\x{67D1}\x{67D2}\x{67D3}\x{67D4}\x{67D6}' . + '\x{67D8}\x{67D9}\x{67DA}\x{67DB}\x{67DC}\x{67DD}\x{67DE}\x{67DF}\x{67E0}' . + '\x{67E1}\x{67E2}\x{67E3}\x{67E4}\x{67E5}\x{67E6}\x{67E7}\x{67E8}\x{67E9}' . + '\x{67EA}\x{67EB}\x{67EC}\x{67ED}\x{67EE}\x{67EF}\x{67F0}\x{67F1}\x{67F2}' . + '\x{67F3}\x{67F4}\x{67F5}\x{67F6}\x{67F7}\x{67F8}\x{67FA}\x{67FB}\x{67FC}' . + '\x{67FD}\x{67FE}\x{67FF}\x{6800}\x{6802}\x{6803}\x{6804}\x{6805}\x{6806}' . + '\x{6807}\x{6808}\x{6809}\x{680A}\x{680B}\x{680C}\x{680D}\x{680E}\x{680F}' . + '\x{6810}\x{6811}\x{6812}\x{6813}\x{6814}\x{6816}\x{6817}\x{6818}\x{6819}' . + '\x{681A}\x{681B}\x{681C}\x{681D}\x{681F}\x{6820}\x{6821}\x{6822}\x{6823}' . + '\x{6824}\x{6825}\x{6826}\x{6828}\x{6829}\x{682A}\x{682B}\x{682C}\x{682D}' . + '\x{682E}\x{682F}\x{6831}\x{6832}\x{6833}\x{6834}\x{6835}\x{6836}\x{6837}' . + '\x{6838}\x{6839}\x{683A}\x{683B}\x{683C}\x{683D}\x{683E}\x{683F}\x{6840}' . + '\x{6841}\x{6842}\x{6843}\x{6844}\x{6845}\x{6846}\x{6847}\x{6848}\x{6849}' . + '\x{684A}\x{684B}\x{684C}\x{684D}\x{684E}\x{684F}\x{6850}\x{6851}\x{6852}' . + '\x{6853}\x{6854}\x{6855}\x{6856}\x{6857}\x{685B}\x{685D}\x{6860}\x{6861}' . + '\x{6862}\x{6863}\x{6864}\x{6865}\x{6866}\x{6867}\x{6868}\x{6869}\x{686A}' . + '\x{686B}\x{686C}\x{686D}\x{686E}\x{686F}\x{6870}\x{6871}\x{6872}\x{6873}' . + '\x{6874}\x{6875}\x{6876}\x{6877}\x{6878}\x{6879}\x{687B}\x{687C}\x{687D}' . + '\x{687E}\x{687F}\x{6880}\x{6881}\x{6882}\x{6883}\x{6884}\x{6885}\x{6886}' . + '\x{6887}\x{6888}\x{6889}\x{688A}\x{688B}\x{688C}\x{688D}\x{688E}\x{688F}' . + '\x{6890}\x{6891}\x{6892}\x{6893}\x{6894}\x{6896}\x{6897}\x{6898}\x{689A}' . + '\x{689B}\x{689C}\x{689D}\x{689E}\x{689F}\x{68A0}\x{68A1}\x{68A2}\x{68A3}' . + '\x{68A4}\x{68A6}\x{68A7}\x{68A8}\x{68A9}\x{68AA}\x{68AB}\x{68AC}\x{68AD}' . + '\x{68AE}\x{68AF}\x{68B0}\x{68B1}\x{68B2}\x{68B3}\x{68B4}\x{68B5}\x{68B6}' . + '\x{68B7}\x{68B9}\x{68BB}\x{68BC}\x{68BD}\x{68BE}\x{68BF}\x{68C0}\x{68C1}' . + '\x{68C2}\x{68C4}\x{68C6}\x{68C7}\x{68C8}\x{68C9}\x{68CA}\x{68CB}\x{68CC}' . + '\x{68CD}\x{68CE}\x{68CF}\x{68D0}\x{68D1}\x{68D2}\x{68D3}\x{68D4}\x{68D5}' . + '\x{68D6}\x{68D7}\x{68D8}\x{68DA}\x{68DB}\x{68DC}\x{68DD}\x{68DE}\x{68DF}' . + '\x{68E0}\x{68E1}\x{68E3}\x{68E4}\x{68E6}\x{68E7}\x{68E8}\x{68E9}\x{68EA}' . + '\x{68EB}\x{68EC}\x{68ED}\x{68EE}\x{68EF}\x{68F0}\x{68F1}\x{68F2}\x{68F3}' . + '\x{68F4}\x{68F5}\x{68F6}\x{68F7}\x{68F8}\x{68F9}\x{68FA}\x{68FB}\x{68FC}' . + '\x{68FD}\x{68FE}\x{68FF}\x{6901}\x{6902}\x{6903}\x{6904}\x{6905}\x{6906}' . + '\x{6907}\x{6908}\x{690A}\x{690B}\x{690C}\x{690D}\x{690E}\x{690F}\x{6910}' . + '\x{6911}\x{6912}\x{6913}\x{6914}\x{6915}\x{6916}\x{6917}\x{6918}\x{6919}' . + '\x{691A}\x{691B}\x{691C}\x{691D}\x{691E}\x{691F}\x{6920}\x{6921}\x{6922}' . + '\x{6923}\x{6924}\x{6925}\x{6926}\x{6927}\x{6928}\x{6929}\x{692A}\x{692B}' . + '\x{692C}\x{692D}\x{692E}\x{692F}\x{6930}\x{6931}\x{6932}\x{6933}\x{6934}' . + '\x{6935}\x{6936}\x{6937}\x{6938}\x{6939}\x{693A}\x{693B}\x{693C}\x{693D}' . + '\x{693F}\x{6940}\x{6941}\x{6942}\x{6943}\x{6944}\x{6945}\x{6946}\x{6947}' . + '\x{6948}\x{6949}\x{694A}\x{694B}\x{694C}\x{694E}\x{694F}\x{6950}\x{6951}' . + '\x{6952}\x{6953}\x{6954}\x{6955}\x{6956}\x{6957}\x{6958}\x{6959}\x{695A}' . + '\x{695B}\x{695C}\x{695D}\x{695E}\x{695F}\x{6960}\x{6961}\x{6962}\x{6963}' . + '\x{6964}\x{6965}\x{6966}\x{6967}\x{6968}\x{6969}\x{696A}\x{696B}\x{696C}' . + '\x{696D}\x{696E}\x{696F}\x{6970}\x{6971}\x{6972}\x{6973}\x{6974}\x{6975}' . + '\x{6976}\x{6977}\x{6978}\x{6979}\x{697A}\x{697B}\x{697C}\x{697D}\x{697E}' . + '\x{697F}\x{6980}\x{6981}\x{6982}\x{6983}\x{6984}\x{6985}\x{6986}\x{6987}' . + '\x{6988}\x{6989}\x{698A}\x{698B}\x{698C}\x{698D}\x{698E}\x{698F}\x{6990}' . + '\x{6991}\x{6992}\x{6993}\x{6994}\x{6995}\x{6996}\x{6997}\x{6998}\x{6999}' . + '\x{699A}\x{699B}\x{699C}\x{699D}\x{699E}\x{69A0}\x{69A1}\x{69A3}\x{69A4}' . + '\x{69A5}\x{69A6}\x{69A7}\x{69A8}\x{69A9}\x{69AA}\x{69AB}\x{69AC}\x{69AD}' . + '\x{69AE}\x{69AF}\x{69B0}\x{69B1}\x{69B2}\x{69B3}\x{69B4}\x{69B5}\x{69B6}' . + '\x{69B7}\x{69B8}\x{69B9}\x{69BA}\x{69BB}\x{69BC}\x{69BD}\x{69BE}\x{69BF}' . + '\x{69C1}\x{69C2}\x{69C3}\x{69C4}\x{69C5}\x{69C6}\x{69C7}\x{69C8}\x{69C9}' . + '\x{69CA}\x{69CB}\x{69CC}\x{69CD}\x{69CE}\x{69CF}\x{69D0}\x{69D3}\x{69D4}' . + '\x{69D8}\x{69D9}\x{69DA}\x{69DB}\x{69DC}\x{69DD}\x{69DE}\x{69DF}\x{69E0}' . + '\x{69E1}\x{69E2}\x{69E3}\x{69E4}\x{69E5}\x{69E6}\x{69E7}\x{69E8}\x{69E9}' . + '\x{69EA}\x{69EB}\x{69EC}\x{69ED}\x{69EE}\x{69EF}\x{69F0}\x{69F1}\x{69F2}' . + '\x{69F3}\x{69F4}\x{69F5}\x{69F6}\x{69F7}\x{69F8}\x{69FA}\x{69FB}\x{69FC}' . + '\x{69FD}\x{69FE}\x{69FF}\x{6A00}\x{6A01}\x{6A02}\x{6A04}\x{6A05}\x{6A06}' . + '\x{6A07}\x{6A08}\x{6A09}\x{6A0A}\x{6A0B}\x{6A0D}\x{6A0E}\x{6A0F}\x{6A10}' . + '\x{6A11}\x{6A12}\x{6A13}\x{6A14}\x{6A15}\x{6A16}\x{6A17}\x{6A18}\x{6A19}' . + '\x{6A1A}\x{6A1B}\x{6A1D}\x{6A1E}\x{6A1F}\x{6A20}\x{6A21}\x{6A22}\x{6A23}' . + '\x{6A25}\x{6A26}\x{6A27}\x{6A28}\x{6A29}\x{6A2A}\x{6A2B}\x{6A2C}\x{6A2D}' . + '\x{6A2E}\x{6A2F}\x{6A30}\x{6A31}\x{6A32}\x{6A33}\x{6A34}\x{6A35}\x{6A36}' . + '\x{6A38}\x{6A39}\x{6A3A}\x{6A3B}\x{6A3C}\x{6A3D}\x{6A3E}\x{6A3F}\x{6A40}' . + '\x{6A41}\x{6A42}\x{6A43}\x{6A44}\x{6A45}\x{6A46}\x{6A47}\x{6A48}\x{6A49}' . + '\x{6A4B}\x{6A4C}\x{6A4D}\x{6A4E}\x{6A4F}\x{6A50}\x{6A51}\x{6A52}\x{6A54}' . + '\x{6A55}\x{6A56}\x{6A57}\x{6A58}\x{6A59}\x{6A5A}\x{6A5B}\x{6A5D}\x{6A5E}' . + '\x{6A5F}\x{6A60}\x{6A61}\x{6A62}\x{6A63}\x{6A64}\x{6A65}\x{6A66}\x{6A67}' . + '\x{6A68}\x{6A69}\x{6A6A}\x{6A6B}\x{6A6C}\x{6A6D}\x{6A6F}\x{6A71}\x{6A72}' . + '\x{6A73}\x{6A74}\x{6A75}\x{6A76}\x{6A77}\x{6A78}\x{6A79}\x{6A7A}\x{6A7B}' . + '\x{6A7C}\x{6A7D}\x{6A7E}\x{6A7F}\x{6A80}\x{6A81}\x{6A82}\x{6A83}\x{6A84}' . + '\x{6A85}\x{6A87}\x{6A88}\x{6A89}\x{6A8B}\x{6A8C}\x{6A8D}\x{6A8E}\x{6A90}' . + '\x{6A91}\x{6A92}\x{6A93}\x{6A94}\x{6A95}\x{6A96}\x{6A97}\x{6A98}\x{6A9A}' . + '\x{6A9B}\x{6A9C}\x{6A9E}\x{6A9F}\x{6AA0}\x{6AA1}\x{6AA2}\x{6AA3}\x{6AA4}' . + '\x{6AA5}\x{6AA6}\x{6AA7}\x{6AA8}\x{6AA9}\x{6AAB}\x{6AAC}\x{6AAD}\x{6AAE}' . + '\x{6AAF}\x{6AB0}\x{6AB2}\x{6AB3}\x{6AB4}\x{6AB5}\x{6AB6}\x{6AB7}\x{6AB8}' . + '\x{6AB9}\x{6ABA}\x{6ABB}\x{6ABC}\x{6ABD}\x{6ABF}\x{6AC1}\x{6AC2}\x{6AC3}' . + '\x{6AC5}\x{6AC6}\x{6AC7}\x{6ACA}\x{6ACB}\x{6ACC}\x{6ACD}\x{6ACE}\x{6ACF}' . + '\x{6AD0}\x{6AD1}\x{6AD2}\x{6AD3}\x{6AD4}\x{6AD5}\x{6AD6}\x{6AD7}\x{6AD9}' . + '\x{6ADA}\x{6ADB}\x{6ADC}\x{6ADD}\x{6ADE}\x{6ADF}\x{6AE0}\x{6AE1}\x{6AE2}' . + '\x{6AE3}\x{6AE4}\x{6AE5}\x{6AE6}\x{6AE7}\x{6AE8}\x{6AEA}\x{6AEB}\x{6AEC}' . + '\x{6AED}\x{6AEE}\x{6AEF}\x{6AF0}\x{6AF1}\x{6AF2}\x{6AF3}\x{6AF4}\x{6AF5}' . + '\x{6AF6}\x{6AF7}\x{6AF8}\x{6AF9}\x{6AFA}\x{6AFB}\x{6AFC}\x{6AFD}\x{6AFE}' . + '\x{6AFF}\x{6B00}\x{6B01}\x{6B02}\x{6B03}\x{6B04}\x{6B05}\x{6B06}\x{6B07}' . + '\x{6B08}\x{6B09}\x{6B0A}\x{6B0B}\x{6B0C}\x{6B0D}\x{6B0F}\x{6B10}\x{6B11}' . + '\x{6B12}\x{6B13}\x{6B14}\x{6B15}\x{6B16}\x{6B17}\x{6B18}\x{6B19}\x{6B1A}' . + '\x{6B1C}\x{6B1D}\x{6B1E}\x{6B1F}\x{6B20}\x{6B21}\x{6B22}\x{6B23}\x{6B24}' . + '\x{6B25}\x{6B26}\x{6B27}\x{6B28}\x{6B29}\x{6B2A}\x{6B2B}\x{6B2C}\x{6B2D}' . + '\x{6B2F}\x{6B30}\x{6B31}\x{6B32}\x{6B33}\x{6B34}\x{6B36}\x{6B37}\x{6B38}' . + '\x{6B39}\x{6B3A}\x{6B3B}\x{6B3C}\x{6B3D}\x{6B3E}\x{6B3F}\x{6B41}\x{6B42}' . + '\x{6B43}\x{6B44}\x{6B45}\x{6B46}\x{6B47}\x{6B48}\x{6B49}\x{6B4A}\x{6B4B}' . + '\x{6B4C}\x{6B4D}\x{6B4E}\x{6B4F}\x{6B50}\x{6B51}\x{6B52}\x{6B53}\x{6B54}' . + '\x{6B55}\x{6B56}\x{6B59}\x{6B5A}\x{6B5B}\x{6B5C}\x{6B5E}\x{6B5F}\x{6B60}' . + '\x{6B61}\x{6B62}\x{6B63}\x{6B64}\x{6B65}\x{6B66}\x{6B67}\x{6B69}\x{6B6A}' . + '\x{6B6B}\x{6B6D}\x{6B6F}\x{6B70}\x{6B72}\x{6B73}\x{6B74}\x{6B76}\x{6B77}' . + '\x{6B78}\x{6B79}\x{6B7A}\x{6B7B}\x{6B7C}\x{6B7E}\x{6B7F}\x{6B80}\x{6B81}' . + '\x{6B82}\x{6B83}\x{6B84}\x{6B85}\x{6B86}\x{6B87}\x{6B88}\x{6B89}\x{6B8A}' . + '\x{6B8B}\x{6B8C}\x{6B8D}\x{6B8E}\x{6B8F}\x{6B90}\x{6B91}\x{6B92}\x{6B93}' . + '\x{6B94}\x{6B95}\x{6B96}\x{6B97}\x{6B98}\x{6B99}\x{6B9A}\x{6B9B}\x{6B9C}' . + '\x{6B9D}\x{6B9E}\x{6B9F}\x{6BA0}\x{6BA1}\x{6BA2}\x{6BA3}\x{6BA4}\x{6BA5}' . + '\x{6BA6}\x{6BA7}\x{6BA8}\x{6BA9}\x{6BAA}\x{6BAB}\x{6BAC}\x{6BAD}\x{6BAE}' . + '\x{6BAF}\x{6BB0}\x{6BB2}\x{6BB3}\x{6BB4}\x{6BB5}\x{6BB6}\x{6BB7}\x{6BB9}' . + '\x{6BBA}\x{6BBB}\x{6BBC}\x{6BBD}\x{6BBE}\x{6BBF}\x{6BC0}\x{6BC1}\x{6BC2}' . + '\x{6BC3}\x{6BC4}\x{6BC5}\x{6BC6}\x{6BC7}\x{6BC8}\x{6BC9}\x{6BCA}\x{6BCB}' . + '\x{6BCC}\x{6BCD}\x{6BCE}\x{6BCF}\x{6BD0}\x{6BD1}\x{6BD2}\x{6BD3}\x{6BD4}' . + '\x{6BD5}\x{6BD6}\x{6BD7}\x{6BD8}\x{6BD9}\x{6BDA}\x{6BDB}\x{6BDC}\x{6BDD}' . + '\x{6BDE}\x{6BDF}\x{6BE0}\x{6BE1}\x{6BE2}\x{6BE3}\x{6BE4}\x{6BE5}\x{6BE6}' . + '\x{6BE7}\x{6BE8}\x{6BEA}\x{6BEB}\x{6BEC}\x{6BED}\x{6BEE}\x{6BEF}\x{6BF0}' . + '\x{6BF2}\x{6BF3}\x{6BF5}\x{6BF6}\x{6BF7}\x{6BF8}\x{6BF9}\x{6BFB}\x{6BFC}' . + '\x{6BFD}\x{6BFE}\x{6BFF}\x{6C00}\x{6C01}\x{6C02}\x{6C03}\x{6C04}\x{6C05}' . + '\x{6C06}\x{6C07}\x{6C08}\x{6C09}\x{6C0B}\x{6C0C}\x{6C0D}\x{6C0E}\x{6C0F}' . + '\x{6C10}\x{6C11}\x{6C12}\x{6C13}\x{6C14}\x{6C15}\x{6C16}\x{6C18}\x{6C19}' . + '\x{6C1A}\x{6C1B}\x{6C1D}\x{6C1E}\x{6C1F}\x{6C20}\x{6C21}\x{6C22}\x{6C23}' . + '\x{6C24}\x{6C25}\x{6C26}\x{6C27}\x{6C28}\x{6C29}\x{6C2A}\x{6C2B}\x{6C2C}' . + '\x{6C2E}\x{6C2F}\x{6C30}\x{6C31}\x{6C32}\x{6C33}\x{6C34}\x{6C35}\x{6C36}' . + '\x{6C37}\x{6C38}\x{6C3A}\x{6C3B}\x{6C3D}\x{6C3E}\x{6C3F}\x{6C40}\x{6C41}' . + '\x{6C42}\x{6C43}\x{6C44}\x{6C46}\x{6C47}\x{6C48}\x{6C49}\x{6C4A}\x{6C4B}' . + '\x{6C4C}\x{6C4D}\x{6C4E}\x{6C4F}\x{6C50}\x{6C51}\x{6C52}\x{6C53}\x{6C54}' . + '\x{6C55}\x{6C56}\x{6C57}\x{6C58}\x{6C59}\x{6C5A}\x{6C5B}\x{6C5C}\x{6C5D}' . + '\x{6C5E}\x{6C5F}\x{6C60}\x{6C61}\x{6C62}\x{6C63}\x{6C64}\x{6C65}\x{6C66}' . + '\x{6C67}\x{6C68}\x{6C69}\x{6C6A}\x{6C6B}\x{6C6D}\x{6C6F}\x{6C70}\x{6C71}' . + '\x{6C72}\x{6C73}\x{6C74}\x{6C75}\x{6C76}\x{6C77}\x{6C78}\x{6C79}\x{6C7A}' . + '\x{6C7B}\x{6C7C}\x{6C7D}\x{6C7E}\x{6C7F}\x{6C80}\x{6C81}\x{6C82}\x{6C83}' . + '\x{6C84}\x{6C85}\x{6C86}\x{6C87}\x{6C88}\x{6C89}\x{6C8A}\x{6C8B}\x{6C8C}' . + '\x{6C8D}\x{6C8E}\x{6C8F}\x{6C90}\x{6C91}\x{6C92}\x{6C93}\x{6C94}\x{6C95}' . + '\x{6C96}\x{6C97}\x{6C98}\x{6C99}\x{6C9A}\x{6C9B}\x{6C9C}\x{6C9D}\x{6C9E}' . + '\x{6C9F}\x{6CA1}\x{6CA2}\x{6CA3}\x{6CA4}\x{6CA5}\x{6CA6}\x{6CA7}\x{6CA8}' . + '\x{6CA9}\x{6CAA}\x{6CAB}\x{6CAC}\x{6CAD}\x{6CAE}\x{6CAF}\x{6CB0}\x{6CB1}' . + '\x{6CB2}\x{6CB3}\x{6CB4}\x{6CB5}\x{6CB6}\x{6CB7}\x{6CB8}\x{6CB9}\x{6CBA}' . + '\x{6CBB}\x{6CBC}\x{6CBD}\x{6CBE}\x{6CBF}\x{6CC0}\x{6CC1}\x{6CC2}\x{6CC3}' . + '\x{6CC4}\x{6CC5}\x{6CC6}\x{6CC7}\x{6CC8}\x{6CC9}\x{6CCA}\x{6CCB}\x{6CCC}' . + '\x{6CCD}\x{6CCE}\x{6CCF}\x{6CD0}\x{6CD1}\x{6CD2}\x{6CD3}\x{6CD4}\x{6CD5}' . + '\x{6CD6}\x{6CD7}\x{6CD9}\x{6CDA}\x{6CDB}\x{6CDC}\x{6CDD}\x{6CDE}\x{6CDF}' . + '\x{6CE0}\x{6CE1}\x{6CE2}\x{6CE3}\x{6CE4}\x{6CE5}\x{6CE6}\x{6CE7}\x{6CE8}' . + '\x{6CE9}\x{6CEA}\x{6CEB}\x{6CEC}\x{6CED}\x{6CEE}\x{6CEF}\x{6CF0}\x{6CF1}' . + '\x{6CF2}\x{6CF3}\x{6CF5}\x{6CF6}\x{6CF7}\x{6CF8}\x{6CF9}\x{6CFA}\x{6CFB}' . + '\x{6CFC}\x{6CFD}\x{6CFE}\x{6CFF}\x{6D00}\x{6D01}\x{6D03}\x{6D04}\x{6D05}' . + '\x{6D06}\x{6D07}\x{6D08}\x{6D09}\x{6D0A}\x{6D0B}\x{6D0C}\x{6D0D}\x{6D0E}' . + '\x{6D0F}\x{6D10}\x{6D11}\x{6D12}\x{6D13}\x{6D14}\x{6D15}\x{6D16}\x{6D17}' . + '\x{6D18}\x{6D19}\x{6D1A}\x{6D1B}\x{6D1D}\x{6D1E}\x{6D1F}\x{6D20}\x{6D21}' . + '\x{6D22}\x{6D23}\x{6D25}\x{6D26}\x{6D27}\x{6D28}\x{6D29}\x{6D2A}\x{6D2B}' . + '\x{6D2C}\x{6D2D}\x{6D2E}\x{6D2F}\x{6D30}\x{6D31}\x{6D32}\x{6D33}\x{6D34}' . + '\x{6D35}\x{6D36}\x{6D37}\x{6D38}\x{6D39}\x{6D3A}\x{6D3B}\x{6D3C}\x{6D3D}' . + '\x{6D3E}\x{6D3F}\x{6D40}\x{6D41}\x{6D42}\x{6D43}\x{6D44}\x{6D45}\x{6D46}' . + '\x{6D47}\x{6D48}\x{6D49}\x{6D4A}\x{6D4B}\x{6D4C}\x{6D4D}\x{6D4E}\x{6D4F}' . + '\x{6D50}\x{6D51}\x{6D52}\x{6D53}\x{6D54}\x{6D55}\x{6D56}\x{6D57}\x{6D58}' . + '\x{6D59}\x{6D5A}\x{6D5B}\x{6D5C}\x{6D5D}\x{6D5E}\x{6D5F}\x{6D60}\x{6D61}' . + '\x{6D62}\x{6D63}\x{6D64}\x{6D65}\x{6D66}\x{6D67}\x{6D68}\x{6D69}\x{6D6A}' . + '\x{6D6B}\x{6D6C}\x{6D6D}\x{6D6E}\x{6D6F}\x{6D70}\x{6D72}\x{6D73}\x{6D74}' . + '\x{6D75}\x{6D76}\x{6D77}\x{6D78}\x{6D79}\x{6D7A}\x{6D7B}\x{6D7C}\x{6D7D}' . + '\x{6D7E}\x{6D7F}\x{6D80}\x{6D82}\x{6D83}\x{6D84}\x{6D85}\x{6D86}\x{6D87}' . + '\x{6D88}\x{6D89}\x{6D8A}\x{6D8B}\x{6D8C}\x{6D8D}\x{6D8E}\x{6D8F}\x{6D90}' . + '\x{6D91}\x{6D92}\x{6D93}\x{6D94}\x{6D95}\x{6D97}\x{6D98}\x{6D99}\x{6D9A}' . + '\x{6D9B}\x{6D9D}\x{6D9E}\x{6D9F}\x{6DA0}\x{6DA1}\x{6DA2}\x{6DA3}\x{6DA4}' . + '\x{6DA5}\x{6DA6}\x{6DA7}\x{6DA8}\x{6DA9}\x{6DAA}\x{6DAB}\x{6DAC}\x{6DAD}' . + '\x{6DAE}\x{6DAF}\x{6DB2}\x{6DB3}\x{6DB4}\x{6DB5}\x{6DB7}\x{6DB8}\x{6DB9}' . + '\x{6DBA}\x{6DBB}\x{6DBC}\x{6DBD}\x{6DBE}\x{6DBF}\x{6DC0}\x{6DC1}\x{6DC2}' . + '\x{6DC3}\x{6DC4}\x{6DC5}\x{6DC6}\x{6DC7}\x{6DC8}\x{6DC9}\x{6DCA}\x{6DCB}' . + '\x{6DCC}\x{6DCD}\x{6DCE}\x{6DCF}\x{6DD0}\x{6DD1}\x{6DD2}\x{6DD3}\x{6DD4}' . + '\x{6DD5}\x{6DD6}\x{6DD7}\x{6DD8}\x{6DD9}\x{6DDA}\x{6DDB}\x{6DDC}\x{6DDD}' . + '\x{6DDE}\x{6DDF}\x{6DE0}\x{6DE1}\x{6DE2}\x{6DE3}\x{6DE4}\x{6DE5}\x{6DE6}' . + '\x{6DE7}\x{6DE8}\x{6DE9}\x{6DEA}\x{6DEB}\x{6DEC}\x{6DED}\x{6DEE}\x{6DEF}' . + '\x{6DF0}\x{6DF1}\x{6DF2}\x{6DF3}\x{6DF4}\x{6DF5}\x{6DF6}\x{6DF7}\x{6DF8}' . + '\x{6DF9}\x{6DFA}\x{6DFB}\x{6DFC}\x{6DFD}\x{6E00}\x{6E03}\x{6E04}\x{6E05}' . + '\x{6E07}\x{6E08}\x{6E09}\x{6E0A}\x{6E0B}\x{6E0C}\x{6E0D}\x{6E0E}\x{6E0F}' . + '\x{6E10}\x{6E11}\x{6E14}\x{6E15}\x{6E16}\x{6E17}\x{6E19}\x{6E1A}\x{6E1B}' . + '\x{6E1C}\x{6E1D}\x{6E1E}\x{6E1F}\x{6E20}\x{6E21}\x{6E22}\x{6E23}\x{6E24}' . + '\x{6E25}\x{6E26}\x{6E27}\x{6E28}\x{6E29}\x{6E2B}\x{6E2C}\x{6E2D}\x{6E2E}' . + '\x{6E2F}\x{6E30}\x{6E31}\x{6E32}\x{6E33}\x{6E34}\x{6E35}\x{6E36}\x{6E37}' . + '\x{6E38}\x{6E39}\x{6E3A}\x{6E3B}\x{6E3C}\x{6E3D}\x{6E3E}\x{6E3F}\x{6E40}' . + '\x{6E41}\x{6E42}\x{6E43}\x{6E44}\x{6E45}\x{6E46}\x{6E47}\x{6E48}\x{6E49}' . + '\x{6E4A}\x{6E4B}\x{6E4D}\x{6E4E}\x{6E4F}\x{6E50}\x{6E51}\x{6E52}\x{6E53}' . + '\x{6E54}\x{6E55}\x{6E56}\x{6E57}\x{6E58}\x{6E59}\x{6E5A}\x{6E5B}\x{6E5C}' . + '\x{6E5D}\x{6E5E}\x{6E5F}\x{6E60}\x{6E61}\x{6E62}\x{6E63}\x{6E64}\x{6E65}' . + '\x{6E66}\x{6E67}\x{6E68}\x{6E69}\x{6E6A}\x{6E6B}\x{6E6D}\x{6E6E}\x{6E6F}' . + '\x{6E70}\x{6E71}\x{6E72}\x{6E73}\x{6E74}\x{6E75}\x{6E77}\x{6E78}\x{6E79}' . + '\x{6E7E}\x{6E7F}\x{6E80}\x{6E81}\x{6E82}\x{6E83}\x{6E84}\x{6E85}\x{6E86}' . + '\x{6E87}\x{6E88}\x{6E89}\x{6E8A}\x{6E8D}\x{6E8E}\x{6E8F}\x{6E90}\x{6E91}' . + '\x{6E92}\x{6E93}\x{6E94}\x{6E96}\x{6E97}\x{6E98}\x{6E99}\x{6E9A}\x{6E9B}' . + '\x{6E9C}\x{6E9D}\x{6E9E}\x{6E9F}\x{6EA0}\x{6EA1}\x{6EA2}\x{6EA3}\x{6EA4}' . + '\x{6EA5}\x{6EA6}\x{6EA7}\x{6EA8}\x{6EA9}\x{6EAA}\x{6EAB}\x{6EAC}\x{6EAD}' . + '\x{6EAE}\x{6EAF}\x{6EB0}\x{6EB1}\x{6EB2}\x{6EB3}\x{6EB4}\x{6EB5}\x{6EB6}' . + '\x{6EB7}\x{6EB8}\x{6EB9}\x{6EBA}\x{6EBB}\x{6EBC}\x{6EBD}\x{6EBE}\x{6EBF}' . + '\x{6EC0}\x{6EC1}\x{6EC2}\x{6EC3}\x{6EC4}\x{6EC5}\x{6EC6}\x{6EC7}\x{6EC8}' . + '\x{6EC9}\x{6ECA}\x{6ECB}\x{6ECC}\x{6ECD}\x{6ECE}\x{6ECF}\x{6ED0}\x{6ED1}' . + '\x{6ED2}\x{6ED3}\x{6ED4}\x{6ED5}\x{6ED6}\x{6ED7}\x{6ED8}\x{6ED9}\x{6EDA}' . + '\x{6EDC}\x{6EDE}\x{6EDF}\x{6EE0}\x{6EE1}\x{6EE2}\x{6EE4}\x{6EE5}\x{6EE6}' . + '\x{6EE7}\x{6EE8}\x{6EE9}\x{6EEA}\x{6EEB}\x{6EEC}\x{6EED}\x{6EEE}\x{6EEF}' . + '\x{6EF0}\x{6EF1}\x{6EF2}\x{6EF3}\x{6EF4}\x{6EF5}\x{6EF6}\x{6EF7}\x{6EF8}' . + '\x{6EF9}\x{6EFA}\x{6EFB}\x{6EFC}\x{6EFD}\x{6EFE}\x{6EFF}\x{6F00}\x{6F01}' . + '\x{6F02}\x{6F03}\x{6F05}\x{6F06}\x{6F07}\x{6F08}\x{6F09}\x{6F0A}\x{6F0C}' . + '\x{6F0D}\x{6F0E}\x{6F0F}\x{6F10}\x{6F11}\x{6F12}\x{6F13}\x{6F14}\x{6F15}' . + '\x{6F16}\x{6F17}\x{6F18}\x{6F19}\x{6F1A}\x{6F1B}\x{6F1C}\x{6F1D}\x{6F1E}' . + '\x{6F1F}\x{6F20}\x{6F21}\x{6F22}\x{6F23}\x{6F24}\x{6F25}\x{6F26}\x{6F27}' . + '\x{6F28}\x{6F29}\x{6F2A}\x{6F2B}\x{6F2C}\x{6F2D}\x{6F2E}\x{6F2F}\x{6F30}' . + '\x{6F31}\x{6F32}\x{6F33}\x{6F34}\x{6F35}\x{6F36}\x{6F37}\x{6F38}\x{6F39}' . + '\x{6F3A}\x{6F3B}\x{6F3C}\x{6F3D}\x{6F3E}\x{6F3F}\x{6F40}\x{6F41}\x{6F43}' . + '\x{6F44}\x{6F45}\x{6F46}\x{6F47}\x{6F49}\x{6F4B}\x{6F4C}\x{6F4D}\x{6F4E}' . + '\x{6F4F}\x{6F50}\x{6F51}\x{6F52}\x{6F53}\x{6F54}\x{6F55}\x{6F56}\x{6F57}' . + '\x{6F58}\x{6F59}\x{6F5A}\x{6F5B}\x{6F5C}\x{6F5D}\x{6F5E}\x{6F5F}\x{6F60}' . + '\x{6F61}\x{6F62}\x{6F63}\x{6F64}\x{6F65}\x{6F66}\x{6F67}\x{6F68}\x{6F69}' . + '\x{6F6A}\x{6F6B}\x{6F6C}\x{6F6D}\x{6F6E}\x{6F6F}\x{6F70}\x{6F71}\x{6F72}' . + '\x{6F73}\x{6F74}\x{6F75}\x{6F76}\x{6F77}\x{6F78}\x{6F7A}\x{6F7B}\x{6F7C}' . + '\x{6F7D}\x{6F7E}\x{6F7F}\x{6F80}\x{6F81}\x{6F82}\x{6F83}\x{6F84}\x{6F85}' . + '\x{6F86}\x{6F87}\x{6F88}\x{6F89}\x{6F8A}\x{6F8B}\x{6F8C}\x{6F8D}\x{6F8E}' . + '\x{6F8F}\x{6F90}\x{6F91}\x{6F92}\x{6F93}\x{6F94}\x{6F95}\x{6F96}\x{6F97}' . + '\x{6F99}\x{6F9B}\x{6F9C}\x{6F9D}\x{6F9E}\x{6FA0}\x{6FA1}\x{6FA2}\x{6FA3}' . + '\x{6FA4}\x{6FA5}\x{6FA6}\x{6FA7}\x{6FA8}\x{6FA9}\x{6FAA}\x{6FAB}\x{6FAC}' . + '\x{6FAD}\x{6FAE}\x{6FAF}\x{6FB0}\x{6FB1}\x{6FB2}\x{6FB3}\x{6FB4}\x{6FB5}' . + '\x{6FB6}\x{6FB8}\x{6FB9}\x{6FBA}\x{6FBB}\x{6FBC}\x{6FBD}\x{6FBE}\x{6FBF}' . + '\x{6FC0}\x{6FC1}\x{6FC2}\x{6FC3}\x{6FC4}\x{6FC6}\x{6FC7}\x{6FC8}\x{6FC9}' . + '\x{6FCA}\x{6FCB}\x{6FCC}\x{6FCD}\x{6FCE}\x{6FCF}\x{6FD1}\x{6FD2}\x{6FD4}' . + '\x{6FD5}\x{6FD6}\x{6FD7}\x{6FD8}\x{6FD9}\x{6FDA}\x{6FDB}\x{6FDC}\x{6FDD}' . + '\x{6FDE}\x{6FDF}\x{6FE0}\x{6FE1}\x{6FE2}\x{6FE3}\x{6FE4}\x{6FE5}\x{6FE6}' . + '\x{6FE7}\x{6FE8}\x{6FE9}\x{6FEA}\x{6FEB}\x{6FEC}\x{6FED}\x{6FEE}\x{6FEF}' . + '\x{6FF0}\x{6FF1}\x{6FF2}\x{6FF3}\x{6FF4}\x{6FF6}\x{6FF7}\x{6FF8}\x{6FF9}' . + '\x{6FFA}\x{6FFB}\x{6FFC}\x{6FFE}\x{6FFF}\x{7000}\x{7001}\x{7002}\x{7003}' . + '\x{7004}\x{7005}\x{7006}\x{7007}\x{7008}\x{7009}\x{700A}\x{700B}\x{700C}' . + '\x{700D}\x{700E}\x{700F}\x{7011}\x{7012}\x{7014}\x{7015}\x{7016}\x{7017}' . + '\x{7018}\x{7019}\x{701A}\x{701B}\x{701C}\x{701D}\x{701F}\x{7020}\x{7021}' . + '\x{7022}\x{7023}\x{7024}\x{7025}\x{7026}\x{7027}\x{7028}\x{7029}\x{702A}' . + '\x{702B}\x{702C}\x{702D}\x{702E}\x{702F}\x{7030}\x{7031}\x{7032}\x{7033}' . + '\x{7034}\x{7035}\x{7036}\x{7037}\x{7038}\x{7039}\x{703A}\x{703B}\x{703C}' . + '\x{703D}\x{703E}\x{703F}\x{7040}\x{7041}\x{7042}\x{7043}\x{7044}\x{7045}' . + '\x{7046}\x{7048}\x{7049}\x{704A}\x{704C}\x{704D}\x{704F}\x{7050}\x{7051}' . + '\x{7052}\x{7053}\x{7054}\x{7055}\x{7056}\x{7057}\x{7058}\x{7059}\x{705A}' . + '\x{705B}\x{705C}\x{705D}\x{705E}\x{705F}\x{7060}\x{7061}\x{7062}\x{7063}' . + '\x{7064}\x{7065}\x{7066}\x{7067}\x{7068}\x{7069}\x{706A}\x{706B}\x{706C}' . + '\x{706D}\x{706E}\x{706F}\x{7070}\x{7071}\x{7074}\x{7075}\x{7076}\x{7077}' . + '\x{7078}\x{7079}\x{707A}\x{707C}\x{707D}\x{707E}\x{707F}\x{7080}\x{7082}' . + '\x{7083}\x{7084}\x{7085}\x{7086}\x{7087}\x{7088}\x{7089}\x{708A}\x{708B}' . + '\x{708C}\x{708E}\x{708F}\x{7090}\x{7091}\x{7092}\x{7093}\x{7094}\x{7095}' . + '\x{7096}\x{7098}\x{7099}\x{709A}\x{709C}\x{709D}\x{709E}\x{709F}\x{70A0}' . + '\x{70A1}\x{70A2}\x{70A3}\x{70A4}\x{70A5}\x{70A6}\x{70A7}\x{70A8}\x{70A9}' . + '\x{70AB}\x{70AC}\x{70AD}\x{70AE}\x{70AF}\x{70B0}\x{70B1}\x{70B3}\x{70B4}' . + '\x{70B5}\x{70B7}\x{70B8}\x{70B9}\x{70BA}\x{70BB}\x{70BC}\x{70BD}\x{70BE}' . + '\x{70BF}\x{70C0}\x{70C1}\x{70C2}\x{70C3}\x{70C4}\x{70C5}\x{70C6}\x{70C7}' . + '\x{70C8}\x{70C9}\x{70CA}\x{70CB}\x{70CC}\x{70CD}\x{70CE}\x{70CF}\x{70D0}' . + '\x{70D1}\x{70D2}\x{70D3}\x{70D4}\x{70D6}\x{70D7}\x{70D8}\x{70D9}\x{70DA}' . + '\x{70DB}\x{70DC}\x{70DD}\x{70DE}\x{70DF}\x{70E0}\x{70E1}\x{70E2}\x{70E3}' . + '\x{70E4}\x{70E5}\x{70E6}\x{70E7}\x{70E8}\x{70E9}\x{70EA}\x{70EB}\x{70EC}' . + '\x{70ED}\x{70EE}\x{70EF}\x{70F0}\x{70F1}\x{70F2}\x{70F3}\x{70F4}\x{70F5}' . + '\x{70F6}\x{70F7}\x{70F8}\x{70F9}\x{70FA}\x{70FB}\x{70FC}\x{70FD}\x{70FF}' . + '\x{7100}\x{7101}\x{7102}\x{7103}\x{7104}\x{7105}\x{7106}\x{7107}\x{7109}' . + '\x{710A}\x{710B}\x{710C}\x{710D}\x{710E}\x{710F}\x{7110}\x{7111}\x{7112}' . + '\x{7113}\x{7115}\x{7116}\x{7117}\x{7118}\x{7119}\x{711A}\x{711B}\x{711C}' . + '\x{711D}\x{711E}\x{711F}\x{7120}\x{7121}\x{7122}\x{7123}\x{7125}\x{7126}' . + '\x{7127}\x{7128}\x{7129}\x{712A}\x{712B}\x{712C}\x{712D}\x{712E}\x{712F}' . + '\x{7130}\x{7131}\x{7132}\x{7135}\x{7136}\x{7137}\x{7138}\x{7139}\x{713A}' . + '\x{713B}\x{713D}\x{713E}\x{713F}\x{7140}\x{7141}\x{7142}\x{7143}\x{7144}' . + '\x{7145}\x{7146}\x{7147}\x{7148}\x{7149}\x{714A}\x{714B}\x{714C}\x{714D}' . + '\x{714E}\x{714F}\x{7150}\x{7151}\x{7152}\x{7153}\x{7154}\x{7156}\x{7158}' . + '\x{7159}\x{715A}\x{715B}\x{715C}\x{715D}\x{715E}\x{715F}\x{7160}\x{7161}' . + '\x{7162}\x{7163}\x{7164}\x{7165}\x{7166}\x{7167}\x{7168}\x{7169}\x{716A}' . + '\x{716C}\x{716E}\x{716F}\x{7170}\x{7171}\x{7172}\x{7173}\x{7174}\x{7175}' . + '\x{7176}\x{7177}\x{7178}\x{7179}\x{717A}\x{717B}\x{717C}\x{717D}\x{717E}' . + '\x{717F}\x{7180}\x{7181}\x{7182}\x{7183}\x{7184}\x{7185}\x{7186}\x{7187}' . + '\x{7188}\x{7189}\x{718A}\x{718B}\x{718C}\x{718E}\x{718F}\x{7190}\x{7191}' . + '\x{7192}\x{7193}\x{7194}\x{7195}\x{7197}\x{7198}\x{7199}\x{719A}\x{719B}' . + '\x{719C}\x{719D}\x{719E}\x{719F}\x{71A0}\x{71A1}\x{71A2}\x{71A3}\x{71A4}' . + '\x{71A5}\x{71A7}\x{71A8}\x{71A9}\x{71AA}\x{71AC}\x{71AD}\x{71AE}\x{71AF}' . + '\x{71B0}\x{71B1}\x{71B2}\x{71B3}\x{71B4}\x{71B5}\x{71B7}\x{71B8}\x{71B9}' . + '\x{71BA}\x{71BB}\x{71BC}\x{71BD}\x{71BE}\x{71BF}\x{71C0}\x{71C1}\x{71C2}' . + '\x{71C3}\x{71C4}\x{71C5}\x{71C6}\x{71C7}\x{71C8}\x{71C9}\x{71CA}\x{71CB}' . + '\x{71CD}\x{71CE}\x{71CF}\x{71D0}\x{71D1}\x{71D2}\x{71D4}\x{71D5}\x{71D6}' . + '\x{71D7}\x{71D8}\x{71D9}\x{71DA}\x{71DB}\x{71DC}\x{71DD}\x{71DE}\x{71DF}' . + '\x{71E0}\x{71E1}\x{71E2}\x{71E3}\x{71E4}\x{71E5}\x{71E6}\x{71E7}\x{71E8}' . + '\x{71E9}\x{71EA}\x{71EB}\x{71EC}\x{71ED}\x{71EE}\x{71EF}\x{71F0}\x{71F1}' . + '\x{71F2}\x{71F4}\x{71F5}\x{71F6}\x{71F7}\x{71F8}\x{71F9}\x{71FB}\x{71FC}' . + '\x{71FD}\x{71FE}\x{71FF}\x{7201}\x{7202}\x{7203}\x{7204}\x{7205}\x{7206}' . + '\x{7207}\x{7208}\x{7209}\x{720A}\x{720C}\x{720D}\x{720E}\x{720F}\x{7210}' . + '\x{7212}\x{7213}\x{7214}\x{7216}\x{7218}\x{7219}\x{721A}\x{721B}\x{721C}' . + '\x{721D}\x{721E}\x{721F}\x{7221}\x{7222}\x{7223}\x{7226}\x{7227}\x{7228}' . + '\x{7229}\x{722A}\x{722B}\x{722C}\x{722D}\x{722E}\x{7230}\x{7231}\x{7232}' . + '\x{7233}\x{7235}\x{7236}\x{7237}\x{7238}\x{7239}\x{723A}\x{723B}\x{723C}' . + '\x{723D}\x{723E}\x{723F}\x{7240}\x{7241}\x{7242}\x{7243}\x{7244}\x{7246}' . + '\x{7247}\x{7248}\x{7249}\x{724A}\x{724B}\x{724C}\x{724D}\x{724F}\x{7251}' . + '\x{7252}\x{7253}\x{7254}\x{7256}\x{7257}\x{7258}\x{7259}\x{725A}\x{725B}' . + '\x{725C}\x{725D}\x{725E}\x{725F}\x{7260}\x{7261}\x{7262}\x{7263}\x{7264}' . + '\x{7265}\x{7266}\x{7267}\x{7268}\x{7269}\x{726A}\x{726B}\x{726C}\x{726D}' . + '\x{726E}\x{726F}\x{7270}\x{7271}\x{7272}\x{7273}\x{7274}\x{7275}\x{7276}' . + '\x{7277}\x{7278}\x{7279}\x{727A}\x{727B}\x{727C}\x{727D}\x{727E}\x{727F}' . + '\x{7280}\x{7281}\x{7282}\x{7283}\x{7284}\x{7285}\x{7286}\x{7287}\x{7288}' . + '\x{7289}\x{728A}\x{728B}\x{728C}\x{728D}\x{728E}\x{728F}\x{7290}\x{7291}' . + '\x{7292}\x{7293}\x{7294}\x{7295}\x{7296}\x{7297}\x{7298}\x{7299}\x{729A}' . + '\x{729B}\x{729C}\x{729D}\x{729E}\x{729F}\x{72A1}\x{72A2}\x{72A3}\x{72A4}' . + '\x{72A5}\x{72A6}\x{72A7}\x{72A8}\x{72A9}\x{72AA}\x{72AC}\x{72AD}\x{72AE}' . + '\x{72AF}\x{72B0}\x{72B1}\x{72B2}\x{72B3}\x{72B4}\x{72B5}\x{72B6}\x{72B7}' . + '\x{72B8}\x{72B9}\x{72BA}\x{72BB}\x{72BC}\x{72BD}\x{72BF}\x{72C0}\x{72C1}' . + '\x{72C2}\x{72C3}\x{72C4}\x{72C5}\x{72C6}\x{72C7}\x{72C8}\x{72C9}\x{72CA}' . + '\x{72CB}\x{72CC}\x{72CD}\x{72CE}\x{72CF}\x{72D0}\x{72D1}\x{72D2}\x{72D3}' . + '\x{72D4}\x{72D5}\x{72D6}\x{72D7}\x{72D8}\x{72D9}\x{72DA}\x{72DB}\x{72DC}' . + '\x{72DD}\x{72DE}\x{72DF}\x{72E0}\x{72E1}\x{72E2}\x{72E3}\x{72E4}\x{72E5}' . + '\x{72E6}\x{72E7}\x{72E8}\x{72E9}\x{72EA}\x{72EB}\x{72EC}\x{72ED}\x{72EE}' . + '\x{72EF}\x{72F0}\x{72F1}\x{72F2}\x{72F3}\x{72F4}\x{72F5}\x{72F6}\x{72F7}' . + '\x{72F8}\x{72F9}\x{72FA}\x{72FB}\x{72FC}\x{72FD}\x{72FE}\x{72FF}\x{7300}' . + '\x{7301}\x{7303}\x{7304}\x{7305}\x{7306}\x{7307}\x{7308}\x{7309}\x{730A}' . + '\x{730B}\x{730C}\x{730D}\x{730E}\x{730F}\x{7311}\x{7312}\x{7313}\x{7314}' . + '\x{7315}\x{7316}\x{7317}\x{7318}\x{7319}\x{731A}\x{731B}\x{731C}\x{731D}' . + '\x{731E}\x{7320}\x{7321}\x{7322}\x{7323}\x{7324}\x{7325}\x{7326}\x{7327}' . + '\x{7329}\x{732A}\x{732B}\x{732C}\x{732D}\x{732E}\x{7330}\x{7331}\x{7332}' . + '\x{7333}\x{7334}\x{7335}\x{7336}\x{7337}\x{7338}\x{7339}\x{733A}\x{733B}' . + '\x{733C}\x{733D}\x{733E}\x{733F}\x{7340}\x{7341}\x{7342}\x{7343}\x{7344}' . + '\x{7345}\x{7346}\x{7347}\x{7348}\x{7349}\x{734A}\x{734B}\x{734C}\x{734D}' . + '\x{734E}\x{7350}\x{7351}\x{7352}\x{7354}\x{7355}\x{7356}\x{7357}\x{7358}' . + '\x{7359}\x{735A}\x{735B}\x{735C}\x{735D}\x{735E}\x{735F}\x{7360}\x{7361}' . + '\x{7362}\x{7364}\x{7365}\x{7366}\x{7367}\x{7368}\x{7369}\x{736A}\x{736B}' . + '\x{736C}\x{736D}\x{736E}\x{736F}\x{7370}\x{7371}\x{7372}\x{7373}\x{7374}' . + '\x{7375}\x{7376}\x{7377}\x{7378}\x{7379}\x{737A}\x{737B}\x{737C}\x{737D}' . + '\x{737E}\x{737F}\x{7380}\x{7381}\x{7382}\x{7383}\x{7384}\x{7385}\x{7386}' . + '\x{7387}\x{7388}\x{7389}\x{738A}\x{738B}\x{738C}\x{738D}\x{738E}\x{738F}' . + '\x{7390}\x{7391}\x{7392}\x{7393}\x{7394}\x{7395}\x{7396}\x{7397}\x{7398}' . + '\x{7399}\x{739A}\x{739B}\x{739D}\x{739E}\x{739F}\x{73A0}\x{73A1}\x{73A2}' . + '\x{73A3}\x{73A4}\x{73A5}\x{73A6}\x{73A7}\x{73A8}\x{73A9}\x{73AA}\x{73AB}' . + '\x{73AC}\x{73AD}\x{73AE}\x{73AF}\x{73B0}\x{73B1}\x{73B2}\x{73B3}\x{73B4}' . + '\x{73B5}\x{73B6}\x{73B7}\x{73B8}\x{73B9}\x{73BA}\x{73BB}\x{73BC}\x{73BD}' . + '\x{73BE}\x{73BF}\x{73C0}\x{73C2}\x{73C3}\x{73C4}\x{73C5}\x{73C6}\x{73C7}' . + '\x{73C8}\x{73C9}\x{73CA}\x{73CB}\x{73CC}\x{73CD}\x{73CE}\x{73CF}\x{73D0}' . + '\x{73D1}\x{73D2}\x{73D3}\x{73D4}\x{73D5}\x{73D6}\x{73D7}\x{73D8}\x{73D9}' . + '\x{73DA}\x{73DB}\x{73DC}\x{73DD}\x{73DE}\x{73DF}\x{73E0}\x{73E2}\x{73E3}' . + '\x{73E5}\x{73E6}\x{73E7}\x{73E8}\x{73E9}\x{73EA}\x{73EB}\x{73EC}\x{73ED}' . + '\x{73EE}\x{73EF}\x{73F0}\x{73F1}\x{73F2}\x{73F4}\x{73F5}\x{73F6}\x{73F7}' . + '\x{73F8}\x{73F9}\x{73FA}\x{73FC}\x{73FD}\x{73FE}\x{73FF}\x{7400}\x{7401}' . + '\x{7402}\x{7403}\x{7404}\x{7405}\x{7406}\x{7407}\x{7408}\x{7409}\x{740A}' . + '\x{740B}\x{740C}\x{740D}\x{740E}\x{740F}\x{7410}\x{7411}\x{7412}\x{7413}' . + '\x{7414}\x{7415}\x{7416}\x{7417}\x{7419}\x{741A}\x{741B}\x{741C}\x{741D}' . + '\x{741E}\x{741F}\x{7420}\x{7421}\x{7422}\x{7423}\x{7424}\x{7425}\x{7426}' . + '\x{7427}\x{7428}\x{7429}\x{742A}\x{742B}\x{742C}\x{742D}\x{742E}\x{742F}' . + '\x{7430}\x{7431}\x{7432}\x{7433}\x{7434}\x{7435}\x{7436}\x{7437}\x{7438}' . + '\x{743A}\x{743B}\x{743C}\x{743D}\x{743F}\x{7440}\x{7441}\x{7442}\x{7443}' . + '\x{7444}\x{7445}\x{7446}\x{7448}\x{744A}\x{744B}\x{744C}\x{744D}\x{744E}' . + '\x{744F}\x{7450}\x{7451}\x{7452}\x{7453}\x{7454}\x{7455}\x{7456}\x{7457}' . + '\x{7459}\x{745A}\x{745B}\x{745C}\x{745D}\x{745E}\x{745F}\x{7461}\x{7462}' . + '\x{7463}\x{7464}\x{7465}\x{7466}\x{7467}\x{7468}\x{7469}\x{746A}\x{746B}' . + '\x{746C}\x{746D}\x{746E}\x{746F}\x{7470}\x{7471}\x{7472}\x{7473}\x{7474}' . + '\x{7475}\x{7476}\x{7477}\x{7478}\x{7479}\x{747A}\x{747C}\x{747D}\x{747E}' . + '\x{747F}\x{7480}\x{7481}\x{7482}\x{7483}\x{7485}\x{7486}\x{7487}\x{7488}' . + '\x{7489}\x{748A}\x{748B}\x{748C}\x{748D}\x{748E}\x{748F}\x{7490}\x{7491}' . + '\x{7492}\x{7493}\x{7494}\x{7495}\x{7497}\x{7498}\x{7499}\x{749A}\x{749B}' . + '\x{749C}\x{749E}\x{749F}\x{74A0}\x{74A1}\x{74A3}\x{74A4}\x{74A5}\x{74A6}' . + '\x{74A7}\x{74A8}\x{74A9}\x{74AA}\x{74AB}\x{74AC}\x{74AD}\x{74AE}\x{74AF}' . + '\x{74B0}\x{74B1}\x{74B2}\x{74B3}\x{74B4}\x{74B5}\x{74B6}\x{74B7}\x{74B8}' . + '\x{74B9}\x{74BA}\x{74BB}\x{74BC}\x{74BD}\x{74BE}\x{74BF}\x{74C0}\x{74C1}' . + '\x{74C2}\x{74C3}\x{74C4}\x{74C5}\x{74C6}\x{74CA}\x{74CB}\x{74CD}\x{74CE}' . + '\x{74CF}\x{74D0}\x{74D1}\x{74D2}\x{74D3}\x{74D4}\x{74D5}\x{74D6}\x{74D7}' . + '\x{74D8}\x{74D9}\x{74DA}\x{74DB}\x{74DC}\x{74DD}\x{74DE}\x{74DF}\x{74E0}' . + '\x{74E1}\x{74E2}\x{74E3}\x{74E4}\x{74E5}\x{74E6}\x{74E7}\x{74E8}\x{74E9}' . + '\x{74EA}\x{74EC}\x{74ED}\x{74EE}\x{74EF}\x{74F0}\x{74F1}\x{74F2}\x{74F3}' . + '\x{74F4}\x{74F5}\x{74F6}\x{74F7}\x{74F8}\x{74F9}\x{74FA}\x{74FB}\x{74FC}' . + '\x{74FD}\x{74FE}\x{74FF}\x{7500}\x{7501}\x{7502}\x{7503}\x{7504}\x{7505}' . + '\x{7506}\x{7507}\x{7508}\x{7509}\x{750A}\x{750B}\x{750C}\x{750D}\x{750F}' . + '\x{7510}\x{7511}\x{7512}\x{7513}\x{7514}\x{7515}\x{7516}\x{7517}\x{7518}' . + '\x{7519}\x{751A}\x{751B}\x{751C}\x{751D}\x{751E}\x{751F}\x{7521}\x{7522}' . + '\x{7523}\x{7524}\x{7525}\x{7526}\x{7527}\x{7528}\x{7529}\x{752A}\x{752B}' . + '\x{752C}\x{752D}\x{752E}\x{752F}\x{7530}\x{7531}\x{7532}\x{7533}\x{7535}' . + '\x{7536}\x{7537}\x{7538}\x{7539}\x{753A}\x{753B}\x{753C}\x{753D}\x{753E}' . + '\x{753F}\x{7540}\x{7542}\x{7543}\x{7544}\x{7545}\x{7546}\x{7547}\x{7548}' . + '\x{7549}\x{754B}\x{754C}\x{754D}\x{754E}\x{754F}\x{7550}\x{7551}\x{7553}' . + '\x{7554}\x{7556}\x{7557}\x{7558}\x{7559}\x{755A}\x{755B}\x{755C}\x{755D}' . + '\x{755F}\x{7560}\x{7562}\x{7563}\x{7564}\x{7565}\x{7566}\x{7567}\x{7568}' . + '\x{7569}\x{756A}\x{756B}\x{756C}\x{756D}\x{756E}\x{756F}\x{7570}\x{7572}' . + '\x{7574}\x{7575}\x{7576}\x{7577}\x{7578}\x{7579}\x{757C}\x{757D}\x{757E}' . + '\x{757F}\x{7580}\x{7581}\x{7582}\x{7583}\x{7584}\x{7586}\x{7587}\x{7588}' . + '\x{7589}\x{758A}\x{758B}\x{758C}\x{758D}\x{758F}\x{7590}\x{7591}\x{7592}' . + '\x{7593}\x{7594}\x{7595}\x{7596}\x{7597}\x{7598}\x{7599}\x{759A}\x{759B}' . + '\x{759C}\x{759D}\x{759E}\x{759F}\x{75A0}\x{75A1}\x{75A2}\x{75A3}\x{75A4}' . + '\x{75A5}\x{75A6}\x{75A7}\x{75A8}\x{75AA}\x{75AB}\x{75AC}\x{75AD}\x{75AE}' . + '\x{75AF}\x{75B0}\x{75B1}\x{75B2}\x{75B3}\x{75B4}\x{75B5}\x{75B6}\x{75B8}' . + '\x{75B9}\x{75BA}\x{75BB}\x{75BC}\x{75BD}\x{75BE}\x{75BF}\x{75C0}\x{75C1}' . + '\x{75C2}\x{75C3}\x{75C4}\x{75C5}\x{75C6}\x{75C7}\x{75C8}\x{75C9}\x{75CA}' . + '\x{75CB}\x{75CC}\x{75CD}\x{75CE}\x{75CF}\x{75D0}\x{75D1}\x{75D2}\x{75D3}' . + '\x{75D4}\x{75D5}\x{75D6}\x{75D7}\x{75D8}\x{75D9}\x{75DA}\x{75DB}\x{75DD}' . + '\x{75DE}\x{75DF}\x{75E0}\x{75E1}\x{75E2}\x{75E3}\x{75E4}\x{75E5}\x{75E6}' . + '\x{75E7}\x{75E8}\x{75EA}\x{75EB}\x{75EC}\x{75ED}\x{75EF}\x{75F0}\x{75F1}' . + '\x{75F2}\x{75F3}\x{75F4}\x{75F5}\x{75F6}\x{75F7}\x{75F8}\x{75F9}\x{75FA}' . + '\x{75FB}\x{75FC}\x{75FD}\x{75FE}\x{75FF}\x{7600}\x{7601}\x{7602}\x{7603}' . + '\x{7604}\x{7605}\x{7606}\x{7607}\x{7608}\x{7609}\x{760A}\x{760B}\x{760C}' . + '\x{760D}\x{760E}\x{760F}\x{7610}\x{7611}\x{7612}\x{7613}\x{7614}\x{7615}' . + '\x{7616}\x{7617}\x{7618}\x{7619}\x{761A}\x{761B}\x{761C}\x{761D}\x{761E}' . + '\x{761F}\x{7620}\x{7621}\x{7622}\x{7623}\x{7624}\x{7625}\x{7626}\x{7627}' . + '\x{7628}\x{7629}\x{762A}\x{762B}\x{762D}\x{762E}\x{762F}\x{7630}\x{7631}' . + '\x{7632}\x{7633}\x{7634}\x{7635}\x{7636}\x{7637}\x{7638}\x{7639}\x{763A}' . + '\x{763B}\x{763C}\x{763D}\x{763E}\x{763F}\x{7640}\x{7641}\x{7642}\x{7643}' . + '\x{7646}\x{7647}\x{7648}\x{7649}\x{764A}\x{764B}\x{764C}\x{764D}\x{764F}' . + '\x{7650}\x{7652}\x{7653}\x{7654}\x{7656}\x{7657}\x{7658}\x{7659}\x{765A}' . + '\x{765B}\x{765C}\x{765D}\x{765E}\x{765F}\x{7660}\x{7661}\x{7662}\x{7663}' . + '\x{7664}\x{7665}\x{7666}\x{7667}\x{7668}\x{7669}\x{766A}\x{766B}\x{766C}' . + '\x{766D}\x{766E}\x{766F}\x{7670}\x{7671}\x{7672}\x{7674}\x{7675}\x{7676}' . + '\x{7677}\x{7678}\x{7679}\x{767B}\x{767C}\x{767D}\x{767E}\x{767F}\x{7680}' . + '\x{7681}\x{7682}\x{7683}\x{7684}\x{7685}\x{7686}\x{7687}\x{7688}\x{7689}' . + '\x{768A}\x{768B}\x{768C}\x{768E}\x{768F}\x{7690}\x{7691}\x{7692}\x{7693}' . + '\x{7694}\x{7695}\x{7696}\x{7697}\x{7698}\x{7699}\x{769A}\x{769B}\x{769C}' . + '\x{769D}\x{769E}\x{769F}\x{76A0}\x{76A3}\x{76A4}\x{76A6}\x{76A7}\x{76A9}' . + '\x{76AA}\x{76AB}\x{76AC}\x{76AD}\x{76AE}\x{76AF}\x{76B0}\x{76B1}\x{76B2}' . + '\x{76B4}\x{76B5}\x{76B7}\x{76B8}\x{76BA}\x{76BB}\x{76BC}\x{76BD}\x{76BE}' . + '\x{76BF}\x{76C0}\x{76C2}\x{76C3}\x{76C4}\x{76C5}\x{76C6}\x{76C7}\x{76C8}' . + '\x{76C9}\x{76CA}\x{76CD}\x{76CE}\x{76CF}\x{76D0}\x{76D1}\x{76D2}\x{76D3}' . + '\x{76D4}\x{76D5}\x{76D6}\x{76D7}\x{76D8}\x{76DA}\x{76DB}\x{76DC}\x{76DD}' . + '\x{76DE}\x{76DF}\x{76E0}\x{76E1}\x{76E2}\x{76E3}\x{76E4}\x{76E5}\x{76E6}' . + '\x{76E7}\x{76E8}\x{76E9}\x{76EA}\x{76EC}\x{76ED}\x{76EE}\x{76EF}\x{76F0}' . + '\x{76F1}\x{76F2}\x{76F3}\x{76F4}\x{76F5}\x{76F6}\x{76F7}\x{76F8}\x{76F9}' . + '\x{76FA}\x{76FB}\x{76FC}\x{76FD}\x{76FE}\x{76FF}\x{7701}\x{7703}\x{7704}' . + '\x{7705}\x{7706}\x{7707}\x{7708}\x{7709}\x{770A}\x{770B}\x{770C}\x{770D}' . + '\x{770F}\x{7710}\x{7711}\x{7712}\x{7713}\x{7714}\x{7715}\x{7716}\x{7717}' . + '\x{7718}\x{7719}\x{771A}\x{771B}\x{771C}\x{771D}\x{771E}\x{771F}\x{7720}' . + '\x{7722}\x{7723}\x{7725}\x{7726}\x{7727}\x{7728}\x{7729}\x{772A}\x{772C}' . + '\x{772D}\x{772E}\x{772F}\x{7730}\x{7731}\x{7732}\x{7733}\x{7734}\x{7735}' . + '\x{7736}\x{7737}\x{7738}\x{7739}\x{773A}\x{773B}\x{773C}\x{773D}\x{773E}' . + '\x{7740}\x{7741}\x{7743}\x{7744}\x{7745}\x{7746}\x{7747}\x{7748}\x{7749}' . + '\x{774A}\x{774B}\x{774C}\x{774D}\x{774E}\x{774F}\x{7750}\x{7751}\x{7752}' . + '\x{7753}\x{7754}\x{7755}\x{7756}\x{7757}\x{7758}\x{7759}\x{775A}\x{775B}' . + '\x{775C}\x{775D}\x{775E}\x{775F}\x{7760}\x{7761}\x{7762}\x{7763}\x{7765}' . + '\x{7766}\x{7767}\x{7768}\x{7769}\x{776A}\x{776B}\x{776C}\x{776D}\x{776E}' . + '\x{776F}\x{7770}\x{7771}\x{7772}\x{7773}\x{7774}\x{7775}\x{7776}\x{7777}' . + '\x{7778}\x{7779}\x{777A}\x{777B}\x{777C}\x{777D}\x{777E}\x{777F}\x{7780}' . + '\x{7781}\x{7782}\x{7783}\x{7784}\x{7785}\x{7786}\x{7787}\x{7788}\x{7789}' . + '\x{778A}\x{778B}\x{778C}\x{778D}\x{778E}\x{778F}\x{7790}\x{7791}\x{7792}' . + '\x{7793}\x{7794}\x{7795}\x{7797}\x{7798}\x{7799}\x{779A}\x{779B}\x{779C}' . + '\x{779D}\x{779E}\x{779F}\x{77A0}\x{77A1}\x{77A2}\x{77A3}\x{77A5}\x{77A6}' . + '\x{77A7}\x{77A8}\x{77A9}\x{77AA}\x{77AB}\x{77AC}\x{77AD}\x{77AE}\x{77AF}' . + '\x{77B0}\x{77B1}\x{77B2}\x{77B3}\x{77B4}\x{77B5}\x{77B6}\x{77B7}\x{77B8}' . + '\x{77B9}\x{77BA}\x{77BB}\x{77BC}\x{77BD}\x{77BF}\x{77C0}\x{77C2}\x{77C3}' . + '\x{77C4}\x{77C5}\x{77C6}\x{77C7}\x{77C8}\x{77C9}\x{77CA}\x{77CB}\x{77CC}' . + '\x{77CD}\x{77CE}\x{77CF}\x{77D0}\x{77D1}\x{77D3}\x{77D4}\x{77D5}\x{77D6}' . + '\x{77D7}\x{77D8}\x{77D9}\x{77DA}\x{77DB}\x{77DC}\x{77DE}\x{77DF}\x{77E0}' . + '\x{77E1}\x{77E2}\x{77E3}\x{77E5}\x{77E7}\x{77E8}\x{77E9}\x{77EA}\x{77EB}' . + '\x{77EC}\x{77ED}\x{77EE}\x{77EF}\x{77F0}\x{77F1}\x{77F2}\x{77F3}\x{77F6}' . + '\x{77F7}\x{77F8}\x{77F9}\x{77FA}\x{77FB}\x{77FC}\x{77FD}\x{77FE}\x{77FF}' . + '\x{7800}\x{7801}\x{7802}\x{7803}\x{7804}\x{7805}\x{7806}\x{7808}\x{7809}' . + '\x{780A}\x{780B}\x{780C}\x{780D}\x{780E}\x{780F}\x{7810}\x{7811}\x{7812}' . + '\x{7813}\x{7814}\x{7815}\x{7816}\x{7817}\x{7818}\x{7819}\x{781A}\x{781B}' . + '\x{781C}\x{781D}\x{781E}\x{781F}\x{7820}\x{7821}\x{7822}\x{7823}\x{7825}' . + '\x{7826}\x{7827}\x{7828}\x{7829}\x{782A}\x{782B}\x{782C}\x{782D}\x{782E}' . + '\x{782F}\x{7830}\x{7831}\x{7832}\x{7833}\x{7834}\x{7835}\x{7837}\x{7838}' . + '\x{7839}\x{783A}\x{783B}\x{783C}\x{783D}\x{783E}\x{7840}\x{7841}\x{7843}' . + '\x{7844}\x{7845}\x{7847}\x{7848}\x{7849}\x{784A}\x{784C}\x{784D}\x{784E}' . + '\x{7850}\x{7851}\x{7852}\x{7853}\x{7854}\x{7855}\x{7856}\x{7857}\x{7858}' . + '\x{7859}\x{785A}\x{785B}\x{785C}\x{785D}\x{785E}\x{785F}\x{7860}\x{7861}' . + '\x{7862}\x{7863}\x{7864}\x{7865}\x{7866}\x{7867}\x{7868}\x{7869}\x{786A}' . + '\x{786B}\x{786C}\x{786D}\x{786E}\x{786F}\x{7870}\x{7871}\x{7872}\x{7873}' . + '\x{7874}\x{7875}\x{7877}\x{7878}\x{7879}\x{787A}\x{787B}\x{787C}\x{787D}' . + '\x{787E}\x{787F}\x{7880}\x{7881}\x{7882}\x{7883}\x{7884}\x{7885}\x{7886}' . + '\x{7887}\x{7889}\x{788A}\x{788B}\x{788C}\x{788D}\x{788E}\x{788F}\x{7890}' . + '\x{7891}\x{7892}\x{7893}\x{7894}\x{7895}\x{7896}\x{7897}\x{7898}\x{7899}' . + '\x{789A}\x{789B}\x{789C}\x{789D}\x{789E}\x{789F}\x{78A0}\x{78A1}\x{78A2}' . + '\x{78A3}\x{78A4}\x{78A5}\x{78A6}\x{78A7}\x{78A8}\x{78A9}\x{78AA}\x{78AB}' . + '\x{78AC}\x{78AD}\x{78AE}\x{78AF}\x{78B0}\x{78B1}\x{78B2}\x{78B3}\x{78B4}' . + '\x{78B5}\x{78B6}\x{78B7}\x{78B8}\x{78B9}\x{78BA}\x{78BB}\x{78BC}\x{78BD}' . + '\x{78BE}\x{78BF}\x{78C0}\x{78C1}\x{78C3}\x{78C4}\x{78C5}\x{78C6}\x{78C8}' . + '\x{78C9}\x{78CA}\x{78CB}\x{78CC}\x{78CD}\x{78CE}\x{78CF}\x{78D0}\x{78D1}' . + '\x{78D3}\x{78D4}\x{78D5}\x{78D6}\x{78D7}\x{78D8}\x{78D9}\x{78DA}\x{78DB}' . + '\x{78DC}\x{78DD}\x{78DE}\x{78DF}\x{78E0}\x{78E1}\x{78E2}\x{78E3}\x{78E4}' . + '\x{78E5}\x{78E6}\x{78E7}\x{78E8}\x{78E9}\x{78EA}\x{78EB}\x{78EC}\x{78ED}' . + '\x{78EE}\x{78EF}\x{78F1}\x{78F2}\x{78F3}\x{78F4}\x{78F5}\x{78F6}\x{78F7}' . + '\x{78F9}\x{78FA}\x{78FB}\x{78FC}\x{78FD}\x{78FE}\x{78FF}\x{7901}\x{7902}' . + '\x{7903}\x{7904}\x{7905}\x{7906}\x{7907}\x{7909}\x{790A}\x{790B}\x{790C}' . + '\x{790E}\x{790F}\x{7910}\x{7911}\x{7912}\x{7913}\x{7914}\x{7916}\x{7917}' . + '\x{7918}\x{7919}\x{791A}\x{791B}\x{791C}\x{791D}\x{791E}\x{7921}\x{7922}' . + '\x{7923}\x{7924}\x{7925}\x{7926}\x{7927}\x{7928}\x{7929}\x{792A}\x{792B}' . + '\x{792C}\x{792D}\x{792E}\x{792F}\x{7930}\x{7931}\x{7933}\x{7934}\x{7935}' . + '\x{7937}\x{7938}\x{7939}\x{793A}\x{793B}\x{793C}\x{793D}\x{793E}\x{793F}' . + '\x{7940}\x{7941}\x{7942}\x{7943}\x{7944}\x{7945}\x{7946}\x{7947}\x{7948}' . + '\x{7949}\x{794A}\x{794B}\x{794C}\x{794D}\x{794E}\x{794F}\x{7950}\x{7951}' . + '\x{7952}\x{7953}\x{7954}\x{7955}\x{7956}\x{7957}\x{7958}\x{795A}\x{795B}' . + '\x{795C}\x{795D}\x{795E}\x{795F}\x{7960}\x{7961}\x{7962}\x{7963}\x{7964}' . + '\x{7965}\x{7966}\x{7967}\x{7968}\x{7969}\x{796A}\x{796B}\x{796D}\x{796F}' . + '\x{7970}\x{7971}\x{7972}\x{7973}\x{7974}\x{7977}\x{7978}\x{7979}\x{797A}' . + '\x{797B}\x{797C}\x{797D}\x{797E}\x{797F}\x{7980}\x{7981}\x{7982}\x{7983}' . + '\x{7984}\x{7985}\x{7988}\x{7989}\x{798A}\x{798B}\x{798C}\x{798D}\x{798E}' . + '\x{798F}\x{7990}\x{7991}\x{7992}\x{7993}\x{7994}\x{7995}\x{7996}\x{7997}' . + '\x{7998}\x{7999}\x{799A}\x{799B}\x{799C}\x{799F}\x{79A0}\x{79A1}\x{79A2}' . + '\x{79A3}\x{79A4}\x{79A5}\x{79A6}\x{79A7}\x{79A8}\x{79AA}\x{79AB}\x{79AC}' . + '\x{79AD}\x{79AE}\x{79AF}\x{79B0}\x{79B1}\x{79B2}\x{79B3}\x{79B4}\x{79B5}' . + '\x{79B6}\x{79B7}\x{79B8}\x{79B9}\x{79BA}\x{79BB}\x{79BD}\x{79BE}\x{79BF}' . + '\x{79C0}\x{79C1}\x{79C2}\x{79C3}\x{79C5}\x{79C6}\x{79C8}\x{79C9}\x{79CA}' . + '\x{79CB}\x{79CD}\x{79CE}\x{79CF}\x{79D0}\x{79D1}\x{79D2}\x{79D3}\x{79D5}' . + '\x{79D6}\x{79D8}\x{79D9}\x{79DA}\x{79DB}\x{79DC}\x{79DD}\x{79DE}\x{79DF}' . + '\x{79E0}\x{79E1}\x{79E2}\x{79E3}\x{79E4}\x{79E5}\x{79E6}\x{79E7}\x{79E8}' . + '\x{79E9}\x{79EA}\x{79EB}\x{79EC}\x{79ED}\x{79EE}\x{79EF}\x{79F0}\x{79F1}' . + '\x{79F2}\x{79F3}\x{79F4}\x{79F5}\x{79F6}\x{79F7}\x{79F8}\x{79F9}\x{79FA}' . + '\x{79FB}\x{79FC}\x{79FD}\x{79FE}\x{79FF}\x{7A00}\x{7A02}\x{7A03}\x{7A04}' . + '\x{7A05}\x{7A06}\x{7A08}\x{7A0A}\x{7A0B}\x{7A0C}\x{7A0D}\x{7A0E}\x{7A0F}' . + '\x{7A10}\x{7A11}\x{7A12}\x{7A13}\x{7A14}\x{7A15}\x{7A16}\x{7A17}\x{7A18}' . + '\x{7A19}\x{7A1A}\x{7A1B}\x{7A1C}\x{7A1D}\x{7A1E}\x{7A1F}\x{7A20}\x{7A21}' . + '\x{7A22}\x{7A23}\x{7A24}\x{7A25}\x{7A26}\x{7A27}\x{7A28}\x{7A29}\x{7A2A}' . + '\x{7A2B}\x{7A2D}\x{7A2E}\x{7A2F}\x{7A30}\x{7A31}\x{7A32}\x{7A33}\x{7A34}' . + '\x{7A35}\x{7A37}\x{7A39}\x{7A3B}\x{7A3C}\x{7A3D}\x{7A3E}\x{7A3F}\x{7A40}' . + '\x{7A41}\x{7A42}\x{7A43}\x{7A44}\x{7A45}\x{7A46}\x{7A47}\x{7A48}\x{7A49}' . + '\x{7A4A}\x{7A4B}\x{7A4C}\x{7A4D}\x{7A4E}\x{7A50}\x{7A51}\x{7A52}\x{7A53}' . + '\x{7A54}\x{7A55}\x{7A56}\x{7A57}\x{7A58}\x{7A59}\x{7A5A}\x{7A5B}\x{7A5C}' . + '\x{7A5D}\x{7A5E}\x{7A5F}\x{7A60}\x{7A61}\x{7A62}\x{7A65}\x{7A66}\x{7A67}' . + '\x{7A68}\x{7A69}\x{7A6B}\x{7A6C}\x{7A6D}\x{7A6E}\x{7A70}\x{7A71}\x{7A72}' . + '\x{7A73}\x{7A74}\x{7A75}\x{7A76}\x{7A77}\x{7A78}\x{7A79}\x{7A7A}\x{7A7B}' . + '\x{7A7C}\x{7A7D}\x{7A7E}\x{7A7F}\x{7A80}\x{7A81}\x{7A83}\x{7A84}\x{7A85}' . + '\x{7A86}\x{7A87}\x{7A88}\x{7A89}\x{7A8A}\x{7A8B}\x{7A8C}\x{7A8D}\x{7A8E}' . + '\x{7A8F}\x{7A90}\x{7A91}\x{7A92}\x{7A93}\x{7A94}\x{7A95}\x{7A96}\x{7A97}' . + '\x{7A98}\x{7A99}\x{7A9C}\x{7A9D}\x{7A9E}\x{7A9F}\x{7AA0}\x{7AA1}\x{7AA2}' . + '\x{7AA3}\x{7AA4}\x{7AA5}\x{7AA6}\x{7AA7}\x{7AA8}\x{7AA9}\x{7AAA}\x{7AAB}' . + '\x{7AAC}\x{7AAD}\x{7AAE}\x{7AAF}\x{7AB0}\x{7AB1}\x{7AB2}\x{7AB3}\x{7AB4}' . + '\x{7AB5}\x{7AB6}\x{7AB7}\x{7AB8}\x{7ABA}\x{7ABE}\x{7ABF}\x{7AC0}\x{7AC1}' . + '\x{7AC4}\x{7AC5}\x{7AC7}\x{7AC8}\x{7AC9}\x{7ACA}\x{7ACB}\x{7ACC}\x{7ACD}' . + '\x{7ACE}\x{7ACF}\x{7AD0}\x{7AD1}\x{7AD2}\x{7AD3}\x{7AD4}\x{7AD5}\x{7AD6}' . + '\x{7AD8}\x{7AD9}\x{7ADB}\x{7ADC}\x{7ADD}\x{7ADE}\x{7ADF}\x{7AE0}\x{7AE1}' . + '\x{7AE2}\x{7AE3}\x{7AE4}\x{7AE5}\x{7AE6}\x{7AE7}\x{7AE8}\x{7AEA}\x{7AEB}' . + '\x{7AEC}\x{7AED}\x{7AEE}\x{7AEF}\x{7AF0}\x{7AF1}\x{7AF2}\x{7AF3}\x{7AF4}' . + '\x{7AF6}\x{7AF7}\x{7AF8}\x{7AF9}\x{7AFA}\x{7AFB}\x{7AFD}\x{7AFE}\x{7AFF}' . + '\x{7B00}\x{7B01}\x{7B02}\x{7B03}\x{7B04}\x{7B05}\x{7B06}\x{7B08}\x{7B09}' . + '\x{7B0A}\x{7B0B}\x{7B0C}\x{7B0D}\x{7B0E}\x{7B0F}\x{7B10}\x{7B11}\x{7B12}' . + '\x{7B13}\x{7B14}\x{7B15}\x{7B16}\x{7B17}\x{7B18}\x{7B19}\x{7B1A}\x{7B1B}' . + '\x{7B1C}\x{7B1D}\x{7B1E}\x{7B20}\x{7B21}\x{7B22}\x{7B23}\x{7B24}\x{7B25}' . + '\x{7B26}\x{7B28}\x{7B2A}\x{7B2B}\x{7B2C}\x{7B2D}\x{7B2E}\x{7B2F}\x{7B30}' . + '\x{7B31}\x{7B32}\x{7B33}\x{7B34}\x{7B35}\x{7B36}\x{7B37}\x{7B38}\x{7B39}' . + '\x{7B3A}\x{7B3B}\x{7B3C}\x{7B3D}\x{7B3E}\x{7B3F}\x{7B40}\x{7B41}\x{7B43}' . + '\x{7B44}\x{7B45}\x{7B46}\x{7B47}\x{7B48}\x{7B49}\x{7B4A}\x{7B4B}\x{7B4C}' . + '\x{7B4D}\x{7B4E}\x{7B4F}\x{7B50}\x{7B51}\x{7B52}\x{7B54}\x{7B55}\x{7B56}' . + '\x{7B57}\x{7B58}\x{7B59}\x{7B5A}\x{7B5B}\x{7B5C}\x{7B5D}\x{7B5E}\x{7B5F}' . + '\x{7B60}\x{7B61}\x{7B62}\x{7B63}\x{7B64}\x{7B65}\x{7B66}\x{7B67}\x{7B68}' . + '\x{7B69}\x{7B6A}\x{7B6B}\x{7B6C}\x{7B6D}\x{7B6E}\x{7B70}\x{7B71}\x{7B72}' . + '\x{7B73}\x{7B74}\x{7B75}\x{7B76}\x{7B77}\x{7B78}\x{7B79}\x{7B7B}\x{7B7C}' . + '\x{7B7D}\x{7B7E}\x{7B7F}\x{7B80}\x{7B81}\x{7B82}\x{7B83}\x{7B84}\x{7B85}' . + '\x{7B87}\x{7B88}\x{7B89}\x{7B8A}\x{7B8B}\x{7B8C}\x{7B8D}\x{7B8E}\x{7B8F}' . + '\x{7B90}\x{7B91}\x{7B93}\x{7B94}\x{7B95}\x{7B96}\x{7B97}\x{7B98}\x{7B99}' . + '\x{7B9A}\x{7B9B}\x{7B9C}\x{7B9D}\x{7B9E}\x{7B9F}\x{7BA0}\x{7BA1}\x{7BA2}' . + '\x{7BA4}\x{7BA6}\x{7BA7}\x{7BA8}\x{7BA9}\x{7BAA}\x{7BAB}\x{7BAC}\x{7BAD}' . + '\x{7BAE}\x{7BAF}\x{7BB1}\x{7BB3}\x{7BB4}\x{7BB5}\x{7BB6}\x{7BB7}\x{7BB8}' . + '\x{7BB9}\x{7BBA}\x{7BBB}\x{7BBC}\x{7BBD}\x{7BBE}\x{7BBF}\x{7BC0}\x{7BC1}' . + '\x{7BC2}\x{7BC3}\x{7BC4}\x{7BC5}\x{7BC6}\x{7BC7}\x{7BC8}\x{7BC9}\x{7BCA}' . + '\x{7BCB}\x{7BCC}\x{7BCD}\x{7BCE}\x{7BD0}\x{7BD1}\x{7BD2}\x{7BD3}\x{7BD4}' . + '\x{7BD5}\x{7BD6}\x{7BD7}\x{7BD8}\x{7BD9}\x{7BDA}\x{7BDB}\x{7BDC}\x{7BDD}' . + '\x{7BDE}\x{7BDF}\x{7BE0}\x{7BE1}\x{7BE2}\x{7BE3}\x{7BE4}\x{7BE5}\x{7BE6}' . + '\x{7BE7}\x{7BE8}\x{7BE9}\x{7BEA}\x{7BEB}\x{7BEC}\x{7BED}\x{7BEE}\x{7BEF}' . + '\x{7BF0}\x{7BF1}\x{7BF2}\x{7BF3}\x{7BF4}\x{7BF5}\x{7BF6}\x{7BF7}\x{7BF8}' . + '\x{7BF9}\x{7BFB}\x{7BFC}\x{7BFD}\x{7BFE}\x{7BFF}\x{7C00}\x{7C01}\x{7C02}' . + '\x{7C03}\x{7C04}\x{7C05}\x{7C06}\x{7C07}\x{7C08}\x{7C09}\x{7C0A}\x{7C0B}' . + '\x{7C0C}\x{7C0D}\x{7C0E}\x{7C0F}\x{7C10}\x{7C11}\x{7C12}\x{7C13}\x{7C15}' . + '\x{7C16}\x{7C17}\x{7C18}\x{7C19}\x{7C1A}\x{7C1C}\x{7C1D}\x{7C1E}\x{7C1F}' . + '\x{7C20}\x{7C21}\x{7C22}\x{7C23}\x{7C24}\x{7C25}\x{7C26}\x{7C27}\x{7C28}' . + '\x{7C29}\x{7C2A}\x{7C2B}\x{7C2C}\x{7C2D}\x{7C30}\x{7C31}\x{7C32}\x{7C33}' . + '\x{7C34}\x{7C35}\x{7C36}\x{7C37}\x{7C38}\x{7C39}\x{7C3A}\x{7C3B}\x{7C3C}' . + '\x{7C3D}\x{7C3E}\x{7C3F}\x{7C40}\x{7C41}\x{7C42}\x{7C43}\x{7C44}\x{7C45}' . + '\x{7C46}\x{7C47}\x{7C48}\x{7C49}\x{7C4A}\x{7C4B}\x{7C4C}\x{7C4D}\x{7C4E}' . + '\x{7C50}\x{7C51}\x{7C53}\x{7C54}\x{7C56}\x{7C57}\x{7C58}\x{7C59}\x{7C5A}' . + '\x{7C5B}\x{7C5C}\x{7C5E}\x{7C5F}\x{7C60}\x{7C61}\x{7C62}\x{7C63}\x{7C64}' . + '\x{7C65}\x{7C66}\x{7C67}\x{7C68}\x{7C69}\x{7C6A}\x{7C6B}\x{7C6C}\x{7C6D}' . + '\x{7C6E}\x{7C6F}\x{7C70}\x{7C71}\x{7C72}\x{7C73}\x{7C74}\x{7C75}\x{7C77}' . + '\x{7C78}\x{7C79}\x{7C7A}\x{7C7B}\x{7C7C}\x{7C7D}\x{7C7E}\x{7C7F}\x{7C80}' . + '\x{7C81}\x{7C82}\x{7C84}\x{7C85}\x{7C86}\x{7C88}\x{7C89}\x{7C8A}\x{7C8B}' . + '\x{7C8C}\x{7C8D}\x{7C8E}\x{7C8F}\x{7C90}\x{7C91}\x{7C92}\x{7C94}\x{7C95}' . + '\x{7C96}\x{7C97}\x{7C98}\x{7C99}\x{7C9B}\x{7C9C}\x{7C9D}\x{7C9E}\x{7C9F}' . + '\x{7CA0}\x{7CA1}\x{7CA2}\x{7CA3}\x{7CA4}\x{7CA5}\x{7CA6}\x{7CA7}\x{7CA8}' . + '\x{7CA9}\x{7CAA}\x{7CAD}\x{7CAE}\x{7CAF}\x{7CB0}\x{7CB1}\x{7CB2}\x{7CB3}' . + '\x{7CB4}\x{7CB5}\x{7CB6}\x{7CB7}\x{7CB8}\x{7CB9}\x{7CBA}\x{7CBB}\x{7CBC}' . + '\x{7CBD}\x{7CBE}\x{7CBF}\x{7CC0}\x{7CC1}\x{7CC2}\x{7CC3}\x{7CC4}\x{7CC5}' . + '\x{7CC6}\x{7CC7}\x{7CC8}\x{7CC9}\x{7CCA}\x{7CCB}\x{7CCC}\x{7CCD}\x{7CCE}' . + '\x{7CCF}\x{7CD0}\x{7CD1}\x{7CD2}\x{7CD4}\x{7CD5}\x{7CD6}\x{7CD7}\x{7CD8}' . + '\x{7CD9}\x{7CDC}\x{7CDD}\x{7CDE}\x{7CDF}\x{7CE0}\x{7CE2}\x{7CE4}\x{7CE7}' . + '\x{7CE8}\x{7CE9}\x{7CEA}\x{7CEB}\x{7CEC}\x{7CED}\x{7CEE}\x{7CEF}\x{7CF0}' . + '\x{7CF1}\x{7CF2}\x{7CF3}\x{7CF4}\x{7CF5}\x{7CF6}\x{7CF7}\x{7CF8}\x{7CF9}' . + '\x{7CFA}\x{7CFB}\x{7CFD}\x{7CFE}\x{7D00}\x{7D01}\x{7D02}\x{7D03}\x{7D04}' . + '\x{7D05}\x{7D06}\x{7D07}\x{7D08}\x{7D09}\x{7D0A}\x{7D0B}\x{7D0C}\x{7D0D}' . + '\x{7D0E}\x{7D0F}\x{7D10}\x{7D11}\x{7D12}\x{7D13}\x{7D14}\x{7D15}\x{7D16}' . + '\x{7D17}\x{7D18}\x{7D19}\x{7D1A}\x{7D1B}\x{7D1C}\x{7D1D}\x{7D1E}\x{7D1F}' . + '\x{7D20}\x{7D21}\x{7D22}\x{7D24}\x{7D25}\x{7D26}\x{7D27}\x{7D28}\x{7D29}' . + '\x{7D2B}\x{7D2C}\x{7D2E}\x{7D2F}\x{7D30}\x{7D31}\x{7D32}\x{7D33}\x{7D34}' . + '\x{7D35}\x{7D36}\x{7D37}\x{7D38}\x{7D39}\x{7D3A}\x{7D3B}\x{7D3C}\x{7D3D}' . + '\x{7D3E}\x{7D3F}\x{7D40}\x{7D41}\x{7D42}\x{7D43}\x{7D44}\x{7D45}\x{7D46}' . + '\x{7D47}\x{7D49}\x{7D4A}\x{7D4B}\x{7D4C}\x{7D4E}\x{7D4F}\x{7D50}\x{7D51}' . + '\x{7D52}\x{7D53}\x{7D54}\x{7D55}\x{7D56}\x{7D57}\x{7D58}\x{7D59}\x{7D5B}' . + '\x{7D5C}\x{7D5D}\x{7D5E}\x{7D5F}\x{7D60}\x{7D61}\x{7D62}\x{7D63}\x{7D65}' . + '\x{7D66}\x{7D67}\x{7D68}\x{7D69}\x{7D6A}\x{7D6B}\x{7D6C}\x{7D6D}\x{7D6E}' . + '\x{7D6F}\x{7D70}\x{7D71}\x{7D72}\x{7D73}\x{7D74}\x{7D75}\x{7D76}\x{7D77}' . + '\x{7D79}\x{7D7A}\x{7D7B}\x{7D7C}\x{7D7D}\x{7D7E}\x{7D7F}\x{7D80}\x{7D81}' . + '\x{7D83}\x{7D84}\x{7D85}\x{7D86}\x{7D87}\x{7D88}\x{7D89}\x{7D8A}\x{7D8B}' . + '\x{7D8C}\x{7D8D}\x{7D8E}\x{7D8F}\x{7D90}\x{7D91}\x{7D92}\x{7D93}\x{7D94}' . + '\x{7D96}\x{7D97}\x{7D99}\x{7D9B}\x{7D9C}\x{7D9D}\x{7D9E}\x{7D9F}\x{7DA0}' . + '\x{7DA1}\x{7DA2}\x{7DA3}\x{7DA5}\x{7DA6}\x{7DA7}\x{7DA9}\x{7DAA}\x{7DAB}' . + '\x{7DAC}\x{7DAD}\x{7DAE}\x{7DAF}\x{7DB0}\x{7DB1}\x{7DB2}\x{7DB3}\x{7DB4}' . + '\x{7DB5}\x{7DB6}\x{7DB7}\x{7DB8}\x{7DB9}\x{7DBA}\x{7DBB}\x{7DBC}\x{7DBD}' . + '\x{7DBE}\x{7DBF}\x{7DC0}\x{7DC1}\x{7DC2}\x{7DC3}\x{7DC4}\x{7DC5}\x{7DC6}' . + '\x{7DC7}\x{7DC8}\x{7DC9}\x{7DCA}\x{7DCB}\x{7DCC}\x{7DCE}\x{7DCF}\x{7DD0}' . + '\x{7DD1}\x{7DD2}\x{7DD4}\x{7DD5}\x{7DD6}\x{7DD7}\x{7DD8}\x{7DD9}\x{7DDA}' . + '\x{7DDB}\x{7DDD}\x{7DDE}\x{7DDF}\x{7DE0}\x{7DE1}\x{7DE2}\x{7DE3}\x{7DE6}' . + '\x{7DE7}\x{7DE8}\x{7DE9}\x{7DEA}\x{7DEC}\x{7DED}\x{7DEE}\x{7DEF}\x{7DF0}' . + '\x{7DF1}\x{7DF2}\x{7DF3}\x{7DF4}\x{7DF5}\x{7DF6}\x{7DF7}\x{7DF8}\x{7DF9}' . + '\x{7DFA}\x{7DFB}\x{7DFC}\x{7E00}\x{7E01}\x{7E02}\x{7E03}\x{7E04}\x{7E05}' . + '\x{7E06}\x{7E07}\x{7E08}\x{7E09}\x{7E0A}\x{7E0B}\x{7E0C}\x{7E0D}\x{7E0E}' . + '\x{7E0F}\x{7E10}\x{7E11}\x{7E12}\x{7E13}\x{7E14}\x{7E15}\x{7E16}\x{7E17}' . + '\x{7E19}\x{7E1A}\x{7E1B}\x{7E1C}\x{7E1D}\x{7E1E}\x{7E1F}\x{7E20}\x{7E21}' . + '\x{7E22}\x{7E23}\x{7E24}\x{7E25}\x{7E26}\x{7E27}\x{7E28}\x{7E29}\x{7E2A}' . + '\x{7E2B}\x{7E2C}\x{7E2D}\x{7E2E}\x{7E2F}\x{7E30}\x{7E31}\x{7E32}\x{7E33}' . + '\x{7E34}\x{7E35}\x{7E36}\x{7E37}\x{7E38}\x{7E39}\x{7E3A}\x{7E3B}\x{7E3C}' . + '\x{7E3D}\x{7E3E}\x{7E3F}\x{7E40}\x{7E41}\x{7E42}\x{7E43}\x{7E44}\x{7E45}' . + '\x{7E46}\x{7E47}\x{7E48}\x{7E49}\x{7E4C}\x{7E4D}\x{7E4E}\x{7E4F}\x{7E50}' . + '\x{7E51}\x{7E52}\x{7E53}\x{7E54}\x{7E55}\x{7E56}\x{7E57}\x{7E58}\x{7E59}' . + '\x{7E5A}\x{7E5C}\x{7E5D}\x{7E5E}\x{7E5F}\x{7E60}\x{7E61}\x{7E62}\x{7E63}' . + '\x{7E65}\x{7E66}\x{7E67}\x{7E68}\x{7E69}\x{7E6A}\x{7E6B}\x{7E6C}\x{7E6D}' . + '\x{7E6E}\x{7E6F}\x{7E70}\x{7E71}\x{7E72}\x{7E73}\x{7E74}\x{7E75}\x{7E76}' . + '\x{7E77}\x{7E78}\x{7E79}\x{7E7A}\x{7E7B}\x{7E7C}\x{7E7D}\x{7E7E}\x{7E7F}' . + '\x{7E80}\x{7E81}\x{7E82}\x{7E83}\x{7E84}\x{7E85}\x{7E86}\x{7E87}\x{7E88}' . + '\x{7E89}\x{7E8A}\x{7E8B}\x{7E8C}\x{7E8D}\x{7E8E}\x{7E8F}\x{7E90}\x{7E91}' . + '\x{7E92}\x{7E93}\x{7E94}\x{7E95}\x{7E96}\x{7E97}\x{7E98}\x{7E99}\x{7E9A}' . + '\x{7E9B}\x{7E9C}\x{7E9E}\x{7E9F}\x{7EA0}\x{7EA1}\x{7EA2}\x{7EA3}\x{7EA4}' . + '\x{7EA5}\x{7EA6}\x{7EA7}\x{7EA8}\x{7EA9}\x{7EAA}\x{7EAB}\x{7EAC}\x{7EAD}' . + '\x{7EAE}\x{7EAF}\x{7EB0}\x{7EB1}\x{7EB2}\x{7EB3}\x{7EB4}\x{7EB5}\x{7EB6}' . + '\x{7EB7}\x{7EB8}\x{7EB9}\x{7EBA}\x{7EBB}\x{7EBC}\x{7EBD}\x{7EBE}\x{7EBF}' . + '\x{7EC0}\x{7EC1}\x{7EC2}\x{7EC3}\x{7EC4}\x{7EC5}\x{7EC6}\x{7EC7}\x{7EC8}' . + '\x{7EC9}\x{7ECA}\x{7ECB}\x{7ECC}\x{7ECD}\x{7ECE}\x{7ECF}\x{7ED0}\x{7ED1}' . + '\x{7ED2}\x{7ED3}\x{7ED4}\x{7ED5}\x{7ED6}\x{7ED7}\x{7ED8}\x{7ED9}\x{7EDA}' . + '\x{7EDB}\x{7EDC}\x{7EDD}\x{7EDE}\x{7EDF}\x{7EE0}\x{7EE1}\x{7EE2}\x{7EE3}' . + '\x{7EE4}\x{7EE5}\x{7EE6}\x{7EE7}\x{7EE8}\x{7EE9}\x{7EEA}\x{7EEB}\x{7EEC}' . + '\x{7EED}\x{7EEE}\x{7EEF}\x{7EF0}\x{7EF1}\x{7EF2}\x{7EF3}\x{7EF4}\x{7EF5}' . + '\x{7EF6}\x{7EF7}\x{7EF8}\x{7EF9}\x{7EFA}\x{7EFB}\x{7EFC}\x{7EFD}\x{7EFE}' . + '\x{7EFF}\x{7F00}\x{7F01}\x{7F02}\x{7F03}\x{7F04}\x{7F05}\x{7F06}\x{7F07}' . + '\x{7F08}\x{7F09}\x{7F0A}\x{7F0B}\x{7F0C}\x{7F0D}\x{7F0E}\x{7F0F}\x{7F10}' . + '\x{7F11}\x{7F12}\x{7F13}\x{7F14}\x{7F15}\x{7F16}\x{7F17}\x{7F18}\x{7F19}' . + '\x{7F1A}\x{7F1B}\x{7F1C}\x{7F1D}\x{7F1E}\x{7F1F}\x{7F20}\x{7F21}\x{7F22}' . + '\x{7F23}\x{7F24}\x{7F25}\x{7F26}\x{7F27}\x{7F28}\x{7F29}\x{7F2A}\x{7F2B}' . + '\x{7F2C}\x{7F2D}\x{7F2E}\x{7F2F}\x{7F30}\x{7F31}\x{7F32}\x{7F33}\x{7F34}' . + '\x{7F35}\x{7F36}\x{7F37}\x{7F38}\x{7F39}\x{7F3A}\x{7F3D}\x{7F3E}\x{7F3F}' . + '\x{7F40}\x{7F42}\x{7F43}\x{7F44}\x{7F45}\x{7F47}\x{7F48}\x{7F49}\x{7F4A}' . + '\x{7F4B}\x{7F4C}\x{7F4D}\x{7F4E}\x{7F4F}\x{7F50}\x{7F51}\x{7F52}\x{7F53}' . + '\x{7F54}\x{7F55}\x{7F56}\x{7F57}\x{7F58}\x{7F5A}\x{7F5B}\x{7F5C}\x{7F5D}' . + '\x{7F5E}\x{7F5F}\x{7F60}\x{7F61}\x{7F62}\x{7F63}\x{7F64}\x{7F65}\x{7F66}' . + '\x{7F67}\x{7F68}\x{7F69}\x{7F6A}\x{7F6B}\x{7F6C}\x{7F6D}\x{7F6E}\x{7F6F}' . + '\x{7F70}\x{7F71}\x{7F72}\x{7F73}\x{7F74}\x{7F75}\x{7F76}\x{7F77}\x{7F78}' . + '\x{7F79}\x{7F7A}\x{7F7B}\x{7F7C}\x{7F7D}\x{7F7E}\x{7F7F}\x{7F80}\x{7F81}' . + '\x{7F82}\x{7F83}\x{7F85}\x{7F86}\x{7F87}\x{7F88}\x{7F89}\x{7F8A}\x{7F8B}' . + '\x{7F8C}\x{7F8D}\x{7F8E}\x{7F8F}\x{7F91}\x{7F92}\x{7F93}\x{7F94}\x{7F95}' . + '\x{7F96}\x{7F98}\x{7F9A}\x{7F9B}\x{7F9C}\x{7F9D}\x{7F9E}\x{7F9F}\x{7FA0}' . + '\x{7FA1}\x{7FA2}\x{7FA3}\x{7FA4}\x{7FA5}\x{7FA6}\x{7FA7}\x{7FA8}\x{7FA9}' . + '\x{7FAA}\x{7FAB}\x{7FAC}\x{7FAD}\x{7FAE}\x{7FAF}\x{7FB0}\x{7FB1}\x{7FB2}' . + '\x{7FB3}\x{7FB5}\x{7FB6}\x{7FB7}\x{7FB8}\x{7FB9}\x{7FBA}\x{7FBB}\x{7FBC}' . + '\x{7FBD}\x{7FBE}\x{7FBF}\x{7FC0}\x{7FC1}\x{7FC2}\x{7FC3}\x{7FC4}\x{7FC5}' . + '\x{7FC6}\x{7FC7}\x{7FC8}\x{7FC9}\x{7FCA}\x{7FCB}\x{7FCC}\x{7FCD}\x{7FCE}' . + '\x{7FCF}\x{7FD0}\x{7FD1}\x{7FD2}\x{7FD3}\x{7FD4}\x{7FD5}\x{7FD7}\x{7FD8}' . + '\x{7FD9}\x{7FDA}\x{7FDB}\x{7FDC}\x{7FDE}\x{7FDF}\x{7FE0}\x{7FE1}\x{7FE2}' . + '\x{7FE3}\x{7FE5}\x{7FE6}\x{7FE7}\x{7FE8}\x{7FE9}\x{7FEA}\x{7FEB}\x{7FEC}' . + '\x{7FED}\x{7FEE}\x{7FEF}\x{7FF0}\x{7FF1}\x{7FF2}\x{7FF3}\x{7FF4}\x{7FF5}' . + '\x{7FF6}\x{7FF7}\x{7FF8}\x{7FF9}\x{7FFA}\x{7FFB}\x{7FFC}\x{7FFD}\x{7FFE}' . + '\x{7FFF}\x{8000}\x{8001}\x{8002}\x{8003}\x{8004}\x{8005}\x{8006}\x{8007}' . + '\x{8008}\x{8009}\x{800B}\x{800C}\x{800D}\x{800E}\x{800F}\x{8010}\x{8011}' . + '\x{8012}\x{8013}\x{8014}\x{8015}\x{8016}\x{8017}\x{8018}\x{8019}\x{801A}' . + '\x{801B}\x{801C}\x{801D}\x{801E}\x{801F}\x{8020}\x{8021}\x{8022}\x{8023}' . + '\x{8024}\x{8025}\x{8026}\x{8027}\x{8028}\x{8029}\x{802A}\x{802B}\x{802C}' . + '\x{802D}\x{802E}\x{8030}\x{8031}\x{8032}\x{8033}\x{8034}\x{8035}\x{8036}' . + '\x{8037}\x{8038}\x{8039}\x{803A}\x{803B}\x{803D}\x{803E}\x{803F}\x{8041}' . + '\x{8042}\x{8043}\x{8044}\x{8045}\x{8046}\x{8047}\x{8048}\x{8049}\x{804A}' . + '\x{804B}\x{804C}\x{804D}\x{804E}\x{804F}\x{8050}\x{8051}\x{8052}\x{8053}' . + '\x{8054}\x{8055}\x{8056}\x{8057}\x{8058}\x{8059}\x{805A}\x{805B}\x{805C}' . + '\x{805D}\x{805E}\x{805F}\x{8060}\x{8061}\x{8062}\x{8063}\x{8064}\x{8065}' . + '\x{8067}\x{8068}\x{8069}\x{806A}\x{806B}\x{806C}\x{806D}\x{806E}\x{806F}' . + '\x{8070}\x{8071}\x{8072}\x{8073}\x{8074}\x{8075}\x{8076}\x{8077}\x{8078}' . + '\x{8079}\x{807A}\x{807B}\x{807C}\x{807D}\x{807E}\x{807F}\x{8080}\x{8081}' . + '\x{8082}\x{8083}\x{8084}\x{8085}\x{8086}\x{8087}\x{8089}\x{808A}\x{808B}' . + '\x{808C}\x{808D}\x{808F}\x{8090}\x{8091}\x{8092}\x{8093}\x{8095}\x{8096}' . + '\x{8097}\x{8098}\x{8099}\x{809A}\x{809B}\x{809C}\x{809D}\x{809E}\x{809F}' . + '\x{80A0}\x{80A1}\x{80A2}\x{80A3}\x{80A4}\x{80A5}\x{80A9}\x{80AA}\x{80AB}' . + '\x{80AD}\x{80AE}\x{80AF}\x{80B0}\x{80B1}\x{80B2}\x{80B4}\x{80B5}\x{80B6}' . + '\x{80B7}\x{80B8}\x{80BA}\x{80BB}\x{80BC}\x{80BD}\x{80BE}\x{80BF}\x{80C0}' . + '\x{80C1}\x{80C2}\x{80C3}\x{80C4}\x{80C5}\x{80C6}\x{80C7}\x{80C8}\x{80C9}' . + '\x{80CA}\x{80CB}\x{80CC}\x{80CD}\x{80CE}\x{80CF}\x{80D0}\x{80D1}\x{80D2}' . + '\x{80D3}\x{80D4}\x{80D5}\x{80D6}\x{80D7}\x{80D8}\x{80D9}\x{80DA}\x{80DB}' . + '\x{80DC}\x{80DD}\x{80DE}\x{80E0}\x{80E1}\x{80E2}\x{80E3}\x{80E4}\x{80E5}' . + '\x{80E6}\x{80E7}\x{80E8}\x{80E9}\x{80EA}\x{80EB}\x{80EC}\x{80ED}\x{80EE}' . + '\x{80EF}\x{80F0}\x{80F1}\x{80F2}\x{80F3}\x{80F4}\x{80F5}\x{80F6}\x{80F7}' . + '\x{80F8}\x{80F9}\x{80FA}\x{80FB}\x{80FC}\x{80FD}\x{80FE}\x{80FF}\x{8100}' . + '\x{8101}\x{8102}\x{8105}\x{8106}\x{8107}\x{8108}\x{8109}\x{810A}\x{810B}' . + '\x{810C}\x{810D}\x{810E}\x{810F}\x{8110}\x{8111}\x{8112}\x{8113}\x{8114}' . + '\x{8115}\x{8116}\x{8118}\x{8119}\x{811A}\x{811B}\x{811C}\x{811D}\x{811E}' . + '\x{811F}\x{8120}\x{8121}\x{8122}\x{8123}\x{8124}\x{8125}\x{8126}\x{8127}' . + '\x{8128}\x{8129}\x{812A}\x{812B}\x{812C}\x{812D}\x{812E}\x{812F}\x{8130}' . + '\x{8131}\x{8132}\x{8136}\x{8137}\x{8138}\x{8139}\x{813A}\x{813B}\x{813C}' . + '\x{813D}\x{813E}\x{813F}\x{8140}\x{8141}\x{8142}\x{8143}\x{8144}\x{8145}' . + '\x{8146}\x{8147}\x{8148}\x{8149}\x{814A}\x{814B}\x{814C}\x{814D}\x{814E}' . + '\x{814F}\x{8150}\x{8151}\x{8152}\x{8153}\x{8154}\x{8155}\x{8156}\x{8157}' . + '\x{8158}\x{8159}\x{815A}\x{815B}\x{815C}\x{815D}\x{815E}\x{8160}\x{8161}' . + '\x{8162}\x{8163}\x{8164}\x{8165}\x{8166}\x{8167}\x{8168}\x{8169}\x{816A}' . + '\x{816B}\x{816C}\x{816D}\x{816E}\x{816F}\x{8170}\x{8171}\x{8172}\x{8173}' . + '\x{8174}\x{8175}\x{8176}\x{8177}\x{8178}\x{8179}\x{817A}\x{817B}\x{817C}' . + '\x{817D}\x{817E}\x{817F}\x{8180}\x{8181}\x{8182}\x{8183}\x{8185}\x{8186}' . + '\x{8187}\x{8188}\x{8189}\x{818A}\x{818B}\x{818C}\x{818D}\x{818E}\x{818F}' . + '\x{8191}\x{8192}\x{8193}\x{8194}\x{8195}\x{8197}\x{8198}\x{8199}\x{819A}' . + '\x{819B}\x{819C}\x{819D}\x{819E}\x{819F}\x{81A0}\x{81A1}\x{81A2}\x{81A3}' . + '\x{81A4}\x{81A5}\x{81A6}\x{81A7}\x{81A8}\x{81A9}\x{81AA}\x{81AB}\x{81AC}' . + '\x{81AD}\x{81AE}\x{81AF}\x{81B0}\x{81B1}\x{81B2}\x{81B3}\x{81B4}\x{81B5}' . + '\x{81B6}\x{81B7}\x{81B8}\x{81B9}\x{81BA}\x{81BB}\x{81BC}\x{81BD}\x{81BE}' . + '\x{81BF}\x{81C0}\x{81C1}\x{81C2}\x{81C3}\x{81C4}\x{81C5}\x{81C6}\x{81C7}' . + '\x{81C8}\x{81C9}\x{81CA}\x{81CC}\x{81CD}\x{81CE}\x{81CF}\x{81D0}\x{81D1}' . + '\x{81D2}\x{81D4}\x{81D5}\x{81D6}\x{81D7}\x{81D8}\x{81D9}\x{81DA}\x{81DB}' . + '\x{81DC}\x{81DD}\x{81DE}\x{81DF}\x{81E0}\x{81E1}\x{81E2}\x{81E3}\x{81E5}' . + '\x{81E6}\x{81E7}\x{81E8}\x{81E9}\x{81EA}\x{81EB}\x{81EC}\x{81ED}\x{81EE}' . + '\x{81F1}\x{81F2}\x{81F3}\x{81F4}\x{81F5}\x{81F6}\x{81F7}\x{81F8}\x{81F9}' . + '\x{81FA}\x{81FB}\x{81FC}\x{81FD}\x{81FE}\x{81FF}\x{8200}\x{8201}\x{8202}' . + '\x{8203}\x{8204}\x{8205}\x{8206}\x{8207}\x{8208}\x{8209}\x{820A}\x{820B}' . + '\x{820C}\x{820D}\x{820E}\x{820F}\x{8210}\x{8211}\x{8212}\x{8214}\x{8215}' . + '\x{8216}\x{8218}\x{8219}\x{821A}\x{821B}\x{821C}\x{821D}\x{821E}\x{821F}' . + '\x{8220}\x{8221}\x{8222}\x{8223}\x{8225}\x{8226}\x{8227}\x{8228}\x{8229}' . + '\x{822A}\x{822B}\x{822C}\x{822D}\x{822F}\x{8230}\x{8231}\x{8232}\x{8233}' . + '\x{8234}\x{8235}\x{8236}\x{8237}\x{8238}\x{8239}\x{823A}\x{823B}\x{823C}' . + '\x{823D}\x{823E}\x{823F}\x{8240}\x{8242}\x{8243}\x{8244}\x{8245}\x{8246}' . + '\x{8247}\x{8248}\x{8249}\x{824A}\x{824B}\x{824C}\x{824D}\x{824E}\x{824F}' . + '\x{8250}\x{8251}\x{8252}\x{8253}\x{8254}\x{8255}\x{8256}\x{8257}\x{8258}' . + '\x{8259}\x{825A}\x{825B}\x{825C}\x{825D}\x{825E}\x{825F}\x{8260}\x{8261}' . + '\x{8263}\x{8264}\x{8266}\x{8267}\x{8268}\x{8269}\x{826A}\x{826B}\x{826C}' . + '\x{826D}\x{826E}\x{826F}\x{8270}\x{8271}\x{8272}\x{8273}\x{8274}\x{8275}' . + '\x{8276}\x{8277}\x{8278}\x{8279}\x{827A}\x{827B}\x{827C}\x{827D}\x{827E}' . + '\x{827F}\x{8280}\x{8281}\x{8282}\x{8283}\x{8284}\x{8285}\x{8286}\x{8287}' . + '\x{8288}\x{8289}\x{828A}\x{828B}\x{828D}\x{828E}\x{828F}\x{8290}\x{8291}' . + '\x{8292}\x{8293}\x{8294}\x{8295}\x{8296}\x{8297}\x{8298}\x{8299}\x{829A}' . + '\x{829B}\x{829C}\x{829D}\x{829E}\x{829F}\x{82A0}\x{82A1}\x{82A2}\x{82A3}' . + '\x{82A4}\x{82A5}\x{82A6}\x{82A7}\x{82A8}\x{82A9}\x{82AA}\x{82AB}\x{82AC}' . + '\x{82AD}\x{82AE}\x{82AF}\x{82B0}\x{82B1}\x{82B3}\x{82B4}\x{82B5}\x{82B6}' . + '\x{82B7}\x{82B8}\x{82B9}\x{82BA}\x{82BB}\x{82BC}\x{82BD}\x{82BE}\x{82BF}' . + '\x{82C0}\x{82C1}\x{82C2}\x{82C3}\x{82C4}\x{82C5}\x{82C6}\x{82C7}\x{82C8}' . + '\x{82C9}\x{82CA}\x{82CB}\x{82CC}\x{82CD}\x{82CE}\x{82CF}\x{82D0}\x{82D1}' . + '\x{82D2}\x{82D3}\x{82D4}\x{82D5}\x{82D6}\x{82D7}\x{82D8}\x{82D9}\x{82DA}' . + '\x{82DB}\x{82DC}\x{82DD}\x{82DE}\x{82DF}\x{82E0}\x{82E1}\x{82E3}\x{82E4}' . + '\x{82E5}\x{82E6}\x{82E7}\x{82E8}\x{82E9}\x{82EA}\x{82EB}\x{82EC}\x{82ED}' . + '\x{82EE}\x{82EF}\x{82F0}\x{82F1}\x{82F2}\x{82F3}\x{82F4}\x{82F5}\x{82F6}' . + '\x{82F7}\x{82F8}\x{82F9}\x{82FA}\x{82FB}\x{82FD}\x{82FE}\x{82FF}\x{8300}' . + '\x{8301}\x{8302}\x{8303}\x{8304}\x{8305}\x{8306}\x{8307}\x{8308}\x{8309}' . + '\x{830B}\x{830C}\x{830D}\x{830E}\x{830F}\x{8311}\x{8312}\x{8313}\x{8314}' . + '\x{8315}\x{8316}\x{8317}\x{8318}\x{8319}\x{831A}\x{831B}\x{831C}\x{831D}' . + '\x{831E}\x{831F}\x{8320}\x{8321}\x{8322}\x{8323}\x{8324}\x{8325}\x{8326}' . + '\x{8327}\x{8328}\x{8329}\x{832A}\x{832B}\x{832C}\x{832D}\x{832E}\x{832F}' . + '\x{8331}\x{8332}\x{8333}\x{8334}\x{8335}\x{8336}\x{8337}\x{8338}\x{8339}' . + '\x{833A}\x{833B}\x{833C}\x{833D}\x{833E}\x{833F}\x{8340}\x{8341}\x{8342}' . + '\x{8343}\x{8344}\x{8345}\x{8346}\x{8347}\x{8348}\x{8349}\x{834A}\x{834B}' . + '\x{834C}\x{834D}\x{834E}\x{834F}\x{8350}\x{8351}\x{8352}\x{8353}\x{8354}' . + '\x{8356}\x{8357}\x{8358}\x{8359}\x{835A}\x{835B}\x{835C}\x{835D}\x{835E}' . + '\x{835F}\x{8360}\x{8361}\x{8362}\x{8363}\x{8364}\x{8365}\x{8366}\x{8367}' . + '\x{8368}\x{8369}\x{836A}\x{836B}\x{836C}\x{836D}\x{836E}\x{836F}\x{8370}' . + '\x{8371}\x{8372}\x{8373}\x{8374}\x{8375}\x{8376}\x{8377}\x{8378}\x{8379}' . + '\x{837A}\x{837B}\x{837C}\x{837D}\x{837E}\x{837F}\x{8380}\x{8381}\x{8382}' . + '\x{8383}\x{8384}\x{8385}\x{8386}\x{8387}\x{8388}\x{8389}\x{838A}\x{838B}' . + '\x{838C}\x{838D}\x{838E}\x{838F}\x{8390}\x{8391}\x{8392}\x{8393}\x{8394}' . + '\x{8395}\x{8396}\x{8397}\x{8398}\x{8399}\x{839A}\x{839B}\x{839C}\x{839D}' . + '\x{839E}\x{83A0}\x{83A1}\x{83A2}\x{83A3}\x{83A4}\x{83A5}\x{83A6}\x{83A7}' . + '\x{83A8}\x{83A9}\x{83AA}\x{83AB}\x{83AC}\x{83AD}\x{83AE}\x{83AF}\x{83B0}' . + '\x{83B1}\x{83B2}\x{83B3}\x{83B4}\x{83B6}\x{83B7}\x{83B8}\x{83B9}\x{83BA}' . + '\x{83BB}\x{83BC}\x{83BD}\x{83BF}\x{83C0}\x{83C1}\x{83C2}\x{83C3}\x{83C4}' . + '\x{83C5}\x{83C6}\x{83C7}\x{83C8}\x{83C9}\x{83CA}\x{83CB}\x{83CC}\x{83CD}' . + '\x{83CE}\x{83CF}\x{83D0}\x{83D1}\x{83D2}\x{83D3}\x{83D4}\x{83D5}\x{83D6}' . + '\x{83D7}\x{83D8}\x{83D9}\x{83DA}\x{83DB}\x{83DC}\x{83DD}\x{83DE}\x{83DF}' . + '\x{83E0}\x{83E1}\x{83E2}\x{83E3}\x{83E4}\x{83E5}\x{83E7}\x{83E8}\x{83E9}' . + '\x{83EA}\x{83EB}\x{83EC}\x{83EE}\x{83EF}\x{83F0}\x{83F1}\x{83F2}\x{83F3}' . + '\x{83F4}\x{83F5}\x{83F6}\x{83F7}\x{83F8}\x{83F9}\x{83FA}\x{83FB}\x{83FC}' . + '\x{83FD}\x{83FE}\x{83FF}\x{8400}\x{8401}\x{8402}\x{8403}\x{8404}\x{8405}' . + '\x{8406}\x{8407}\x{8408}\x{8409}\x{840A}\x{840B}\x{840C}\x{840D}\x{840E}' . + '\x{840F}\x{8410}\x{8411}\x{8412}\x{8413}\x{8415}\x{8418}\x{8419}\x{841A}' . + '\x{841B}\x{841C}\x{841D}\x{841E}\x{8421}\x{8422}\x{8423}\x{8424}\x{8425}' . + '\x{8426}\x{8427}\x{8428}\x{8429}\x{842A}\x{842B}\x{842C}\x{842D}\x{842E}' . + '\x{842F}\x{8430}\x{8431}\x{8432}\x{8433}\x{8434}\x{8435}\x{8436}\x{8437}' . + '\x{8438}\x{8439}\x{843A}\x{843B}\x{843C}\x{843D}\x{843E}\x{843F}\x{8440}' . + '\x{8441}\x{8442}\x{8443}\x{8444}\x{8445}\x{8446}\x{8447}\x{8448}\x{8449}' . + '\x{844A}\x{844B}\x{844C}\x{844D}\x{844E}\x{844F}\x{8450}\x{8451}\x{8452}' . + '\x{8453}\x{8454}\x{8455}\x{8456}\x{8457}\x{8459}\x{845A}\x{845B}\x{845C}' . + '\x{845D}\x{845E}\x{845F}\x{8460}\x{8461}\x{8462}\x{8463}\x{8464}\x{8465}' . + '\x{8466}\x{8467}\x{8468}\x{8469}\x{846A}\x{846B}\x{846C}\x{846D}\x{846E}' . + '\x{846F}\x{8470}\x{8471}\x{8472}\x{8473}\x{8474}\x{8475}\x{8476}\x{8477}' . + '\x{8478}\x{8479}\x{847A}\x{847B}\x{847C}\x{847D}\x{847E}\x{847F}\x{8480}' . + '\x{8481}\x{8482}\x{8484}\x{8485}\x{8486}\x{8487}\x{8488}\x{8489}\x{848A}' . + '\x{848B}\x{848C}\x{848D}\x{848E}\x{848F}\x{8490}\x{8491}\x{8492}\x{8493}' . + '\x{8494}\x{8496}\x{8497}\x{8498}\x{8499}\x{849A}\x{849B}\x{849C}\x{849D}' . + '\x{849E}\x{849F}\x{84A0}\x{84A1}\x{84A2}\x{84A3}\x{84A4}\x{84A5}\x{84A6}' . + '\x{84A7}\x{84A8}\x{84A9}\x{84AA}\x{84AB}\x{84AC}\x{84AE}\x{84AF}\x{84B0}' . + '\x{84B1}\x{84B2}\x{84B3}\x{84B4}\x{84B5}\x{84B6}\x{84B8}\x{84B9}\x{84BA}' . + '\x{84BB}\x{84BC}\x{84BD}\x{84BE}\x{84BF}\x{84C0}\x{84C1}\x{84C2}\x{84C4}' . + '\x{84C5}\x{84C6}\x{84C7}\x{84C8}\x{84C9}\x{84CA}\x{84CB}\x{84CC}\x{84CD}' . + '\x{84CE}\x{84CF}\x{84D0}\x{84D1}\x{84D2}\x{84D3}\x{84D4}\x{84D5}\x{84D6}' . + '\x{84D7}\x{84D8}\x{84D9}\x{84DB}\x{84DC}\x{84DD}\x{84DE}\x{84DF}\x{84E0}' . + '\x{84E1}\x{84E2}\x{84E3}\x{84E4}\x{84E5}\x{84E6}\x{84E7}\x{84E8}\x{84E9}' . + '\x{84EA}\x{84EB}\x{84EC}\x{84EE}\x{84EF}\x{84F0}\x{84F1}\x{84F2}\x{84F3}' . + '\x{84F4}\x{84F5}\x{84F6}\x{84F7}\x{84F8}\x{84F9}\x{84FA}\x{84FB}\x{84FC}' . + '\x{84FD}\x{84FE}\x{84FF}\x{8500}\x{8501}\x{8502}\x{8503}\x{8504}\x{8506}' . + '\x{8507}\x{8508}\x{8509}\x{850A}\x{850B}\x{850C}\x{850D}\x{850E}\x{850F}' . + '\x{8511}\x{8512}\x{8513}\x{8514}\x{8515}\x{8516}\x{8517}\x{8518}\x{8519}' . + '\x{851A}\x{851B}\x{851C}\x{851D}\x{851E}\x{851F}\x{8520}\x{8521}\x{8522}' . + '\x{8523}\x{8524}\x{8525}\x{8526}\x{8527}\x{8528}\x{8529}\x{852A}\x{852B}' . + '\x{852C}\x{852D}\x{852E}\x{852F}\x{8530}\x{8531}\x{8534}\x{8535}\x{8536}' . + '\x{8537}\x{8538}\x{8539}\x{853A}\x{853B}\x{853C}\x{853D}\x{853E}\x{853F}' . + '\x{8540}\x{8541}\x{8542}\x{8543}\x{8544}\x{8545}\x{8546}\x{8547}\x{8548}' . + '\x{8549}\x{854A}\x{854B}\x{854D}\x{854E}\x{854F}\x{8551}\x{8552}\x{8553}' . + '\x{8554}\x{8555}\x{8556}\x{8557}\x{8558}\x{8559}\x{855A}\x{855B}\x{855C}' . + '\x{855D}\x{855E}\x{855F}\x{8560}\x{8561}\x{8562}\x{8563}\x{8564}\x{8565}' . + '\x{8566}\x{8567}\x{8568}\x{8569}\x{856A}\x{856B}\x{856C}\x{856D}\x{856E}' . + '\x{856F}\x{8570}\x{8571}\x{8572}\x{8573}\x{8574}\x{8575}\x{8576}\x{8577}' . + '\x{8578}\x{8579}\x{857A}\x{857B}\x{857C}\x{857D}\x{857E}\x{8580}\x{8581}' . + '\x{8582}\x{8583}\x{8584}\x{8585}\x{8586}\x{8587}\x{8588}\x{8589}\x{858A}' . + '\x{858B}\x{858C}\x{858D}\x{858E}\x{858F}\x{8590}\x{8591}\x{8592}\x{8594}' . + '\x{8595}\x{8596}\x{8598}\x{8599}\x{859A}\x{859B}\x{859C}\x{859D}\x{859E}' . + '\x{859F}\x{85A0}\x{85A1}\x{85A2}\x{85A3}\x{85A4}\x{85A5}\x{85A6}\x{85A7}' . + '\x{85A8}\x{85A9}\x{85AA}\x{85AB}\x{85AC}\x{85AD}\x{85AE}\x{85AF}\x{85B0}' . + '\x{85B1}\x{85B3}\x{85B4}\x{85B5}\x{85B6}\x{85B7}\x{85B8}\x{85B9}\x{85BA}' . + '\x{85BC}\x{85BD}\x{85BE}\x{85BF}\x{85C0}\x{85C1}\x{85C2}\x{85C3}\x{85C4}' . + '\x{85C5}\x{85C6}\x{85C7}\x{85C8}\x{85C9}\x{85CA}\x{85CB}\x{85CD}\x{85CE}' . + '\x{85CF}\x{85D0}\x{85D1}\x{85D2}\x{85D3}\x{85D4}\x{85D5}\x{85D6}\x{85D7}' . + '\x{85D8}\x{85D9}\x{85DA}\x{85DB}\x{85DC}\x{85DD}\x{85DE}\x{85DF}\x{85E0}' . + '\x{85E1}\x{85E2}\x{85E3}\x{85E4}\x{85E5}\x{85E6}\x{85E7}\x{85E8}\x{85E9}' . + '\x{85EA}\x{85EB}\x{85EC}\x{85ED}\x{85EF}\x{85F0}\x{85F1}\x{85F2}\x{85F4}' . + '\x{85F5}\x{85F6}\x{85F7}\x{85F8}\x{85F9}\x{85FA}\x{85FB}\x{85FD}\x{85FE}' . + '\x{85FF}\x{8600}\x{8601}\x{8602}\x{8604}\x{8605}\x{8606}\x{8607}\x{8608}' . + '\x{8609}\x{860A}\x{860B}\x{860C}\x{860F}\x{8611}\x{8612}\x{8613}\x{8614}' . + '\x{8616}\x{8617}\x{8618}\x{8619}\x{861A}\x{861B}\x{861C}\x{861E}\x{861F}' . + '\x{8620}\x{8621}\x{8622}\x{8623}\x{8624}\x{8625}\x{8626}\x{8627}\x{8628}' . + '\x{8629}\x{862A}\x{862B}\x{862C}\x{862D}\x{862E}\x{862F}\x{8630}\x{8631}' . + '\x{8632}\x{8633}\x{8634}\x{8635}\x{8636}\x{8638}\x{8639}\x{863A}\x{863B}' . + '\x{863C}\x{863D}\x{863E}\x{863F}\x{8640}\x{8641}\x{8642}\x{8643}\x{8644}' . + '\x{8645}\x{8646}\x{8647}\x{8648}\x{8649}\x{864A}\x{864B}\x{864C}\x{864D}' . + '\x{864E}\x{864F}\x{8650}\x{8651}\x{8652}\x{8653}\x{8654}\x{8655}\x{8656}' . + '\x{8658}\x{8659}\x{865A}\x{865B}\x{865C}\x{865D}\x{865E}\x{865F}\x{8660}' . + '\x{8661}\x{8662}\x{8663}\x{8664}\x{8665}\x{8666}\x{8667}\x{8668}\x{8669}' . + '\x{866A}\x{866B}\x{866C}\x{866D}\x{866E}\x{866F}\x{8670}\x{8671}\x{8672}' . + '\x{8673}\x{8674}\x{8676}\x{8677}\x{8678}\x{8679}\x{867A}\x{867B}\x{867C}' . + '\x{867D}\x{867E}\x{867F}\x{8680}\x{8681}\x{8682}\x{8683}\x{8684}\x{8685}' . + '\x{8686}\x{8687}\x{8688}\x{868A}\x{868B}\x{868C}\x{868D}\x{868E}\x{868F}' . + '\x{8690}\x{8691}\x{8693}\x{8694}\x{8695}\x{8696}\x{8697}\x{8698}\x{8699}' . + '\x{869A}\x{869B}\x{869C}\x{869D}\x{869E}\x{869F}\x{86A1}\x{86A2}\x{86A3}' . + '\x{86A4}\x{86A5}\x{86A7}\x{86A8}\x{86A9}\x{86AA}\x{86AB}\x{86AC}\x{86AD}' . + '\x{86AE}\x{86AF}\x{86B0}\x{86B1}\x{86B2}\x{86B3}\x{86B4}\x{86B5}\x{86B6}' . + '\x{86B7}\x{86B8}\x{86B9}\x{86BA}\x{86BB}\x{86BC}\x{86BD}\x{86BE}\x{86BF}' . + '\x{86C0}\x{86C1}\x{86C2}\x{86C3}\x{86C4}\x{86C5}\x{86C6}\x{86C7}\x{86C8}' . + '\x{86C9}\x{86CA}\x{86CB}\x{86CC}\x{86CE}\x{86CF}\x{86D0}\x{86D1}\x{86D2}' . + '\x{86D3}\x{86D4}\x{86D6}\x{86D7}\x{86D8}\x{86D9}\x{86DA}\x{86DB}\x{86DC}' . + '\x{86DD}\x{86DE}\x{86DF}\x{86E1}\x{86E2}\x{86E3}\x{86E4}\x{86E5}\x{86E6}' . + '\x{86E8}\x{86E9}\x{86EA}\x{86EB}\x{86EC}\x{86ED}\x{86EE}\x{86EF}\x{86F0}' . + '\x{86F1}\x{86F2}\x{86F3}\x{86F4}\x{86F5}\x{86F6}\x{86F7}\x{86F8}\x{86F9}' . + '\x{86FA}\x{86FB}\x{86FC}\x{86FE}\x{86FF}\x{8700}\x{8701}\x{8702}\x{8703}' . + '\x{8704}\x{8705}\x{8706}\x{8707}\x{8708}\x{8709}\x{870A}\x{870B}\x{870C}' . + '\x{870D}\x{870E}\x{870F}\x{8710}\x{8711}\x{8712}\x{8713}\x{8714}\x{8715}' . + '\x{8716}\x{8717}\x{8718}\x{8719}\x{871A}\x{871B}\x{871C}\x{871E}\x{871F}' . + '\x{8720}\x{8721}\x{8722}\x{8723}\x{8724}\x{8725}\x{8726}\x{8727}\x{8728}' . + '\x{8729}\x{872A}\x{872B}\x{872C}\x{872D}\x{872E}\x{8730}\x{8731}\x{8732}' . + '\x{8733}\x{8734}\x{8735}\x{8736}\x{8737}\x{8738}\x{8739}\x{873A}\x{873B}' . + '\x{873C}\x{873E}\x{873F}\x{8740}\x{8741}\x{8742}\x{8743}\x{8744}\x{8746}' . + '\x{8747}\x{8748}\x{8749}\x{874A}\x{874C}\x{874D}\x{874E}\x{874F}\x{8750}' . + '\x{8751}\x{8752}\x{8753}\x{8754}\x{8755}\x{8756}\x{8757}\x{8758}\x{8759}' . + '\x{875A}\x{875B}\x{875C}\x{875D}\x{875E}\x{875F}\x{8760}\x{8761}\x{8762}' . + '\x{8763}\x{8764}\x{8765}\x{8766}\x{8767}\x{8768}\x{8769}\x{876A}\x{876B}' . + '\x{876C}\x{876D}\x{876E}\x{876F}\x{8770}\x{8772}\x{8773}\x{8774}\x{8775}' . + '\x{8776}\x{8777}\x{8778}\x{8779}\x{877A}\x{877B}\x{877C}\x{877D}\x{877E}' . + '\x{8780}\x{8781}\x{8782}\x{8783}\x{8784}\x{8785}\x{8786}\x{8787}\x{8788}' . + '\x{8789}\x{878A}\x{878B}\x{878C}\x{878D}\x{878F}\x{8790}\x{8791}\x{8792}' . + '\x{8793}\x{8794}\x{8795}\x{8796}\x{8797}\x{8798}\x{879A}\x{879B}\x{879C}' . + '\x{879D}\x{879E}\x{879F}\x{87A0}\x{87A1}\x{87A2}\x{87A3}\x{87A4}\x{87A5}' . + '\x{87A6}\x{87A7}\x{87A8}\x{87A9}\x{87AA}\x{87AB}\x{87AC}\x{87AD}\x{87AE}' . + '\x{87AF}\x{87B0}\x{87B1}\x{87B2}\x{87B3}\x{87B4}\x{87B5}\x{87B6}\x{87B7}' . + '\x{87B8}\x{87B9}\x{87BA}\x{87BB}\x{87BC}\x{87BD}\x{87BE}\x{87BF}\x{87C0}' . + '\x{87C1}\x{87C2}\x{87C3}\x{87C4}\x{87C5}\x{87C6}\x{87C7}\x{87C8}\x{87C9}' . + '\x{87CA}\x{87CB}\x{87CC}\x{87CD}\x{87CE}\x{87CF}\x{87D0}\x{87D1}\x{87D2}' . + '\x{87D3}\x{87D4}\x{87D5}\x{87D6}\x{87D7}\x{87D8}\x{87D9}\x{87DB}\x{87DC}' . + '\x{87DD}\x{87DE}\x{87DF}\x{87E0}\x{87E1}\x{87E2}\x{87E3}\x{87E4}\x{87E5}' . + '\x{87E6}\x{87E7}\x{87E8}\x{87E9}\x{87EA}\x{87EB}\x{87EC}\x{87ED}\x{87EE}' . + '\x{87EF}\x{87F1}\x{87F2}\x{87F3}\x{87F4}\x{87F5}\x{87F6}\x{87F7}\x{87F8}' . + '\x{87F9}\x{87FA}\x{87FB}\x{87FC}\x{87FD}\x{87FE}\x{87FF}\x{8800}\x{8801}' . + '\x{8802}\x{8803}\x{8804}\x{8805}\x{8806}\x{8808}\x{8809}\x{880A}\x{880B}' . + '\x{880C}\x{880D}\x{880E}\x{880F}\x{8810}\x{8811}\x{8813}\x{8814}\x{8815}' . + '\x{8816}\x{8817}\x{8818}\x{8819}\x{881A}\x{881B}\x{881C}\x{881D}\x{881E}' . + '\x{881F}\x{8820}\x{8821}\x{8822}\x{8823}\x{8824}\x{8825}\x{8826}\x{8827}' . + '\x{8828}\x{8829}\x{882A}\x{882B}\x{882C}\x{882E}\x{882F}\x{8830}\x{8831}' . + '\x{8832}\x{8833}\x{8834}\x{8835}\x{8836}\x{8837}\x{8838}\x{8839}\x{883B}' . + '\x{883C}\x{883D}\x{883E}\x{883F}\x{8840}\x{8841}\x{8842}\x{8843}\x{8844}' . + '\x{8845}\x{8846}\x{8848}\x{8849}\x{884A}\x{884B}\x{884C}\x{884D}\x{884E}' . + '\x{884F}\x{8850}\x{8851}\x{8852}\x{8853}\x{8854}\x{8855}\x{8856}\x{8857}' . + '\x{8859}\x{885A}\x{885B}\x{885D}\x{885E}\x{8860}\x{8861}\x{8862}\x{8863}' . + '\x{8864}\x{8865}\x{8866}\x{8867}\x{8868}\x{8869}\x{886A}\x{886B}\x{886C}' . + '\x{886D}\x{886E}\x{886F}\x{8870}\x{8871}\x{8872}\x{8873}\x{8874}\x{8875}' . + '\x{8876}\x{8877}\x{8878}\x{8879}\x{887B}\x{887C}\x{887D}\x{887E}\x{887F}' . + '\x{8880}\x{8881}\x{8882}\x{8883}\x{8884}\x{8885}\x{8886}\x{8887}\x{8888}' . + '\x{8889}\x{888A}\x{888B}\x{888C}\x{888D}\x{888E}\x{888F}\x{8890}\x{8891}' . + '\x{8892}\x{8893}\x{8894}\x{8895}\x{8896}\x{8897}\x{8898}\x{8899}\x{889A}' . + '\x{889B}\x{889C}\x{889D}\x{889E}\x{889F}\x{88A0}\x{88A1}\x{88A2}\x{88A3}' . + '\x{88A4}\x{88A5}\x{88A6}\x{88A7}\x{88A8}\x{88A9}\x{88AA}\x{88AB}\x{88AC}' . + '\x{88AD}\x{88AE}\x{88AF}\x{88B0}\x{88B1}\x{88B2}\x{88B3}\x{88B4}\x{88B6}' . + '\x{88B7}\x{88B8}\x{88B9}\x{88BA}\x{88BB}\x{88BC}\x{88BD}\x{88BE}\x{88BF}' . + '\x{88C0}\x{88C1}\x{88C2}\x{88C3}\x{88C4}\x{88C5}\x{88C6}\x{88C7}\x{88C8}' . + '\x{88C9}\x{88CA}\x{88CB}\x{88CC}\x{88CD}\x{88CE}\x{88CF}\x{88D0}\x{88D1}' . + '\x{88D2}\x{88D3}\x{88D4}\x{88D5}\x{88D6}\x{88D7}\x{88D8}\x{88D9}\x{88DA}' . + '\x{88DB}\x{88DC}\x{88DD}\x{88DE}\x{88DF}\x{88E0}\x{88E1}\x{88E2}\x{88E3}' . + '\x{88E4}\x{88E5}\x{88E7}\x{88E8}\x{88EA}\x{88EB}\x{88EC}\x{88EE}\x{88EF}' . + '\x{88F0}\x{88F1}\x{88F2}\x{88F3}\x{88F4}\x{88F5}\x{88F6}\x{88F7}\x{88F8}' . + '\x{88F9}\x{88FA}\x{88FB}\x{88FC}\x{88FD}\x{88FE}\x{88FF}\x{8900}\x{8901}' . + '\x{8902}\x{8904}\x{8905}\x{8906}\x{8907}\x{8908}\x{8909}\x{890A}\x{890B}' . + '\x{890C}\x{890D}\x{890E}\x{8910}\x{8911}\x{8912}\x{8913}\x{8914}\x{8915}' . + '\x{8916}\x{8917}\x{8918}\x{8919}\x{891A}\x{891B}\x{891C}\x{891D}\x{891E}' . + '\x{891F}\x{8920}\x{8921}\x{8922}\x{8923}\x{8925}\x{8926}\x{8927}\x{8928}' . + '\x{8929}\x{892A}\x{892B}\x{892C}\x{892D}\x{892E}\x{892F}\x{8930}\x{8931}' . + '\x{8932}\x{8933}\x{8934}\x{8935}\x{8936}\x{8937}\x{8938}\x{8939}\x{893A}' . + '\x{893B}\x{893C}\x{893D}\x{893E}\x{893F}\x{8940}\x{8941}\x{8942}\x{8943}' . + '\x{8944}\x{8945}\x{8946}\x{8947}\x{8948}\x{8949}\x{894A}\x{894B}\x{894C}' . + '\x{894E}\x{894F}\x{8950}\x{8951}\x{8952}\x{8953}\x{8954}\x{8955}\x{8956}' . + '\x{8957}\x{8958}\x{8959}\x{895A}\x{895B}\x{895C}\x{895D}\x{895E}\x{895F}' . + '\x{8960}\x{8961}\x{8962}\x{8963}\x{8964}\x{8966}\x{8967}\x{8968}\x{8969}' . + '\x{896A}\x{896B}\x{896C}\x{896D}\x{896E}\x{896F}\x{8970}\x{8971}\x{8972}' . + '\x{8973}\x{8974}\x{8976}\x{8977}\x{8978}\x{8979}\x{897A}\x{897B}\x{897C}' . + '\x{897E}\x{897F}\x{8980}\x{8981}\x{8982}\x{8983}\x{8984}\x{8985}\x{8986}' . + '\x{8987}\x{8988}\x{8989}\x{898A}\x{898B}\x{898C}\x{898E}\x{898F}\x{8991}' . + '\x{8992}\x{8993}\x{8995}\x{8996}\x{8997}\x{8998}\x{899A}\x{899B}\x{899C}' . + '\x{899D}\x{899E}\x{899F}\x{89A0}\x{89A1}\x{89A2}\x{89A3}\x{89A4}\x{89A5}' . + '\x{89A6}\x{89A7}\x{89A8}\x{89AA}\x{89AB}\x{89AC}\x{89AD}\x{89AE}\x{89AF}' . + '\x{89B1}\x{89B2}\x{89B3}\x{89B5}\x{89B6}\x{89B7}\x{89B8}\x{89B9}\x{89BA}' . + '\x{89BD}\x{89BE}\x{89BF}\x{89C0}\x{89C1}\x{89C2}\x{89C3}\x{89C4}\x{89C5}' . + '\x{89C6}\x{89C7}\x{89C8}\x{89C9}\x{89CA}\x{89CB}\x{89CC}\x{89CD}\x{89CE}' . + '\x{89CF}\x{89D0}\x{89D1}\x{89D2}\x{89D3}\x{89D4}\x{89D5}\x{89D6}\x{89D7}' . + '\x{89D8}\x{89D9}\x{89DA}\x{89DB}\x{89DC}\x{89DD}\x{89DE}\x{89DF}\x{89E0}' . + '\x{89E1}\x{89E2}\x{89E3}\x{89E4}\x{89E5}\x{89E6}\x{89E7}\x{89E8}\x{89E9}' . + '\x{89EA}\x{89EB}\x{89EC}\x{89ED}\x{89EF}\x{89F0}\x{89F1}\x{89F2}\x{89F3}' . + '\x{89F4}\x{89F6}\x{89F7}\x{89F8}\x{89FA}\x{89FB}\x{89FC}\x{89FE}\x{89FF}' . + '\x{8A00}\x{8A01}\x{8A02}\x{8A03}\x{8A04}\x{8A07}\x{8A08}\x{8A09}\x{8A0A}' . + '\x{8A0B}\x{8A0C}\x{8A0D}\x{8A0E}\x{8A0F}\x{8A10}\x{8A11}\x{8A12}\x{8A13}' . + '\x{8A15}\x{8A16}\x{8A17}\x{8A18}\x{8A1A}\x{8A1B}\x{8A1C}\x{8A1D}\x{8A1E}' . + '\x{8A1F}\x{8A22}\x{8A23}\x{8A24}\x{8A25}\x{8A26}\x{8A27}\x{8A28}\x{8A29}' . + '\x{8A2A}\x{8A2C}\x{8A2D}\x{8A2E}\x{8A2F}\x{8A30}\x{8A31}\x{8A32}\x{8A34}' . + '\x{8A35}\x{8A36}\x{8A37}\x{8A38}\x{8A39}\x{8A3A}\x{8A3B}\x{8A3C}\x{8A3E}' . + '\x{8A3F}\x{8A40}\x{8A41}\x{8A42}\x{8A43}\x{8A44}\x{8A45}\x{8A46}\x{8A47}' . + '\x{8A48}\x{8A49}\x{8A4A}\x{8A4C}\x{8A4D}\x{8A4E}\x{8A4F}\x{8A50}\x{8A51}' . + '\x{8A52}\x{8A53}\x{8A54}\x{8A55}\x{8A56}\x{8A57}\x{8A58}\x{8A59}\x{8A5A}' . + '\x{8A5B}\x{8A5C}\x{8A5D}\x{8A5E}\x{8A5F}\x{8A60}\x{8A61}\x{8A62}\x{8A63}' . + '\x{8A65}\x{8A66}\x{8A67}\x{8A68}\x{8A69}\x{8A6A}\x{8A6B}\x{8A6C}\x{8A6D}' . + '\x{8A6E}\x{8A6F}\x{8A70}\x{8A71}\x{8A72}\x{8A73}\x{8A74}\x{8A75}\x{8A76}' . + '\x{8A77}\x{8A79}\x{8A7A}\x{8A7B}\x{8A7C}\x{8A7E}\x{8A7F}\x{8A80}\x{8A81}' . + '\x{8A82}\x{8A83}\x{8A84}\x{8A85}\x{8A86}\x{8A87}\x{8A89}\x{8A8A}\x{8A8B}' . + '\x{8A8C}\x{8A8D}\x{8A8E}\x{8A8F}\x{8A90}\x{8A91}\x{8A92}\x{8A93}\x{8A94}' . + '\x{8A95}\x{8A96}\x{8A97}\x{8A98}\x{8A99}\x{8A9A}\x{8A9B}\x{8A9C}\x{8A9D}' . + '\x{8A9E}\x{8AA0}\x{8AA1}\x{8AA2}\x{8AA3}\x{8AA4}\x{8AA5}\x{8AA6}\x{8AA7}' . + '\x{8AA8}\x{8AA9}\x{8AAA}\x{8AAB}\x{8AAC}\x{8AAE}\x{8AB0}\x{8AB1}\x{8AB2}' . + '\x{8AB3}\x{8AB4}\x{8AB5}\x{8AB6}\x{8AB8}\x{8AB9}\x{8ABA}\x{8ABB}\x{8ABC}' . + '\x{8ABD}\x{8ABE}\x{8ABF}\x{8AC0}\x{8AC1}\x{8AC2}\x{8AC3}\x{8AC4}\x{8AC5}' . + '\x{8AC6}\x{8AC7}\x{8AC8}\x{8AC9}\x{8ACA}\x{8ACB}\x{8ACC}\x{8ACD}\x{8ACE}' . + '\x{8ACF}\x{8AD1}\x{8AD2}\x{8AD3}\x{8AD4}\x{8AD5}\x{8AD6}\x{8AD7}\x{8AD8}' . + '\x{8AD9}\x{8ADA}\x{8ADB}\x{8ADC}\x{8ADD}\x{8ADE}\x{8ADF}\x{8AE0}\x{8AE1}' . + '\x{8AE2}\x{8AE3}\x{8AE4}\x{8AE5}\x{8AE6}\x{8AE7}\x{8AE8}\x{8AE9}\x{8AEA}' . + '\x{8AEB}\x{8AED}\x{8AEE}\x{8AEF}\x{8AF0}\x{8AF1}\x{8AF2}\x{8AF3}\x{8AF4}' . + '\x{8AF5}\x{8AF6}\x{8AF7}\x{8AF8}\x{8AF9}\x{8AFA}\x{8AFB}\x{8AFC}\x{8AFD}' . + '\x{8AFE}\x{8AFF}\x{8B00}\x{8B01}\x{8B02}\x{8B03}\x{8B04}\x{8B05}\x{8B06}' . + '\x{8B07}\x{8B08}\x{8B09}\x{8B0A}\x{8B0B}\x{8B0D}\x{8B0E}\x{8B0F}\x{8B10}' . + '\x{8B11}\x{8B12}\x{8B13}\x{8B14}\x{8B15}\x{8B16}\x{8B17}\x{8B18}\x{8B19}' . + '\x{8B1A}\x{8B1B}\x{8B1C}\x{8B1D}\x{8B1E}\x{8B1F}\x{8B20}\x{8B21}\x{8B22}' . + '\x{8B23}\x{8B24}\x{8B25}\x{8B26}\x{8B27}\x{8B28}\x{8B2A}\x{8B2B}\x{8B2C}' . + '\x{8B2D}\x{8B2E}\x{8B2F}\x{8B30}\x{8B31}\x{8B33}\x{8B34}\x{8B35}\x{8B36}' . + '\x{8B37}\x{8B39}\x{8B3A}\x{8B3B}\x{8B3C}\x{8B3D}\x{8B3E}\x{8B40}\x{8B41}' . + '\x{8B42}\x{8B43}\x{8B44}\x{8B45}\x{8B46}\x{8B47}\x{8B48}\x{8B49}\x{8B4A}' . + '\x{8B4B}\x{8B4C}\x{8B4D}\x{8B4E}\x{8B4F}\x{8B50}\x{8B51}\x{8B52}\x{8B53}' . + '\x{8B54}\x{8B55}\x{8B56}\x{8B57}\x{8B58}\x{8B59}\x{8B5A}\x{8B5B}\x{8B5C}' . + '\x{8B5D}\x{8B5E}\x{8B5F}\x{8B60}\x{8B63}\x{8B64}\x{8B65}\x{8B66}\x{8B67}' . + '\x{8B68}\x{8B6A}\x{8B6B}\x{8B6C}\x{8B6D}\x{8B6E}\x{8B6F}\x{8B70}\x{8B71}' . + '\x{8B73}\x{8B74}\x{8B76}\x{8B77}\x{8B78}\x{8B79}\x{8B7A}\x{8B7B}\x{8B7D}' . + '\x{8B7E}\x{8B7F}\x{8B80}\x{8B82}\x{8B83}\x{8B84}\x{8B85}\x{8B86}\x{8B88}' . + '\x{8B89}\x{8B8A}\x{8B8B}\x{8B8C}\x{8B8E}\x{8B90}\x{8B91}\x{8B92}\x{8B93}' . + '\x{8B94}\x{8B95}\x{8B96}\x{8B97}\x{8B98}\x{8B99}\x{8B9A}\x{8B9C}\x{8B9D}' . + '\x{8B9E}\x{8B9F}\x{8BA0}\x{8BA1}\x{8BA2}\x{8BA3}\x{8BA4}\x{8BA5}\x{8BA6}' . + '\x{8BA7}\x{8BA8}\x{8BA9}\x{8BAA}\x{8BAB}\x{8BAC}\x{8BAD}\x{8BAE}\x{8BAF}' . + '\x{8BB0}\x{8BB1}\x{8BB2}\x{8BB3}\x{8BB4}\x{8BB5}\x{8BB6}\x{8BB7}\x{8BB8}' . + '\x{8BB9}\x{8BBA}\x{8BBB}\x{8BBC}\x{8BBD}\x{8BBE}\x{8BBF}\x{8BC0}\x{8BC1}' . + '\x{8BC2}\x{8BC3}\x{8BC4}\x{8BC5}\x{8BC6}\x{8BC7}\x{8BC8}\x{8BC9}\x{8BCA}' . + '\x{8BCB}\x{8BCC}\x{8BCD}\x{8BCE}\x{8BCF}\x{8BD0}\x{8BD1}\x{8BD2}\x{8BD3}' . + '\x{8BD4}\x{8BD5}\x{8BD6}\x{8BD7}\x{8BD8}\x{8BD9}\x{8BDA}\x{8BDB}\x{8BDC}' . + '\x{8BDD}\x{8BDE}\x{8BDF}\x{8BE0}\x{8BE1}\x{8BE2}\x{8BE3}\x{8BE4}\x{8BE5}' . + '\x{8BE6}\x{8BE7}\x{8BE8}\x{8BE9}\x{8BEA}\x{8BEB}\x{8BEC}\x{8BED}\x{8BEE}' . + '\x{8BEF}\x{8BF0}\x{8BF1}\x{8BF2}\x{8BF3}\x{8BF4}\x{8BF5}\x{8BF6}\x{8BF7}' . + '\x{8BF8}\x{8BF9}\x{8BFA}\x{8BFB}\x{8BFC}\x{8BFD}\x{8BFE}\x{8BFF}\x{8C00}' . + '\x{8C01}\x{8C02}\x{8C03}\x{8C04}\x{8C05}\x{8C06}\x{8C07}\x{8C08}\x{8C09}' . + '\x{8C0A}\x{8C0B}\x{8C0C}\x{8C0D}\x{8C0E}\x{8C0F}\x{8C10}\x{8C11}\x{8C12}' . + '\x{8C13}\x{8C14}\x{8C15}\x{8C16}\x{8C17}\x{8C18}\x{8C19}\x{8C1A}\x{8C1B}' . + '\x{8C1C}\x{8C1D}\x{8C1E}\x{8C1F}\x{8C20}\x{8C21}\x{8C22}\x{8C23}\x{8C24}' . + '\x{8C25}\x{8C26}\x{8C27}\x{8C28}\x{8C29}\x{8C2A}\x{8C2B}\x{8C2C}\x{8C2D}' . + '\x{8C2E}\x{8C2F}\x{8C30}\x{8C31}\x{8C32}\x{8C33}\x{8C34}\x{8C35}\x{8C36}' . + '\x{8C37}\x{8C39}\x{8C3A}\x{8C3B}\x{8C3C}\x{8C3D}\x{8C3E}\x{8C3F}\x{8C41}' . + '\x{8C42}\x{8C43}\x{8C45}\x{8C46}\x{8C47}\x{8C48}\x{8C49}\x{8C4A}\x{8C4B}' . + '\x{8C4C}\x{8C4D}\x{8C4E}\x{8C4F}\x{8C50}\x{8C54}\x{8C55}\x{8C56}\x{8C57}' . + '\x{8C59}\x{8C5A}\x{8C5B}\x{8C5C}\x{8C5D}\x{8C5E}\x{8C5F}\x{8C60}\x{8C61}' . + '\x{8C62}\x{8C63}\x{8C64}\x{8C65}\x{8C66}\x{8C67}\x{8C68}\x{8C69}\x{8C6A}' . + '\x{8C6B}\x{8C6C}\x{8C6D}\x{8C6E}\x{8C6F}\x{8C70}\x{8C71}\x{8C72}\x{8C73}' . + '\x{8C75}\x{8C76}\x{8C77}\x{8C78}\x{8C79}\x{8C7A}\x{8C7B}\x{8C7D}\x{8C7E}' . + '\x{8C80}\x{8C81}\x{8C82}\x{8C84}\x{8C85}\x{8C86}\x{8C88}\x{8C89}\x{8C8A}' . + '\x{8C8C}\x{8C8D}\x{8C8F}\x{8C90}\x{8C91}\x{8C92}\x{8C93}\x{8C94}\x{8C95}' . + '\x{8C96}\x{8C97}\x{8C98}\x{8C99}\x{8C9A}\x{8C9C}\x{8C9D}\x{8C9E}\x{8C9F}' . + '\x{8CA0}\x{8CA1}\x{8CA2}\x{8CA3}\x{8CA4}\x{8CA5}\x{8CA7}\x{8CA8}\x{8CA9}' . + '\x{8CAA}\x{8CAB}\x{8CAC}\x{8CAD}\x{8CAE}\x{8CAF}\x{8CB0}\x{8CB1}\x{8CB2}' . + '\x{8CB3}\x{8CB4}\x{8CB5}\x{8CB6}\x{8CB7}\x{8CB8}\x{8CB9}\x{8CBA}\x{8CBB}' . + '\x{8CBC}\x{8CBD}\x{8CBE}\x{8CBF}\x{8CC0}\x{8CC1}\x{8CC2}\x{8CC3}\x{8CC4}' . + '\x{8CC5}\x{8CC6}\x{8CC7}\x{8CC8}\x{8CC9}\x{8CCA}\x{8CCC}\x{8CCE}\x{8CCF}' . + '\x{8CD0}\x{8CD1}\x{8CD2}\x{8CD3}\x{8CD4}\x{8CD5}\x{8CD7}\x{8CD9}\x{8CDA}' . + '\x{8CDB}\x{8CDC}\x{8CDD}\x{8CDE}\x{8CDF}\x{8CE0}\x{8CE1}\x{8CE2}\x{8CE3}' . + '\x{8CE4}\x{8CE5}\x{8CE6}\x{8CE7}\x{8CE8}\x{8CEA}\x{8CEB}\x{8CEC}\x{8CED}' . + '\x{8CEE}\x{8CEF}\x{8CF0}\x{8CF1}\x{8CF2}\x{8CF3}\x{8CF4}\x{8CF5}\x{8CF6}' . + '\x{8CF8}\x{8CF9}\x{8CFA}\x{8CFB}\x{8CFC}\x{8CFD}\x{8CFE}\x{8CFF}\x{8D00}' . + '\x{8D02}\x{8D03}\x{8D04}\x{8D05}\x{8D06}\x{8D07}\x{8D08}\x{8D09}\x{8D0A}' . + '\x{8D0B}\x{8D0C}\x{8D0D}\x{8D0E}\x{8D0F}\x{8D10}\x{8D13}\x{8D14}\x{8D15}' . + '\x{8D16}\x{8D17}\x{8D18}\x{8D19}\x{8D1A}\x{8D1B}\x{8D1C}\x{8D1D}\x{8D1E}' . + '\x{8D1F}\x{8D20}\x{8D21}\x{8D22}\x{8D23}\x{8D24}\x{8D25}\x{8D26}\x{8D27}' . + '\x{8D28}\x{8D29}\x{8D2A}\x{8D2B}\x{8D2C}\x{8D2D}\x{8D2E}\x{8D2F}\x{8D30}' . + '\x{8D31}\x{8D32}\x{8D33}\x{8D34}\x{8D35}\x{8D36}\x{8D37}\x{8D38}\x{8D39}' . + '\x{8D3A}\x{8D3B}\x{8D3C}\x{8D3D}\x{8D3E}\x{8D3F}\x{8D40}\x{8D41}\x{8D42}' . + '\x{8D43}\x{8D44}\x{8D45}\x{8D46}\x{8D47}\x{8D48}\x{8D49}\x{8D4A}\x{8D4B}' . + '\x{8D4C}\x{8D4D}\x{8D4E}\x{8D4F}\x{8D50}\x{8D51}\x{8D52}\x{8D53}\x{8D54}' . + '\x{8D55}\x{8D56}\x{8D57}\x{8D58}\x{8D59}\x{8D5A}\x{8D5B}\x{8D5C}\x{8D5D}' . + '\x{8D5E}\x{8D5F}\x{8D60}\x{8D61}\x{8D62}\x{8D63}\x{8D64}\x{8D65}\x{8D66}' . + '\x{8D67}\x{8D68}\x{8D69}\x{8D6A}\x{8D6B}\x{8D6C}\x{8D6D}\x{8D6E}\x{8D6F}' . + '\x{8D70}\x{8D71}\x{8D72}\x{8D73}\x{8D74}\x{8D75}\x{8D76}\x{8D77}\x{8D78}' . + '\x{8D79}\x{8D7A}\x{8D7B}\x{8D7D}\x{8D7E}\x{8D7F}\x{8D80}\x{8D81}\x{8D82}' . + '\x{8D83}\x{8D84}\x{8D85}\x{8D86}\x{8D87}\x{8D88}\x{8D89}\x{8D8A}\x{8D8B}' . + '\x{8D8C}\x{8D8D}\x{8D8E}\x{8D8F}\x{8D90}\x{8D91}\x{8D92}\x{8D93}\x{8D94}' . + '\x{8D95}\x{8D96}\x{8D97}\x{8D98}\x{8D99}\x{8D9A}\x{8D9B}\x{8D9C}\x{8D9D}' . + '\x{8D9E}\x{8D9F}\x{8DA0}\x{8DA1}\x{8DA2}\x{8DA3}\x{8DA4}\x{8DA5}\x{8DA7}' . + '\x{8DA8}\x{8DA9}\x{8DAA}\x{8DAB}\x{8DAC}\x{8DAD}\x{8DAE}\x{8DAF}\x{8DB0}' . + '\x{8DB1}\x{8DB2}\x{8DB3}\x{8DB4}\x{8DB5}\x{8DB6}\x{8DB7}\x{8DB8}\x{8DB9}' . + '\x{8DBA}\x{8DBB}\x{8DBC}\x{8DBD}\x{8DBE}\x{8DBF}\x{8DC1}\x{8DC2}\x{8DC3}' . + '\x{8DC4}\x{8DC5}\x{8DC6}\x{8DC7}\x{8DC8}\x{8DC9}\x{8DCA}\x{8DCB}\x{8DCC}' . + '\x{8DCD}\x{8DCE}\x{8DCF}\x{8DD0}\x{8DD1}\x{8DD2}\x{8DD3}\x{8DD4}\x{8DD5}' . + '\x{8DD6}\x{8DD7}\x{8DD8}\x{8DD9}\x{8DDA}\x{8DDB}\x{8DDC}\x{8DDD}\x{8DDE}' . + '\x{8DDF}\x{8DE0}\x{8DE1}\x{8DE2}\x{8DE3}\x{8DE4}\x{8DE6}\x{8DE7}\x{8DE8}' . + '\x{8DE9}\x{8DEA}\x{8DEB}\x{8DEC}\x{8DED}\x{8DEE}\x{8DEF}\x{8DF0}\x{8DF1}' . + '\x{8DF2}\x{8DF3}\x{8DF4}\x{8DF5}\x{8DF6}\x{8DF7}\x{8DF8}\x{8DF9}\x{8DFA}' . + '\x{8DFB}\x{8DFC}\x{8DFD}\x{8DFE}\x{8DFF}\x{8E00}\x{8E02}\x{8E03}\x{8E04}' . + '\x{8E05}\x{8E06}\x{8E07}\x{8E08}\x{8E09}\x{8E0A}\x{8E0C}\x{8E0D}\x{8E0E}' . + '\x{8E0F}\x{8E10}\x{8E11}\x{8E12}\x{8E13}\x{8E14}\x{8E15}\x{8E16}\x{8E17}' . + '\x{8E18}\x{8E19}\x{8E1A}\x{8E1B}\x{8E1C}\x{8E1D}\x{8E1E}\x{8E1F}\x{8E20}' . + '\x{8E21}\x{8E22}\x{8E23}\x{8E24}\x{8E25}\x{8E26}\x{8E27}\x{8E28}\x{8E29}' . + '\x{8E2A}\x{8E2B}\x{8E2C}\x{8E2D}\x{8E2E}\x{8E2F}\x{8E30}\x{8E31}\x{8E33}' . + '\x{8E34}\x{8E35}\x{8E36}\x{8E37}\x{8E38}\x{8E39}\x{8E3A}\x{8E3B}\x{8E3C}' . + '\x{8E3D}\x{8E3E}\x{8E3F}\x{8E40}\x{8E41}\x{8E42}\x{8E43}\x{8E44}\x{8E45}' . + '\x{8E47}\x{8E48}\x{8E49}\x{8E4A}\x{8E4B}\x{8E4C}\x{8E4D}\x{8E4E}\x{8E50}' . + '\x{8E51}\x{8E52}\x{8E53}\x{8E54}\x{8E55}\x{8E56}\x{8E57}\x{8E58}\x{8E59}' . + '\x{8E5A}\x{8E5B}\x{8E5C}\x{8E5D}\x{8E5E}\x{8E5F}\x{8E60}\x{8E61}\x{8E62}' . + '\x{8E63}\x{8E64}\x{8E65}\x{8E66}\x{8E67}\x{8E68}\x{8E69}\x{8E6A}\x{8E6B}' . + '\x{8E6C}\x{8E6D}\x{8E6F}\x{8E70}\x{8E71}\x{8E72}\x{8E73}\x{8E74}\x{8E76}' . + '\x{8E78}\x{8E7A}\x{8E7B}\x{8E7C}\x{8E7D}\x{8E7E}\x{8E7F}\x{8E80}\x{8E81}' . + '\x{8E82}\x{8E83}\x{8E84}\x{8E85}\x{8E86}\x{8E87}\x{8E88}\x{8E89}\x{8E8A}' . + '\x{8E8B}\x{8E8C}\x{8E8D}\x{8E8E}\x{8E8F}\x{8E90}\x{8E91}\x{8E92}\x{8E93}' . + '\x{8E94}\x{8E95}\x{8E96}\x{8E97}\x{8E98}\x{8E9A}\x{8E9C}\x{8E9D}\x{8E9E}' . + '\x{8E9F}\x{8EA0}\x{8EA1}\x{8EA3}\x{8EA4}\x{8EA5}\x{8EA6}\x{8EA7}\x{8EA8}' . + '\x{8EA9}\x{8EAA}\x{8EAB}\x{8EAC}\x{8EAD}\x{8EAE}\x{8EAF}\x{8EB0}\x{8EB1}' . + '\x{8EB2}\x{8EB4}\x{8EB5}\x{8EB8}\x{8EB9}\x{8EBA}\x{8EBB}\x{8EBC}\x{8EBD}' . + '\x{8EBE}\x{8EBF}\x{8EC0}\x{8EC2}\x{8EC3}\x{8EC5}\x{8EC6}\x{8EC7}\x{8EC8}' . + '\x{8EC9}\x{8ECA}\x{8ECB}\x{8ECC}\x{8ECD}\x{8ECE}\x{8ECF}\x{8ED0}\x{8ED1}' . + '\x{8ED2}\x{8ED3}\x{8ED4}\x{8ED5}\x{8ED6}\x{8ED7}\x{8ED8}\x{8EDA}\x{8EDB}' . + '\x{8EDC}\x{8EDD}\x{8EDE}\x{8EDF}\x{8EE0}\x{8EE1}\x{8EE4}\x{8EE5}\x{8EE6}' . + '\x{8EE7}\x{8EE8}\x{8EE9}\x{8EEA}\x{8EEB}\x{8EEC}\x{8EED}\x{8EEE}\x{8EEF}' . + '\x{8EF1}\x{8EF2}\x{8EF3}\x{8EF4}\x{8EF5}\x{8EF6}\x{8EF7}\x{8EF8}\x{8EF9}' . + '\x{8EFA}\x{8EFB}\x{8EFC}\x{8EFD}\x{8EFE}\x{8EFF}\x{8F00}\x{8F01}\x{8F02}' . + '\x{8F03}\x{8F04}\x{8F05}\x{8F06}\x{8F07}\x{8F08}\x{8F09}\x{8F0A}\x{8F0B}' . + '\x{8F0D}\x{8F0E}\x{8F10}\x{8F11}\x{8F12}\x{8F13}\x{8F14}\x{8F15}\x{8F16}' . + '\x{8F17}\x{8F18}\x{8F1A}\x{8F1B}\x{8F1C}\x{8F1D}\x{8F1E}\x{8F1F}\x{8F20}' . + '\x{8F21}\x{8F22}\x{8F23}\x{8F24}\x{8F25}\x{8F26}\x{8F27}\x{8F28}\x{8F29}' . + '\x{8F2A}\x{8F2B}\x{8F2C}\x{8F2E}\x{8F2F}\x{8F30}\x{8F31}\x{8F32}\x{8F33}' . + '\x{8F34}\x{8F35}\x{8F36}\x{8F37}\x{8F38}\x{8F39}\x{8F3B}\x{8F3C}\x{8F3D}' . + '\x{8F3E}\x{8F3F}\x{8F40}\x{8F42}\x{8F43}\x{8F44}\x{8F45}\x{8F46}\x{8F47}' . + '\x{8F48}\x{8F49}\x{8F4A}\x{8F4B}\x{8F4C}\x{8F4D}\x{8F4E}\x{8F4F}\x{8F50}' . + '\x{8F51}\x{8F52}\x{8F53}\x{8F54}\x{8F55}\x{8F56}\x{8F57}\x{8F58}\x{8F59}' . + '\x{8F5A}\x{8F5B}\x{8F5D}\x{8F5E}\x{8F5F}\x{8F60}\x{8F61}\x{8F62}\x{8F63}' . + '\x{8F64}\x{8F65}\x{8F66}\x{8F67}\x{8F68}\x{8F69}\x{8F6A}\x{8F6B}\x{8F6C}' . + '\x{8F6D}\x{8F6E}\x{8F6F}\x{8F70}\x{8F71}\x{8F72}\x{8F73}\x{8F74}\x{8F75}' . + '\x{8F76}\x{8F77}\x{8F78}\x{8F79}\x{8F7A}\x{8F7B}\x{8F7C}\x{8F7D}\x{8F7E}' . + '\x{8F7F}\x{8F80}\x{8F81}\x{8F82}\x{8F83}\x{8F84}\x{8F85}\x{8F86}\x{8F87}' . + '\x{8F88}\x{8F89}\x{8F8A}\x{8F8B}\x{8F8C}\x{8F8D}\x{8F8E}\x{8F8F}\x{8F90}' . + '\x{8F91}\x{8F92}\x{8F93}\x{8F94}\x{8F95}\x{8F96}\x{8F97}\x{8F98}\x{8F99}' . + '\x{8F9A}\x{8F9B}\x{8F9C}\x{8F9E}\x{8F9F}\x{8FA0}\x{8FA1}\x{8FA2}\x{8FA3}' . + '\x{8FA5}\x{8FA6}\x{8FA7}\x{8FA8}\x{8FA9}\x{8FAA}\x{8FAB}\x{8FAC}\x{8FAD}' . + '\x{8FAE}\x{8FAF}\x{8FB0}\x{8FB1}\x{8FB2}\x{8FB4}\x{8FB5}\x{8FB6}\x{8FB7}' . + '\x{8FB8}\x{8FB9}\x{8FBB}\x{8FBC}\x{8FBD}\x{8FBE}\x{8FBF}\x{8FC0}\x{8FC1}' . + '\x{8FC2}\x{8FC4}\x{8FC5}\x{8FC6}\x{8FC7}\x{8FC8}\x{8FC9}\x{8FCB}\x{8FCC}' . + '\x{8FCD}\x{8FCE}\x{8FCF}\x{8FD0}\x{8FD1}\x{8FD2}\x{8FD3}\x{8FD4}\x{8FD5}' . + '\x{8FD6}\x{8FD7}\x{8FD8}\x{8FD9}\x{8FDA}\x{8FDB}\x{8FDC}\x{8FDD}\x{8FDE}' . + '\x{8FDF}\x{8FE0}\x{8FE1}\x{8FE2}\x{8FE3}\x{8FE4}\x{8FE5}\x{8FE6}\x{8FE8}' . + '\x{8FE9}\x{8FEA}\x{8FEB}\x{8FEC}\x{8FED}\x{8FEE}\x{8FEF}\x{8FF0}\x{8FF1}' . + '\x{8FF2}\x{8FF3}\x{8FF4}\x{8FF5}\x{8FF6}\x{8FF7}\x{8FF8}\x{8FF9}\x{8FFA}' . + '\x{8FFB}\x{8FFC}\x{8FFD}\x{8FFE}\x{8FFF}\x{9000}\x{9001}\x{9002}\x{9003}' . + '\x{9004}\x{9005}\x{9006}\x{9007}\x{9008}\x{9009}\x{900A}\x{900B}\x{900C}' . + '\x{900D}\x{900F}\x{9010}\x{9011}\x{9012}\x{9013}\x{9014}\x{9015}\x{9016}' . + '\x{9017}\x{9018}\x{9019}\x{901A}\x{901B}\x{901C}\x{901D}\x{901E}\x{901F}' . + '\x{9020}\x{9021}\x{9022}\x{9023}\x{9024}\x{9025}\x{9026}\x{9027}\x{9028}' . + '\x{9029}\x{902B}\x{902D}\x{902E}\x{902F}\x{9030}\x{9031}\x{9032}\x{9033}' . + '\x{9034}\x{9035}\x{9036}\x{9038}\x{903A}\x{903B}\x{903C}\x{903D}\x{903E}' . + '\x{903F}\x{9041}\x{9042}\x{9043}\x{9044}\x{9045}\x{9047}\x{9048}\x{9049}' . + '\x{904A}\x{904B}\x{904C}\x{904D}\x{904E}\x{904F}\x{9050}\x{9051}\x{9052}' . + '\x{9053}\x{9054}\x{9055}\x{9056}\x{9057}\x{9058}\x{9059}\x{905A}\x{905B}' . + '\x{905C}\x{905D}\x{905E}\x{905F}\x{9060}\x{9061}\x{9062}\x{9063}\x{9064}' . + '\x{9065}\x{9066}\x{9067}\x{9068}\x{9069}\x{906A}\x{906B}\x{906C}\x{906D}' . + '\x{906E}\x{906F}\x{9070}\x{9071}\x{9072}\x{9073}\x{9074}\x{9075}\x{9076}' . + '\x{9077}\x{9078}\x{9079}\x{907A}\x{907B}\x{907C}\x{907D}\x{907E}\x{907F}' . + '\x{9080}\x{9081}\x{9082}\x{9083}\x{9084}\x{9085}\x{9086}\x{9087}\x{9088}' . + '\x{9089}\x{908A}\x{908B}\x{908C}\x{908D}\x{908E}\x{908F}\x{9090}\x{9091}' . + '\x{9092}\x{9093}\x{9094}\x{9095}\x{9096}\x{9097}\x{9098}\x{9099}\x{909A}' . + '\x{909B}\x{909C}\x{909D}\x{909E}\x{909F}\x{90A0}\x{90A1}\x{90A2}\x{90A3}' . + '\x{90A4}\x{90A5}\x{90A6}\x{90A7}\x{90A8}\x{90A9}\x{90AA}\x{90AC}\x{90AD}' . + '\x{90AE}\x{90AF}\x{90B0}\x{90B1}\x{90B2}\x{90B3}\x{90B4}\x{90B5}\x{90B6}' . + '\x{90B7}\x{90B8}\x{90B9}\x{90BA}\x{90BB}\x{90BC}\x{90BD}\x{90BE}\x{90BF}' . + '\x{90C0}\x{90C1}\x{90C2}\x{90C3}\x{90C4}\x{90C5}\x{90C6}\x{90C7}\x{90C8}' . + '\x{90C9}\x{90CA}\x{90CB}\x{90CE}\x{90CF}\x{90D0}\x{90D1}\x{90D3}\x{90D4}' . + '\x{90D5}\x{90D6}\x{90D7}\x{90D8}\x{90D9}\x{90DA}\x{90DB}\x{90DC}\x{90DD}' . + '\x{90DE}\x{90DF}\x{90E0}\x{90E1}\x{90E2}\x{90E3}\x{90E4}\x{90E5}\x{90E6}' . + '\x{90E7}\x{90E8}\x{90E9}\x{90EA}\x{90EB}\x{90EC}\x{90ED}\x{90EE}\x{90EF}' . + '\x{90F0}\x{90F1}\x{90F2}\x{90F3}\x{90F4}\x{90F5}\x{90F7}\x{90F8}\x{90F9}' . + '\x{90FA}\x{90FB}\x{90FC}\x{90FD}\x{90FE}\x{90FF}\x{9100}\x{9101}\x{9102}' . + '\x{9103}\x{9104}\x{9105}\x{9106}\x{9107}\x{9108}\x{9109}\x{910B}\x{910C}' . + '\x{910D}\x{910E}\x{910F}\x{9110}\x{9111}\x{9112}\x{9113}\x{9114}\x{9115}' . + '\x{9116}\x{9117}\x{9118}\x{9119}\x{911A}\x{911B}\x{911C}\x{911D}\x{911E}' . + '\x{911F}\x{9120}\x{9121}\x{9122}\x{9123}\x{9124}\x{9125}\x{9126}\x{9127}' . + '\x{9128}\x{9129}\x{912A}\x{912B}\x{912C}\x{912D}\x{912E}\x{912F}\x{9130}' . + '\x{9131}\x{9132}\x{9133}\x{9134}\x{9135}\x{9136}\x{9137}\x{9138}\x{9139}' . + '\x{913A}\x{913B}\x{913E}\x{913F}\x{9140}\x{9141}\x{9142}\x{9143}\x{9144}' . + '\x{9145}\x{9146}\x{9147}\x{9148}\x{9149}\x{914A}\x{914B}\x{914C}\x{914D}' . + '\x{914E}\x{914F}\x{9150}\x{9151}\x{9152}\x{9153}\x{9154}\x{9155}\x{9156}' . + '\x{9157}\x{9158}\x{915A}\x{915B}\x{915C}\x{915D}\x{915E}\x{915F}\x{9160}' . + '\x{9161}\x{9162}\x{9163}\x{9164}\x{9165}\x{9166}\x{9167}\x{9168}\x{9169}' . + '\x{916A}\x{916B}\x{916C}\x{916D}\x{916E}\x{916F}\x{9170}\x{9171}\x{9172}' . + '\x{9173}\x{9174}\x{9175}\x{9176}\x{9177}\x{9178}\x{9179}\x{917A}\x{917C}' . + '\x{917D}\x{917E}\x{917F}\x{9180}\x{9181}\x{9182}\x{9183}\x{9184}\x{9185}' . + '\x{9186}\x{9187}\x{9188}\x{9189}\x{918A}\x{918B}\x{918C}\x{918D}\x{918E}' . + '\x{918F}\x{9190}\x{9191}\x{9192}\x{9193}\x{9194}\x{9196}\x{9199}\x{919A}' . + '\x{919B}\x{919C}\x{919D}\x{919E}\x{919F}\x{91A0}\x{91A1}\x{91A2}\x{91A3}' . + '\x{91A5}\x{91A6}\x{91A7}\x{91A8}\x{91AA}\x{91AB}\x{91AC}\x{91AD}\x{91AE}' . + '\x{91AF}\x{91B0}\x{91B1}\x{91B2}\x{91B3}\x{91B4}\x{91B5}\x{91B6}\x{91B7}' . + '\x{91B9}\x{91BA}\x{91BB}\x{91BC}\x{91BD}\x{91BE}\x{91C0}\x{91C1}\x{91C2}' . + '\x{91C3}\x{91C5}\x{91C6}\x{91C7}\x{91C9}\x{91CA}\x{91CB}\x{91CC}\x{91CD}' . + '\x{91CE}\x{91CF}\x{91D0}\x{91D1}\x{91D2}\x{91D3}\x{91D4}\x{91D5}\x{91D7}' . + '\x{91D8}\x{91D9}\x{91DA}\x{91DB}\x{91DC}\x{91DD}\x{91DE}\x{91DF}\x{91E2}' . + '\x{91E3}\x{91E4}\x{91E5}\x{91E6}\x{91E7}\x{91E8}\x{91E9}\x{91EA}\x{91EB}' . + '\x{91EC}\x{91ED}\x{91EE}\x{91F0}\x{91F1}\x{91F2}\x{91F3}\x{91F4}\x{91F5}' . + '\x{91F7}\x{91F8}\x{91F9}\x{91FA}\x{91FB}\x{91FD}\x{91FE}\x{91FF}\x{9200}' . + '\x{9201}\x{9202}\x{9203}\x{9204}\x{9205}\x{9206}\x{9207}\x{9208}\x{9209}' . + '\x{920A}\x{920B}\x{920C}\x{920D}\x{920E}\x{920F}\x{9210}\x{9211}\x{9212}' . + '\x{9214}\x{9215}\x{9216}\x{9217}\x{9218}\x{9219}\x{921A}\x{921B}\x{921C}' . + '\x{921D}\x{921E}\x{9220}\x{9221}\x{9223}\x{9224}\x{9225}\x{9226}\x{9227}' . + '\x{9228}\x{9229}\x{922A}\x{922B}\x{922D}\x{922E}\x{922F}\x{9230}\x{9231}' . + '\x{9232}\x{9233}\x{9234}\x{9235}\x{9236}\x{9237}\x{9238}\x{9239}\x{923A}' . + '\x{923B}\x{923C}\x{923D}\x{923E}\x{923F}\x{9240}\x{9241}\x{9242}\x{9245}' . + '\x{9246}\x{9247}\x{9248}\x{9249}\x{924A}\x{924B}\x{924C}\x{924D}\x{924E}' . + '\x{924F}\x{9250}\x{9251}\x{9252}\x{9253}\x{9254}\x{9255}\x{9256}\x{9257}' . + '\x{9258}\x{9259}\x{925A}\x{925B}\x{925C}\x{925D}\x{925E}\x{925F}\x{9260}' . + '\x{9261}\x{9262}\x{9263}\x{9264}\x{9265}\x{9266}\x{9267}\x{9268}\x{926B}' . + '\x{926C}\x{926D}\x{926E}\x{926F}\x{9270}\x{9272}\x{9273}\x{9274}\x{9275}' . + '\x{9276}\x{9277}\x{9278}\x{9279}\x{927A}\x{927B}\x{927C}\x{927D}\x{927E}' . + '\x{927F}\x{9280}\x{9282}\x{9283}\x{9285}\x{9286}\x{9287}\x{9288}\x{9289}' . + '\x{928A}\x{928B}\x{928C}\x{928D}\x{928E}\x{928F}\x{9290}\x{9291}\x{9292}' . + '\x{9293}\x{9294}\x{9295}\x{9296}\x{9297}\x{9298}\x{9299}\x{929A}\x{929B}' . + '\x{929C}\x{929D}\x{929F}\x{92A0}\x{92A1}\x{92A2}\x{92A3}\x{92A4}\x{92A5}' . + '\x{92A6}\x{92A7}\x{92A8}\x{92A9}\x{92AA}\x{92AB}\x{92AC}\x{92AD}\x{92AE}' . + '\x{92AF}\x{92B0}\x{92B1}\x{92B2}\x{92B3}\x{92B4}\x{92B5}\x{92B6}\x{92B7}' . + '\x{92B8}\x{92B9}\x{92BA}\x{92BB}\x{92BC}\x{92BE}\x{92BF}\x{92C0}\x{92C1}' . + '\x{92C2}\x{92C3}\x{92C4}\x{92C5}\x{92C6}\x{92C7}\x{92C8}\x{92C9}\x{92CA}' . + '\x{92CB}\x{92CC}\x{92CD}\x{92CE}\x{92CF}\x{92D0}\x{92D1}\x{92D2}\x{92D3}' . + '\x{92D5}\x{92D6}\x{92D7}\x{92D8}\x{92D9}\x{92DA}\x{92DC}\x{92DD}\x{92DE}' . + '\x{92DF}\x{92E0}\x{92E1}\x{92E3}\x{92E4}\x{92E5}\x{92E6}\x{92E7}\x{92E8}' . + '\x{92E9}\x{92EA}\x{92EB}\x{92EC}\x{92ED}\x{92EE}\x{92EF}\x{92F0}\x{92F1}' . + '\x{92F2}\x{92F3}\x{92F4}\x{92F5}\x{92F6}\x{92F7}\x{92F8}\x{92F9}\x{92FA}' . + '\x{92FB}\x{92FC}\x{92FD}\x{92FE}\x{92FF}\x{9300}\x{9301}\x{9302}\x{9303}' . + '\x{9304}\x{9305}\x{9306}\x{9307}\x{9308}\x{9309}\x{930A}\x{930B}\x{930C}' . + '\x{930D}\x{930E}\x{930F}\x{9310}\x{9311}\x{9312}\x{9313}\x{9314}\x{9315}' . + '\x{9316}\x{9317}\x{9318}\x{9319}\x{931A}\x{931B}\x{931D}\x{931E}\x{931F}' . + '\x{9320}\x{9321}\x{9322}\x{9323}\x{9324}\x{9325}\x{9326}\x{9327}\x{9328}' . + '\x{9329}\x{932A}\x{932B}\x{932D}\x{932E}\x{932F}\x{9332}\x{9333}\x{9334}' . + '\x{9335}\x{9336}\x{9337}\x{9338}\x{9339}\x{933A}\x{933B}\x{933C}\x{933D}' . + '\x{933E}\x{933F}\x{9340}\x{9341}\x{9342}\x{9343}\x{9344}\x{9345}\x{9346}' . + '\x{9347}\x{9348}\x{9349}\x{934A}\x{934B}\x{934C}\x{934D}\x{934E}\x{934F}' . + '\x{9350}\x{9351}\x{9352}\x{9353}\x{9354}\x{9355}\x{9356}\x{9357}\x{9358}' . + '\x{9359}\x{935A}\x{935B}\x{935C}\x{935D}\x{935E}\x{935F}\x{9360}\x{9361}' . + '\x{9363}\x{9364}\x{9365}\x{9366}\x{9367}\x{9369}\x{936A}\x{936C}\x{936D}' . + '\x{936E}\x{9370}\x{9371}\x{9372}\x{9374}\x{9375}\x{9376}\x{9377}\x{9379}' . + '\x{937A}\x{937B}\x{937C}\x{937D}\x{937E}\x{9380}\x{9382}\x{9383}\x{9384}' . + '\x{9385}\x{9386}\x{9387}\x{9388}\x{9389}\x{938A}\x{938C}\x{938D}\x{938E}' . + '\x{938F}\x{9390}\x{9391}\x{9392}\x{9393}\x{9394}\x{9395}\x{9396}\x{9397}' . + '\x{9398}\x{9399}\x{939A}\x{939B}\x{939D}\x{939E}\x{939F}\x{93A1}\x{93A2}' . + '\x{93A3}\x{93A4}\x{93A5}\x{93A6}\x{93A7}\x{93A8}\x{93A9}\x{93AA}\x{93AC}' . + '\x{93AD}\x{93AE}\x{93AF}\x{93B0}\x{93B1}\x{93B2}\x{93B3}\x{93B4}\x{93B5}' . + '\x{93B6}\x{93B7}\x{93B8}\x{93B9}\x{93BA}\x{93BC}\x{93BD}\x{93BE}\x{93BF}' . + '\x{93C0}\x{93C1}\x{93C2}\x{93C3}\x{93C4}\x{93C5}\x{93C6}\x{93C7}\x{93C8}' . + '\x{93C9}\x{93CA}\x{93CB}\x{93CC}\x{93CD}\x{93CE}\x{93CF}\x{93D0}\x{93D1}' . + '\x{93D2}\x{93D3}\x{93D4}\x{93D5}\x{93D6}\x{93D7}\x{93D8}\x{93D9}\x{93DA}' . + '\x{93DB}\x{93DC}\x{93DD}\x{93DE}\x{93DF}\x{93E1}\x{93E2}\x{93E3}\x{93E4}' . + '\x{93E6}\x{93E7}\x{93E8}\x{93E9}\x{93EA}\x{93EB}\x{93EC}\x{93ED}\x{93EE}' . + '\x{93EF}\x{93F0}\x{93F1}\x{93F2}\x{93F4}\x{93F5}\x{93F6}\x{93F7}\x{93F8}' . + '\x{93F9}\x{93FA}\x{93FB}\x{93FC}\x{93FD}\x{93FE}\x{93FF}\x{9400}\x{9401}' . + '\x{9403}\x{9404}\x{9405}\x{9406}\x{9407}\x{9408}\x{9409}\x{940A}\x{940B}' . + '\x{940C}\x{940D}\x{940E}\x{940F}\x{9410}\x{9411}\x{9412}\x{9413}\x{9414}' . + '\x{9415}\x{9416}\x{9418}\x{9419}\x{941B}\x{941D}\x{9420}\x{9422}\x{9423}' . + '\x{9425}\x{9426}\x{9427}\x{9428}\x{9429}\x{942A}\x{942B}\x{942C}\x{942D}' . + '\x{942E}\x{942F}\x{9430}\x{9431}\x{9432}\x{9433}\x{9434}\x{9435}\x{9436}' . + '\x{9437}\x{9438}\x{9439}\x{943A}\x{943B}\x{943C}\x{943D}\x{943E}\x{943F}' . + '\x{9440}\x{9441}\x{9442}\x{9444}\x{9445}\x{9446}\x{9447}\x{9448}\x{9449}' . + '\x{944A}\x{944B}\x{944C}\x{944D}\x{944F}\x{9450}\x{9451}\x{9452}\x{9453}' . + '\x{9454}\x{9455}\x{9456}\x{9457}\x{9458}\x{9459}\x{945B}\x{945C}\x{945D}' . + '\x{945E}\x{945F}\x{9460}\x{9461}\x{9462}\x{9463}\x{9464}\x{9465}\x{9466}' . + '\x{9467}\x{9468}\x{9469}\x{946A}\x{946B}\x{946D}\x{946E}\x{946F}\x{9470}' . + '\x{9471}\x{9472}\x{9473}\x{9474}\x{9475}\x{9476}\x{9477}\x{9478}\x{9479}' . + '\x{947A}\x{947C}\x{947D}\x{947E}\x{947F}\x{9480}\x{9481}\x{9482}\x{9483}' . + '\x{9484}\x{9485}\x{9486}\x{9487}\x{9488}\x{9489}\x{948A}\x{948B}\x{948C}' . + '\x{948D}\x{948E}\x{948F}\x{9490}\x{9491}\x{9492}\x{9493}\x{9494}\x{9495}' . + '\x{9496}\x{9497}\x{9498}\x{9499}\x{949A}\x{949B}\x{949C}\x{949D}\x{949E}' . + '\x{949F}\x{94A0}\x{94A1}\x{94A2}\x{94A3}\x{94A4}\x{94A5}\x{94A6}\x{94A7}' . + '\x{94A8}\x{94A9}\x{94AA}\x{94AB}\x{94AC}\x{94AD}\x{94AE}\x{94AF}\x{94B0}' . + '\x{94B1}\x{94B2}\x{94B3}\x{94B4}\x{94B5}\x{94B6}\x{94B7}\x{94B8}\x{94B9}' . + '\x{94BA}\x{94BB}\x{94BC}\x{94BD}\x{94BE}\x{94BF}\x{94C0}\x{94C1}\x{94C2}' . + '\x{94C3}\x{94C4}\x{94C5}\x{94C6}\x{94C7}\x{94C8}\x{94C9}\x{94CA}\x{94CB}' . + '\x{94CC}\x{94CD}\x{94CE}\x{94CF}\x{94D0}\x{94D1}\x{94D2}\x{94D3}\x{94D4}' . + '\x{94D5}\x{94D6}\x{94D7}\x{94D8}\x{94D9}\x{94DA}\x{94DB}\x{94DC}\x{94DD}' . + '\x{94DE}\x{94DF}\x{94E0}\x{94E1}\x{94E2}\x{94E3}\x{94E4}\x{94E5}\x{94E6}' . + '\x{94E7}\x{94E8}\x{94E9}\x{94EA}\x{94EB}\x{94EC}\x{94ED}\x{94EE}\x{94EF}' . + '\x{94F0}\x{94F1}\x{94F2}\x{94F3}\x{94F4}\x{94F5}\x{94F6}\x{94F7}\x{94F8}' . + '\x{94F9}\x{94FA}\x{94FB}\x{94FC}\x{94FD}\x{94FE}\x{94FF}\x{9500}\x{9501}' . + '\x{9502}\x{9503}\x{9504}\x{9505}\x{9506}\x{9507}\x{9508}\x{9509}\x{950A}' . + '\x{950B}\x{950C}\x{950D}\x{950E}\x{950F}\x{9510}\x{9511}\x{9512}\x{9513}' . + '\x{9514}\x{9515}\x{9516}\x{9517}\x{9518}\x{9519}\x{951A}\x{951B}\x{951C}' . + '\x{951D}\x{951E}\x{951F}\x{9520}\x{9521}\x{9522}\x{9523}\x{9524}\x{9525}' . + '\x{9526}\x{9527}\x{9528}\x{9529}\x{952A}\x{952B}\x{952C}\x{952D}\x{952E}' . + '\x{952F}\x{9530}\x{9531}\x{9532}\x{9533}\x{9534}\x{9535}\x{9536}\x{9537}' . + '\x{9538}\x{9539}\x{953A}\x{953B}\x{953C}\x{953D}\x{953E}\x{953F}\x{9540}' . + '\x{9541}\x{9542}\x{9543}\x{9544}\x{9545}\x{9546}\x{9547}\x{9548}\x{9549}' . + '\x{954A}\x{954B}\x{954C}\x{954D}\x{954E}\x{954F}\x{9550}\x{9551}\x{9552}' . + '\x{9553}\x{9554}\x{9555}\x{9556}\x{9557}\x{9558}\x{9559}\x{955A}\x{955B}' . + '\x{955C}\x{955D}\x{955E}\x{955F}\x{9560}\x{9561}\x{9562}\x{9563}\x{9564}' . + '\x{9565}\x{9566}\x{9567}\x{9568}\x{9569}\x{956A}\x{956B}\x{956C}\x{956D}' . + '\x{956E}\x{956F}\x{9570}\x{9571}\x{9572}\x{9573}\x{9574}\x{9575}\x{9576}' . + '\x{9577}\x{957A}\x{957B}\x{957C}\x{957D}\x{957F}\x{9580}\x{9581}\x{9582}' . + '\x{9583}\x{9584}\x{9586}\x{9587}\x{9588}\x{9589}\x{958A}\x{958B}\x{958C}' . + '\x{958D}\x{958E}\x{958F}\x{9590}\x{9591}\x{9592}\x{9593}\x{9594}\x{9595}' . + '\x{9596}\x{9598}\x{9599}\x{959A}\x{959B}\x{959C}\x{959D}\x{959E}\x{959F}' . + '\x{95A1}\x{95A2}\x{95A3}\x{95A4}\x{95A5}\x{95A6}\x{95A7}\x{95A8}\x{95A9}' . + '\x{95AA}\x{95AB}\x{95AC}\x{95AD}\x{95AE}\x{95AF}\x{95B0}\x{95B1}\x{95B2}' . + '\x{95B5}\x{95B6}\x{95B7}\x{95B9}\x{95BA}\x{95BB}\x{95BC}\x{95BD}\x{95BE}' . + '\x{95BF}\x{95C0}\x{95C2}\x{95C3}\x{95C4}\x{95C5}\x{95C6}\x{95C7}\x{95C8}' . + '\x{95C9}\x{95CA}\x{95CB}\x{95CC}\x{95CD}\x{95CE}\x{95CF}\x{95D0}\x{95D1}' . + '\x{95D2}\x{95D3}\x{95D4}\x{95D5}\x{95D6}\x{95D7}\x{95D8}\x{95DA}\x{95DB}' . + '\x{95DC}\x{95DE}\x{95DF}\x{95E0}\x{95E1}\x{95E2}\x{95E3}\x{95E4}\x{95E5}' . + '\x{95E6}\x{95E7}\x{95E8}\x{95E9}\x{95EA}\x{95EB}\x{95EC}\x{95ED}\x{95EE}' . + '\x{95EF}\x{95F0}\x{95F1}\x{95F2}\x{95F3}\x{95F4}\x{95F5}\x{95F6}\x{95F7}' . + '\x{95F8}\x{95F9}\x{95FA}\x{95FB}\x{95FC}\x{95FD}\x{95FE}\x{95FF}\x{9600}' . + '\x{9601}\x{9602}\x{9603}\x{9604}\x{9605}\x{9606}\x{9607}\x{9608}\x{9609}' . + '\x{960A}\x{960B}\x{960C}\x{960D}\x{960E}\x{960F}\x{9610}\x{9611}\x{9612}' . + '\x{9613}\x{9614}\x{9615}\x{9616}\x{9617}\x{9618}\x{9619}\x{961A}\x{961B}' . + '\x{961C}\x{961D}\x{961E}\x{961F}\x{9620}\x{9621}\x{9622}\x{9623}\x{9624}' . + '\x{9627}\x{9628}\x{962A}\x{962B}\x{962C}\x{962D}\x{962E}\x{962F}\x{9630}' . + '\x{9631}\x{9632}\x{9633}\x{9634}\x{9635}\x{9636}\x{9637}\x{9638}\x{9639}' . + '\x{963A}\x{963B}\x{963C}\x{963D}\x{963F}\x{9640}\x{9641}\x{9642}\x{9643}' . + '\x{9644}\x{9645}\x{9646}\x{9647}\x{9648}\x{9649}\x{964A}\x{964B}\x{964C}' . + '\x{964D}\x{964E}\x{964F}\x{9650}\x{9651}\x{9652}\x{9653}\x{9654}\x{9655}' . + '\x{9658}\x{9659}\x{965A}\x{965B}\x{965C}\x{965D}\x{965E}\x{965F}\x{9660}' . + '\x{9661}\x{9662}\x{9663}\x{9664}\x{9666}\x{9667}\x{9668}\x{9669}\x{966A}' . + '\x{966B}\x{966C}\x{966D}\x{966E}\x{966F}\x{9670}\x{9671}\x{9672}\x{9673}' . + '\x{9674}\x{9675}\x{9676}\x{9677}\x{9678}\x{967C}\x{967D}\x{967E}\x{9680}' . + '\x{9683}\x{9684}\x{9685}\x{9686}\x{9687}\x{9688}\x{9689}\x{968A}\x{968B}' . + '\x{968D}\x{968E}\x{968F}\x{9690}\x{9691}\x{9692}\x{9693}\x{9694}\x{9695}' . + '\x{9697}\x{9698}\x{9699}\x{969B}\x{969C}\x{969E}\x{96A0}\x{96A1}\x{96A2}' . + '\x{96A3}\x{96A4}\x{96A5}\x{96A6}\x{96A7}\x{96A8}\x{96A9}\x{96AA}\x{96AC}' . + '\x{96AD}\x{96AE}\x{96B0}\x{96B1}\x{96B3}\x{96B4}\x{96B6}\x{96B7}\x{96B8}' . + '\x{96B9}\x{96BA}\x{96BB}\x{96BC}\x{96BD}\x{96BE}\x{96BF}\x{96C0}\x{96C1}' . + '\x{96C2}\x{96C3}\x{96C4}\x{96C5}\x{96C6}\x{96C7}\x{96C8}\x{96C9}\x{96CA}' . + '\x{96CB}\x{96CC}\x{96CD}\x{96CE}\x{96CF}\x{96D0}\x{96D1}\x{96D2}\x{96D3}' . + '\x{96D4}\x{96D5}\x{96D6}\x{96D7}\x{96D8}\x{96D9}\x{96DA}\x{96DB}\x{96DC}' . + '\x{96DD}\x{96DE}\x{96DF}\x{96E0}\x{96E1}\x{96E2}\x{96E3}\x{96E5}\x{96E8}' . + '\x{96E9}\x{96EA}\x{96EB}\x{96EC}\x{96ED}\x{96EE}\x{96EF}\x{96F0}\x{96F1}' . + '\x{96F2}\x{96F3}\x{96F4}\x{96F5}\x{96F6}\x{96F7}\x{96F8}\x{96F9}\x{96FA}' . + '\x{96FB}\x{96FD}\x{96FE}\x{96FF}\x{9700}\x{9701}\x{9702}\x{9703}\x{9704}' . + '\x{9705}\x{9706}\x{9707}\x{9708}\x{9709}\x{970A}\x{970B}\x{970C}\x{970D}' . + '\x{970E}\x{970F}\x{9710}\x{9711}\x{9712}\x{9713}\x{9715}\x{9716}\x{9718}' . + '\x{9719}\x{971C}\x{971D}\x{971E}\x{971F}\x{9720}\x{9721}\x{9722}\x{9723}' . + '\x{9724}\x{9725}\x{9726}\x{9727}\x{9728}\x{9729}\x{972A}\x{972B}\x{972C}' . + '\x{972D}\x{972E}\x{972F}\x{9730}\x{9731}\x{9732}\x{9735}\x{9736}\x{9738}' . + '\x{9739}\x{973A}\x{973B}\x{973C}\x{973D}\x{973E}\x{973F}\x{9742}\x{9743}' . + '\x{9744}\x{9745}\x{9746}\x{9747}\x{9748}\x{9749}\x{974A}\x{974B}\x{974C}' . + '\x{974E}\x{974F}\x{9750}\x{9751}\x{9752}\x{9753}\x{9754}\x{9755}\x{9756}' . + '\x{9758}\x{9759}\x{975A}\x{975B}\x{975C}\x{975D}\x{975E}\x{975F}\x{9760}' . + '\x{9761}\x{9762}\x{9765}\x{9766}\x{9767}\x{9768}\x{9769}\x{976A}\x{976B}' . + '\x{976C}\x{976D}\x{976E}\x{976F}\x{9770}\x{9772}\x{9773}\x{9774}\x{9776}' . + '\x{9777}\x{9778}\x{9779}\x{977A}\x{977B}\x{977C}\x{977D}\x{977E}\x{977F}' . + '\x{9780}\x{9781}\x{9782}\x{9783}\x{9784}\x{9785}\x{9786}\x{9788}\x{978A}' . + '\x{978B}\x{978C}\x{978D}\x{978E}\x{978F}\x{9790}\x{9791}\x{9792}\x{9793}' . + '\x{9794}\x{9795}\x{9796}\x{9797}\x{9798}\x{9799}\x{979A}\x{979C}\x{979D}' . + '\x{979E}\x{979F}\x{97A0}\x{97A1}\x{97A2}\x{97A3}\x{97A4}\x{97A5}\x{97A6}' . + '\x{97A7}\x{97A8}\x{97AA}\x{97AB}\x{97AC}\x{97AD}\x{97AE}\x{97AF}\x{97B2}' . + '\x{97B3}\x{97B4}\x{97B6}\x{97B7}\x{97B8}\x{97B9}\x{97BA}\x{97BB}\x{97BC}' . + '\x{97BD}\x{97BF}\x{97C1}\x{97C2}\x{97C3}\x{97C4}\x{97C5}\x{97C6}\x{97C7}' . + '\x{97C8}\x{97C9}\x{97CA}\x{97CB}\x{97CC}\x{97CD}\x{97CE}\x{97CF}\x{97D0}' . + '\x{97D1}\x{97D3}\x{97D4}\x{97D5}\x{97D6}\x{97D7}\x{97D8}\x{97D9}\x{97DA}' . + '\x{97DB}\x{97DC}\x{97DD}\x{97DE}\x{97DF}\x{97E0}\x{97E1}\x{97E2}\x{97E3}' . + '\x{97E4}\x{97E5}\x{97E6}\x{97E7}\x{97E8}\x{97E9}\x{97EA}\x{97EB}\x{97EC}' . + '\x{97ED}\x{97EE}\x{97EF}\x{97F0}\x{97F1}\x{97F2}\x{97F3}\x{97F4}\x{97F5}' . + '\x{97F6}\x{97F7}\x{97F8}\x{97F9}\x{97FA}\x{97FB}\x{97FD}\x{97FE}\x{97FF}' . + '\x{9800}\x{9801}\x{9802}\x{9803}\x{9804}\x{9805}\x{9806}\x{9807}\x{9808}' . + '\x{9809}\x{980A}\x{980B}\x{980C}\x{980D}\x{980E}\x{980F}\x{9810}\x{9811}' . + '\x{9812}\x{9813}\x{9814}\x{9815}\x{9816}\x{9817}\x{9818}\x{9819}\x{981A}' . + '\x{981B}\x{981C}\x{981D}\x{981E}\x{9820}\x{9821}\x{9822}\x{9823}\x{9824}' . + '\x{9826}\x{9827}\x{9828}\x{9829}\x{982B}\x{982D}\x{982E}\x{982F}\x{9830}' . + '\x{9831}\x{9832}\x{9834}\x{9835}\x{9836}\x{9837}\x{9838}\x{9839}\x{983B}' . + '\x{983C}\x{983D}\x{983F}\x{9840}\x{9841}\x{9843}\x{9844}\x{9845}\x{9846}' . + '\x{9848}\x{9849}\x{984A}\x{984C}\x{984D}\x{984E}\x{984F}\x{9850}\x{9851}' . + '\x{9852}\x{9853}\x{9854}\x{9855}\x{9857}\x{9858}\x{9859}\x{985A}\x{985B}' . + '\x{985C}\x{985D}\x{985E}\x{985F}\x{9860}\x{9861}\x{9862}\x{9863}\x{9864}' . + '\x{9865}\x{9867}\x{9869}\x{986A}\x{986B}\x{986C}\x{986D}\x{986E}\x{986F}' . + '\x{9870}\x{9871}\x{9872}\x{9873}\x{9874}\x{9875}\x{9876}\x{9877}\x{9878}' . + '\x{9879}\x{987A}\x{987B}\x{987C}\x{987D}\x{987E}\x{987F}\x{9880}\x{9881}' . + '\x{9882}\x{9883}\x{9884}\x{9885}\x{9886}\x{9887}\x{9888}\x{9889}\x{988A}' . + '\x{988B}\x{988C}\x{988D}\x{988E}\x{988F}\x{9890}\x{9891}\x{9892}\x{9893}' . + '\x{9894}\x{9895}\x{9896}\x{9897}\x{9898}\x{9899}\x{989A}\x{989B}\x{989C}' . + '\x{989D}\x{989E}\x{989F}\x{98A0}\x{98A1}\x{98A2}\x{98A3}\x{98A4}\x{98A5}' . + '\x{98A6}\x{98A7}\x{98A8}\x{98A9}\x{98AA}\x{98AB}\x{98AC}\x{98AD}\x{98AE}' . + '\x{98AF}\x{98B0}\x{98B1}\x{98B2}\x{98B3}\x{98B4}\x{98B5}\x{98B6}\x{98B8}' . + '\x{98B9}\x{98BA}\x{98BB}\x{98BC}\x{98BD}\x{98BE}\x{98BF}\x{98C0}\x{98C1}' . + '\x{98C2}\x{98C3}\x{98C4}\x{98C5}\x{98C6}\x{98C8}\x{98C9}\x{98CB}\x{98CC}' . + '\x{98CD}\x{98CE}\x{98CF}\x{98D0}\x{98D1}\x{98D2}\x{98D3}\x{98D4}\x{98D5}' . + '\x{98D6}\x{98D7}\x{98D8}\x{98D9}\x{98DA}\x{98DB}\x{98DC}\x{98DD}\x{98DE}' . + '\x{98DF}\x{98E0}\x{98E2}\x{98E3}\x{98E5}\x{98E6}\x{98E7}\x{98E8}\x{98E9}' . + '\x{98EA}\x{98EB}\x{98ED}\x{98EF}\x{98F0}\x{98F2}\x{98F3}\x{98F4}\x{98F5}' . + '\x{98F6}\x{98F7}\x{98F9}\x{98FA}\x{98FC}\x{98FD}\x{98FE}\x{98FF}\x{9900}' . + '\x{9901}\x{9902}\x{9903}\x{9904}\x{9905}\x{9906}\x{9907}\x{9908}\x{9909}' . + '\x{990A}\x{990B}\x{990C}\x{990D}\x{990E}\x{990F}\x{9910}\x{9911}\x{9912}' . + '\x{9913}\x{9914}\x{9915}\x{9916}\x{9917}\x{9918}\x{991A}\x{991B}\x{991C}' . + '\x{991D}\x{991E}\x{991F}\x{9920}\x{9921}\x{9922}\x{9923}\x{9924}\x{9925}' . + '\x{9926}\x{9927}\x{9928}\x{9929}\x{992A}\x{992B}\x{992C}\x{992D}\x{992E}' . + '\x{992F}\x{9930}\x{9931}\x{9932}\x{9933}\x{9934}\x{9935}\x{9936}\x{9937}' . + '\x{9938}\x{9939}\x{993A}\x{993C}\x{993D}\x{993E}\x{993F}\x{9940}\x{9941}' . + '\x{9942}\x{9943}\x{9945}\x{9946}\x{9947}\x{9948}\x{9949}\x{994A}\x{994B}' . + '\x{994C}\x{994E}\x{994F}\x{9950}\x{9951}\x{9952}\x{9953}\x{9954}\x{9955}' . + '\x{9956}\x{9957}\x{9958}\x{9959}\x{995B}\x{995C}\x{995E}\x{995F}\x{9960}' . + '\x{9961}\x{9962}\x{9963}\x{9964}\x{9965}\x{9966}\x{9967}\x{9968}\x{9969}' . + '\x{996A}\x{996B}\x{996C}\x{996D}\x{996E}\x{996F}\x{9970}\x{9971}\x{9972}' . + '\x{9973}\x{9974}\x{9975}\x{9976}\x{9977}\x{9978}\x{9979}\x{997A}\x{997B}' . + '\x{997C}\x{997D}\x{997E}\x{997F}\x{9980}\x{9981}\x{9982}\x{9983}\x{9984}' . + '\x{9985}\x{9986}\x{9987}\x{9988}\x{9989}\x{998A}\x{998B}\x{998C}\x{998D}' . + '\x{998E}\x{998F}\x{9990}\x{9991}\x{9992}\x{9993}\x{9994}\x{9995}\x{9996}' . + '\x{9997}\x{9998}\x{9999}\x{999A}\x{999B}\x{999C}\x{999D}\x{999E}\x{999F}' . + '\x{99A0}\x{99A1}\x{99A2}\x{99A3}\x{99A4}\x{99A5}\x{99A6}\x{99A7}\x{99A8}' . + '\x{99A9}\x{99AA}\x{99AB}\x{99AC}\x{99AD}\x{99AE}\x{99AF}\x{99B0}\x{99B1}' . + '\x{99B2}\x{99B3}\x{99B4}\x{99B5}\x{99B6}\x{99B7}\x{99B8}\x{99B9}\x{99BA}' . + '\x{99BB}\x{99BC}\x{99BD}\x{99BE}\x{99C0}\x{99C1}\x{99C2}\x{99C3}\x{99C4}' . + '\x{99C6}\x{99C7}\x{99C8}\x{99C9}\x{99CA}\x{99CB}\x{99CC}\x{99CD}\x{99CE}' . + '\x{99CF}\x{99D0}\x{99D1}\x{99D2}\x{99D3}\x{99D4}\x{99D5}\x{99D6}\x{99D7}' . + '\x{99D8}\x{99D9}\x{99DA}\x{99DB}\x{99DC}\x{99DD}\x{99DE}\x{99DF}\x{99E1}' . + '\x{99E2}\x{99E3}\x{99E4}\x{99E5}\x{99E7}\x{99E8}\x{99E9}\x{99EA}\x{99EC}' . + '\x{99ED}\x{99EE}\x{99EF}\x{99F0}\x{99F1}\x{99F2}\x{99F3}\x{99F4}\x{99F6}' . + '\x{99F7}\x{99F8}\x{99F9}\x{99FA}\x{99FB}\x{99FC}\x{99FD}\x{99FE}\x{99FF}' . + '\x{9A00}\x{9A01}\x{9A02}\x{9A03}\x{9A04}\x{9A05}\x{9A06}\x{9A07}\x{9A08}' . + '\x{9A09}\x{9A0A}\x{9A0B}\x{9A0C}\x{9A0D}\x{9A0E}\x{9A0F}\x{9A11}\x{9A14}' . + '\x{9A15}\x{9A16}\x{9A19}\x{9A1A}\x{9A1B}\x{9A1C}\x{9A1D}\x{9A1E}\x{9A1F}' . + '\x{9A20}\x{9A21}\x{9A22}\x{9A23}\x{9A24}\x{9A25}\x{9A26}\x{9A27}\x{9A29}' . + '\x{9A2A}\x{9A2B}\x{9A2C}\x{9A2D}\x{9A2E}\x{9A2F}\x{9A30}\x{9A31}\x{9A32}' . + '\x{9A33}\x{9A34}\x{9A35}\x{9A36}\x{9A37}\x{9A38}\x{9A39}\x{9A3A}\x{9A3C}' . + '\x{9A3D}\x{9A3E}\x{9A3F}\x{9A40}\x{9A41}\x{9A42}\x{9A43}\x{9A44}\x{9A45}' . + '\x{9A46}\x{9A47}\x{9A48}\x{9A49}\x{9A4A}\x{9A4B}\x{9A4C}\x{9A4D}\x{9A4E}' . + '\x{9A4F}\x{9A50}\x{9A52}\x{9A53}\x{9A54}\x{9A55}\x{9A56}\x{9A57}\x{9A59}' . + '\x{9A5A}\x{9A5B}\x{9A5C}\x{9A5E}\x{9A5F}\x{9A60}\x{9A61}\x{9A62}\x{9A64}' . + '\x{9A65}\x{9A66}\x{9A67}\x{9A68}\x{9A69}\x{9A6A}\x{9A6B}\x{9A6C}\x{9A6D}' . + '\x{9A6E}\x{9A6F}\x{9A70}\x{9A71}\x{9A72}\x{9A73}\x{9A74}\x{9A75}\x{9A76}' . + '\x{9A77}\x{9A78}\x{9A79}\x{9A7A}\x{9A7B}\x{9A7C}\x{9A7D}\x{9A7E}\x{9A7F}' . + '\x{9A80}\x{9A81}\x{9A82}\x{9A83}\x{9A84}\x{9A85}\x{9A86}\x{9A87}\x{9A88}' . + '\x{9A89}\x{9A8A}\x{9A8B}\x{9A8C}\x{9A8D}\x{9A8E}\x{9A8F}\x{9A90}\x{9A91}' . + '\x{9A92}\x{9A93}\x{9A94}\x{9A95}\x{9A96}\x{9A97}\x{9A98}\x{9A99}\x{9A9A}' . + '\x{9A9B}\x{9A9C}\x{9A9D}\x{9A9E}\x{9A9F}\x{9AA0}\x{9AA1}\x{9AA2}\x{9AA3}' . + '\x{9AA4}\x{9AA5}\x{9AA6}\x{9AA7}\x{9AA8}\x{9AAA}\x{9AAB}\x{9AAC}\x{9AAD}' . + '\x{9AAE}\x{9AAF}\x{9AB0}\x{9AB1}\x{9AB2}\x{9AB3}\x{9AB4}\x{9AB5}\x{9AB6}' . + '\x{9AB7}\x{9AB8}\x{9AB9}\x{9ABA}\x{9ABB}\x{9ABC}\x{9ABE}\x{9ABF}\x{9AC0}' . + '\x{9AC1}\x{9AC2}\x{9AC3}\x{9AC4}\x{9AC5}\x{9AC6}\x{9AC7}\x{9AC9}\x{9ACA}' . + '\x{9ACB}\x{9ACC}\x{9ACD}\x{9ACE}\x{9ACF}\x{9AD0}\x{9AD1}\x{9AD2}\x{9AD3}' . + '\x{9AD4}\x{9AD5}\x{9AD6}\x{9AD8}\x{9AD9}\x{9ADA}\x{9ADB}\x{9ADC}\x{9ADD}' . + '\x{9ADE}\x{9ADF}\x{9AE1}\x{9AE2}\x{9AE3}\x{9AE5}\x{9AE6}\x{9AE7}\x{9AEA}' . + '\x{9AEB}\x{9AEC}\x{9AED}\x{9AEE}\x{9AEF}\x{9AF1}\x{9AF2}\x{9AF3}\x{9AF4}' . + '\x{9AF5}\x{9AF6}\x{9AF7}\x{9AF8}\x{9AF9}\x{9AFA}\x{9AFB}\x{9AFC}\x{9AFD}' . + '\x{9AFE}\x{9AFF}\x{9B01}\x{9B03}\x{9B04}\x{9B05}\x{9B06}\x{9B07}\x{9B08}' . + '\x{9B0A}\x{9B0B}\x{9B0C}\x{9B0D}\x{9B0E}\x{9B0F}\x{9B10}\x{9B11}\x{9B12}' . + '\x{9B13}\x{9B15}\x{9B16}\x{9B17}\x{9B18}\x{9B19}\x{9B1A}\x{9B1C}\x{9B1D}' . + '\x{9B1E}\x{9B1F}\x{9B20}\x{9B21}\x{9B22}\x{9B23}\x{9B24}\x{9B25}\x{9B26}' . + '\x{9B27}\x{9B28}\x{9B29}\x{9B2A}\x{9B2B}\x{9B2C}\x{9B2D}\x{9B2E}\x{9B2F}' . + '\x{9B30}\x{9B31}\x{9B32}\x{9B33}\x{9B35}\x{9B36}\x{9B37}\x{9B38}\x{9B39}' . + '\x{9B3A}\x{9B3B}\x{9B3C}\x{9B3E}\x{9B3F}\x{9B41}\x{9B42}\x{9B43}\x{9B44}' . + '\x{9B45}\x{9B46}\x{9B47}\x{9B48}\x{9B49}\x{9B4A}\x{9B4B}\x{9B4C}\x{9B4D}' . + '\x{9B4E}\x{9B4F}\x{9B51}\x{9B52}\x{9B53}\x{9B54}\x{9B55}\x{9B56}\x{9B58}' . + '\x{9B59}\x{9B5A}\x{9B5B}\x{9B5C}\x{9B5D}\x{9B5E}\x{9B5F}\x{9B60}\x{9B61}' . + '\x{9B63}\x{9B64}\x{9B65}\x{9B66}\x{9B67}\x{9B68}\x{9B69}\x{9B6A}\x{9B6B}' . + '\x{9B6C}\x{9B6D}\x{9B6E}\x{9B6F}\x{9B70}\x{9B71}\x{9B73}\x{9B74}\x{9B75}' . + '\x{9B76}\x{9B77}\x{9B78}\x{9B79}\x{9B7A}\x{9B7B}\x{9B7C}\x{9B7D}\x{9B7E}' . + '\x{9B7F}\x{9B80}\x{9B81}\x{9B82}\x{9B83}\x{9B84}\x{9B85}\x{9B86}\x{9B87}' . + '\x{9B88}\x{9B8A}\x{9B8B}\x{9B8D}\x{9B8E}\x{9B8F}\x{9B90}\x{9B91}\x{9B92}' . + '\x{9B93}\x{9B94}\x{9B95}\x{9B96}\x{9B97}\x{9B98}\x{9B9A}\x{9B9B}\x{9B9C}' . + '\x{9B9D}\x{9B9E}\x{9B9F}\x{9BA0}\x{9BA1}\x{9BA2}\x{9BA3}\x{9BA4}\x{9BA5}' . + '\x{9BA6}\x{9BA7}\x{9BA8}\x{9BA9}\x{9BAA}\x{9BAB}\x{9BAC}\x{9BAD}\x{9BAE}' . + '\x{9BAF}\x{9BB0}\x{9BB1}\x{9BB2}\x{9BB3}\x{9BB4}\x{9BB5}\x{9BB6}\x{9BB7}' . + '\x{9BB8}\x{9BB9}\x{9BBA}\x{9BBB}\x{9BBC}\x{9BBD}\x{9BBE}\x{9BBF}\x{9BC0}' . + '\x{9BC1}\x{9BC3}\x{9BC4}\x{9BC5}\x{9BC6}\x{9BC7}\x{9BC8}\x{9BC9}\x{9BCA}' . + '\x{9BCB}\x{9BCC}\x{9BCD}\x{9BCE}\x{9BCF}\x{9BD0}\x{9BD1}\x{9BD2}\x{9BD3}' . + '\x{9BD4}\x{9BD5}\x{9BD6}\x{9BD7}\x{9BD8}\x{9BD9}\x{9BDA}\x{9BDB}\x{9BDC}' . + '\x{9BDD}\x{9BDE}\x{9BDF}\x{9BE0}\x{9BE1}\x{9BE2}\x{9BE3}\x{9BE4}\x{9BE5}' . + '\x{9BE6}\x{9BE7}\x{9BE8}\x{9BE9}\x{9BEA}\x{9BEB}\x{9BEC}\x{9BED}\x{9BEE}' . + '\x{9BEF}\x{9BF0}\x{9BF1}\x{9BF2}\x{9BF3}\x{9BF4}\x{9BF5}\x{9BF7}\x{9BF8}' . + '\x{9BF9}\x{9BFA}\x{9BFB}\x{9BFC}\x{9BFD}\x{9BFE}\x{9BFF}\x{9C02}\x{9C05}' . + '\x{9C06}\x{9C07}\x{9C08}\x{9C09}\x{9C0A}\x{9C0B}\x{9C0C}\x{9C0D}\x{9C0E}' . + '\x{9C0F}\x{9C10}\x{9C11}\x{9C12}\x{9C13}\x{9C14}\x{9C15}\x{9C16}\x{9C17}' . + '\x{9C18}\x{9C19}\x{9C1A}\x{9C1B}\x{9C1C}\x{9C1D}\x{9C1E}\x{9C1F}\x{9C20}' . + '\x{9C21}\x{9C22}\x{9C23}\x{9C24}\x{9C25}\x{9C26}\x{9C27}\x{9C28}\x{9C29}' . + '\x{9C2A}\x{9C2B}\x{9C2C}\x{9C2D}\x{9C2F}\x{9C30}\x{9C31}\x{9C32}\x{9C33}' . + '\x{9C34}\x{9C35}\x{9C36}\x{9C37}\x{9C38}\x{9C39}\x{9C3A}\x{9C3B}\x{9C3C}' . + '\x{9C3D}\x{9C3E}\x{9C3F}\x{9C40}\x{9C41}\x{9C43}\x{9C44}\x{9C45}\x{9C46}' . + '\x{9C47}\x{9C48}\x{9C49}\x{9C4A}\x{9C4B}\x{9C4C}\x{9C4D}\x{9C4E}\x{9C50}' . + '\x{9C52}\x{9C53}\x{9C54}\x{9C55}\x{9C56}\x{9C57}\x{9C58}\x{9C59}\x{9C5A}' . + '\x{9C5B}\x{9C5C}\x{9C5D}\x{9C5E}\x{9C5F}\x{9C60}\x{9C62}\x{9C63}\x{9C65}' . + '\x{9C66}\x{9C67}\x{9C68}\x{9C69}\x{9C6A}\x{9C6B}\x{9C6C}\x{9C6D}\x{9C6E}' . + '\x{9C6F}\x{9C70}\x{9C71}\x{9C72}\x{9C73}\x{9C74}\x{9C75}\x{9C77}\x{9C78}' . + '\x{9C79}\x{9C7A}\x{9C7C}\x{9C7D}\x{9C7E}\x{9C7F}\x{9C80}\x{9C81}\x{9C82}' . + '\x{9C83}\x{9C84}\x{9C85}\x{9C86}\x{9C87}\x{9C88}\x{9C89}\x{9C8A}\x{9C8B}' . + '\x{9C8C}\x{9C8D}\x{9C8E}\x{9C8F}\x{9C90}\x{9C91}\x{9C92}\x{9C93}\x{9C94}' . + '\x{9C95}\x{9C96}\x{9C97}\x{9C98}\x{9C99}\x{9C9A}\x{9C9B}\x{9C9C}\x{9C9D}' . + '\x{9C9E}\x{9C9F}\x{9CA0}\x{9CA1}\x{9CA2}\x{9CA3}\x{9CA4}\x{9CA5}\x{9CA6}' . + '\x{9CA7}\x{9CA8}\x{9CA9}\x{9CAA}\x{9CAB}\x{9CAC}\x{9CAD}\x{9CAE}\x{9CAF}' . + '\x{9CB0}\x{9CB1}\x{9CB2}\x{9CB3}\x{9CB4}\x{9CB5}\x{9CB6}\x{9CB7}\x{9CB8}' . + '\x{9CB9}\x{9CBA}\x{9CBB}\x{9CBC}\x{9CBD}\x{9CBE}\x{9CBF}\x{9CC0}\x{9CC1}' . + '\x{9CC2}\x{9CC3}\x{9CC4}\x{9CC5}\x{9CC6}\x{9CC7}\x{9CC8}\x{9CC9}\x{9CCA}' . + '\x{9CCB}\x{9CCC}\x{9CCD}\x{9CCE}\x{9CCF}\x{9CD0}\x{9CD1}\x{9CD2}\x{9CD3}' . + '\x{9CD4}\x{9CD5}\x{9CD6}\x{9CD7}\x{9CD8}\x{9CD9}\x{9CDA}\x{9CDB}\x{9CDC}' . + '\x{9CDD}\x{9CDE}\x{9CDF}\x{9CE0}\x{9CE1}\x{9CE2}\x{9CE3}\x{9CE4}\x{9CE5}' . + '\x{9CE6}\x{9CE7}\x{9CE8}\x{9CE9}\x{9CEA}\x{9CEB}\x{9CEC}\x{9CED}\x{9CEE}' . + '\x{9CEF}\x{9CF0}\x{9CF1}\x{9CF2}\x{9CF3}\x{9CF4}\x{9CF5}\x{9CF6}\x{9CF7}' . + '\x{9CF8}\x{9CF9}\x{9CFA}\x{9CFB}\x{9CFC}\x{9CFD}\x{9CFE}\x{9CFF}\x{9D00}' . + '\x{9D01}\x{9D02}\x{9D03}\x{9D04}\x{9D05}\x{9D06}\x{9D07}\x{9D08}\x{9D09}' . + '\x{9D0A}\x{9D0B}\x{9D0F}\x{9D10}\x{9D12}\x{9D13}\x{9D14}\x{9D15}\x{9D16}' . + '\x{9D17}\x{9D18}\x{9D19}\x{9D1A}\x{9D1B}\x{9D1C}\x{9D1D}\x{9D1E}\x{9D1F}' . + '\x{9D20}\x{9D21}\x{9D22}\x{9D23}\x{9D24}\x{9D25}\x{9D26}\x{9D28}\x{9D29}' . + '\x{9D2B}\x{9D2D}\x{9D2E}\x{9D2F}\x{9D30}\x{9D31}\x{9D32}\x{9D33}\x{9D34}' . + '\x{9D36}\x{9D37}\x{9D38}\x{9D39}\x{9D3A}\x{9D3B}\x{9D3D}\x{9D3E}\x{9D3F}' . + '\x{9D40}\x{9D41}\x{9D42}\x{9D43}\x{9D45}\x{9D46}\x{9D47}\x{9D48}\x{9D49}' . + '\x{9D4A}\x{9D4B}\x{9D4C}\x{9D4D}\x{9D4E}\x{9D4F}\x{9D50}\x{9D51}\x{9D52}' . + '\x{9D53}\x{9D54}\x{9D55}\x{9D56}\x{9D57}\x{9D58}\x{9D59}\x{9D5A}\x{9D5B}' . + '\x{9D5C}\x{9D5D}\x{9D5E}\x{9D5F}\x{9D60}\x{9D61}\x{9D62}\x{9D63}\x{9D64}' . + '\x{9D65}\x{9D66}\x{9D67}\x{9D68}\x{9D69}\x{9D6A}\x{9D6B}\x{9D6C}\x{9D6E}' . + '\x{9D6F}\x{9D70}\x{9D71}\x{9D72}\x{9D73}\x{9D74}\x{9D75}\x{9D76}\x{9D77}' . + '\x{9D78}\x{9D79}\x{9D7A}\x{9D7B}\x{9D7C}\x{9D7D}\x{9D7E}\x{9D7F}\x{9D80}' . + '\x{9D81}\x{9D82}\x{9D83}\x{9D84}\x{9D85}\x{9D86}\x{9D87}\x{9D88}\x{9D89}' . + '\x{9D8A}\x{9D8B}\x{9D8C}\x{9D8D}\x{9D8E}\x{9D90}\x{9D91}\x{9D92}\x{9D93}' . + '\x{9D94}\x{9D96}\x{9D97}\x{9D98}\x{9D99}\x{9D9A}\x{9D9B}\x{9D9C}\x{9D9D}' . + '\x{9D9E}\x{9D9F}\x{9DA0}\x{9DA1}\x{9DA2}\x{9DA3}\x{9DA4}\x{9DA5}\x{9DA6}' . + '\x{9DA7}\x{9DA8}\x{9DA9}\x{9DAA}\x{9DAB}\x{9DAC}\x{9DAD}\x{9DAF}\x{9DB0}' . + '\x{9DB1}\x{9DB2}\x{9DB3}\x{9DB4}\x{9DB5}\x{9DB6}\x{9DB7}\x{9DB8}\x{9DB9}' . + '\x{9DBA}\x{9DBB}\x{9DBC}\x{9DBE}\x{9DBF}\x{9DC1}\x{9DC2}\x{9DC3}\x{9DC4}' . + '\x{9DC5}\x{9DC7}\x{9DC8}\x{9DC9}\x{9DCA}\x{9DCB}\x{9DCC}\x{9DCD}\x{9DCE}' . + '\x{9DCF}\x{9DD0}\x{9DD1}\x{9DD2}\x{9DD3}\x{9DD4}\x{9DD5}\x{9DD6}\x{9DD7}' . + '\x{9DD8}\x{9DD9}\x{9DDA}\x{9DDB}\x{9DDC}\x{9DDD}\x{9DDE}\x{9DDF}\x{9DE0}' . + '\x{9DE1}\x{9DE2}\x{9DE3}\x{9DE4}\x{9DE5}\x{9DE6}\x{9DE7}\x{9DE8}\x{9DE9}' . + '\x{9DEB}\x{9DEC}\x{9DED}\x{9DEE}\x{9DEF}\x{9DF0}\x{9DF1}\x{9DF2}\x{9DF3}' . + '\x{9DF4}\x{9DF5}\x{9DF6}\x{9DF7}\x{9DF8}\x{9DF9}\x{9DFA}\x{9DFB}\x{9DFD}' . + '\x{9DFE}\x{9DFF}\x{9E00}\x{9E01}\x{9E02}\x{9E03}\x{9E04}\x{9E05}\x{9E06}' . + '\x{9E07}\x{9E08}\x{9E09}\x{9E0A}\x{9E0B}\x{9E0C}\x{9E0D}\x{9E0F}\x{9E10}' . + '\x{9E11}\x{9E12}\x{9E13}\x{9E14}\x{9E15}\x{9E17}\x{9E18}\x{9E19}\x{9E1A}' . + '\x{9E1B}\x{9E1D}\x{9E1E}\x{9E1F}\x{9E20}\x{9E21}\x{9E22}\x{9E23}\x{9E24}' . + '\x{9E25}\x{9E26}\x{9E27}\x{9E28}\x{9E29}\x{9E2A}\x{9E2B}\x{9E2C}\x{9E2D}' . + '\x{9E2E}\x{9E2F}\x{9E30}\x{9E31}\x{9E32}\x{9E33}\x{9E34}\x{9E35}\x{9E36}' . + '\x{9E37}\x{9E38}\x{9E39}\x{9E3A}\x{9E3B}\x{9E3C}\x{9E3D}\x{9E3E}\x{9E3F}' . + '\x{9E40}\x{9E41}\x{9E42}\x{9E43}\x{9E44}\x{9E45}\x{9E46}\x{9E47}\x{9E48}' . + '\x{9E49}\x{9E4A}\x{9E4B}\x{9E4C}\x{9E4D}\x{9E4E}\x{9E4F}\x{9E50}\x{9E51}' . + '\x{9E52}\x{9E53}\x{9E54}\x{9E55}\x{9E56}\x{9E57}\x{9E58}\x{9E59}\x{9E5A}' . + '\x{9E5B}\x{9E5C}\x{9E5D}\x{9E5E}\x{9E5F}\x{9E60}\x{9E61}\x{9E62}\x{9E63}' . + '\x{9E64}\x{9E65}\x{9E66}\x{9E67}\x{9E68}\x{9E69}\x{9E6A}\x{9E6B}\x{9E6C}' . + '\x{9E6D}\x{9E6E}\x{9E6F}\x{9E70}\x{9E71}\x{9E72}\x{9E73}\x{9E74}\x{9E75}' . + '\x{9E76}\x{9E77}\x{9E79}\x{9E7A}\x{9E7C}\x{9E7D}\x{9E7E}\x{9E7F}\x{9E80}' . + '\x{9E81}\x{9E82}\x{9E83}\x{9E84}\x{9E85}\x{9E86}\x{9E87}\x{9E88}\x{9E89}' . + '\x{9E8A}\x{9E8B}\x{9E8C}\x{9E8D}\x{9E8E}\x{9E91}\x{9E92}\x{9E93}\x{9E94}' . + '\x{9E96}\x{9E97}\x{9E99}\x{9E9A}\x{9E9B}\x{9E9C}\x{9E9D}\x{9E9F}\x{9EA0}' . + '\x{9EA1}\x{9EA3}\x{9EA4}\x{9EA5}\x{9EA6}\x{9EA7}\x{9EA8}\x{9EA9}\x{9EAA}' . + '\x{9EAD}\x{9EAE}\x{9EAF}\x{9EB0}\x{9EB2}\x{9EB3}\x{9EB4}\x{9EB5}\x{9EB6}' . + '\x{9EB7}\x{9EB8}\x{9EBB}\x{9EBC}\x{9EBD}\x{9EBE}\x{9EBF}\x{9EC0}\x{9EC1}' . + '\x{9EC2}\x{9EC3}\x{9EC4}\x{9EC5}\x{9EC6}\x{9EC7}\x{9EC8}\x{9EC9}\x{9ECA}' . + '\x{9ECB}\x{9ECC}\x{9ECD}\x{9ECE}\x{9ECF}\x{9ED0}\x{9ED1}\x{9ED2}\x{9ED3}' . + '\x{9ED4}\x{9ED5}\x{9ED6}\x{9ED7}\x{9ED8}\x{9ED9}\x{9EDA}\x{9EDB}\x{9EDC}' . + '\x{9EDD}\x{9EDE}\x{9EDF}\x{9EE0}\x{9EE1}\x{9EE2}\x{9EE3}\x{9EE4}\x{9EE5}' . + '\x{9EE6}\x{9EE7}\x{9EE8}\x{9EE9}\x{9EEA}\x{9EEB}\x{9EED}\x{9EEE}\x{9EEF}' . + '\x{9EF0}\x{9EF2}\x{9EF3}\x{9EF4}\x{9EF5}\x{9EF6}\x{9EF7}\x{9EF8}\x{9EF9}' . + '\x{9EFA}\x{9EFB}\x{9EFC}\x{9EFD}\x{9EFE}\x{9EFF}\x{9F00}\x{9F01}\x{9F02}' . + '\x{9F04}\x{9F05}\x{9F06}\x{9F07}\x{9F08}\x{9F09}\x{9F0A}\x{9F0B}\x{9F0C}' . + '\x{9F0D}\x{9F0E}\x{9F0F}\x{9F10}\x{9F12}\x{9F13}\x{9F15}\x{9F16}\x{9F17}' . + '\x{9F18}\x{9F19}\x{9F1A}\x{9F1B}\x{9F1C}\x{9F1D}\x{9F1E}\x{9F1F}\x{9F20}' . + '\x{9F22}\x{9F23}\x{9F24}\x{9F25}\x{9F27}\x{9F28}\x{9F29}\x{9F2A}\x{9F2B}' . + '\x{9F2C}\x{9F2D}\x{9F2E}\x{9F2F}\x{9F30}\x{9F31}\x{9F32}\x{9F33}\x{9F34}' . + '\x{9F35}\x{9F36}\x{9F37}\x{9F38}\x{9F39}\x{9F3A}\x{9F3B}\x{9F3C}\x{9F3D}' . + '\x{9F3E}\x{9F3F}\x{9F40}\x{9F41}\x{9F42}\x{9F43}\x{9F44}\x{9F46}\x{9F47}' . + '\x{9F48}\x{9F49}\x{9F4A}\x{9F4B}\x{9F4C}\x{9F4D}\x{9F4E}\x{9F4F}\x{9F50}' . + '\x{9F51}\x{9F52}\x{9F54}\x{9F55}\x{9F56}\x{9F57}\x{9F58}\x{9F59}\x{9F5A}' . + '\x{9F5B}\x{9F5C}\x{9F5D}\x{9F5E}\x{9F5F}\x{9F60}\x{9F61}\x{9F63}\x{9F64}' . + '\x{9F65}\x{9F66}\x{9F67}\x{9F68}\x{9F69}\x{9F6A}\x{9F6B}\x{9F6C}\x{9F6E}' . + '\x{9F6F}\x{9F70}\x{9F71}\x{9F72}\x{9F73}\x{9F74}\x{9F75}\x{9F76}\x{9F77}' . + '\x{9F78}\x{9F79}\x{9F7A}\x{9F7B}\x{9F7C}\x{9F7D}\x{9F7E}\x{9F7F}\x{9F80}' . + '\x{9F81}\x{9F82}\x{9F83}\x{9F84}\x{9F85}\x{9F86}\x{9F87}\x{9F88}\x{9F89}' . + '\x{9F8A}\x{9F8B}\x{9F8C}\x{9F8D}\x{9F8E}\x{9F8F}\x{9F90}\x{9F91}\x{9F92}' . + '\x{9F93}\x{9F94}\x{9F95}\x{9F96}\x{9F97}\x{9F98}\x{9F99}\x{9F9A}\x{9F9B}' . + '\x{9F9C}\x{9F9D}\x{9F9E}\x{9F9F}\x{9FA0}\x{9FA2}\x{9FA4}\x{9FA5}]{1,20}$/iu', +]; diff --git a/lib/laminas/laminas-validator/src/Hostname/Com.php b/lib/laminas/laminas-validator/src/Hostname/Com.php new file mode 100644 index 000000000..06f071d90 --- /dev/null +++ b/lib/laminas/laminas-validator/src/Hostname/Com.php @@ -0,0 +1,181 @@ + '/^[\x{002d}0-9\x{0400}-\x{052f}]{1,63}$/iu', + 2 => '/^[\x{002d}0-9\x{0370}-\x{03ff}]{1,63}$/iu', + 3 => '/^[\x{002d}0-9a-z\x{ac00}-\x{d7a3}]{1,17}$/iu', + // @codingStandardsIgnoreStart + 4 => '/^[\x{002d}0-9a-z·à-öø-ÿāăąćĉċčďđēĕėęěĝğġģĥħĩīĭįıĵķĸĺļľłńņňŋōŏőœŕŗřśŝşšţťŧũūŭůűųŵŷźżž]{1,63}$/iu', + // @codingStandardsIgnoreEnd + 5 => '/^[\x{002d}0-9A-Za-z\x{3400}-\x{3401}\x{3404}-\x{3406}\x{340C}\x{3416}\x{341C}' . +'\x{3421}\x{3424}\x{3428}-\x{3429}\x{342B}-\x{342E}\x{3430}-\x{3434}\x{3436}' . +'\x{3438}-\x{343C}\x{343E}\x{3441}-\x{3445}\x{3447}\x{3449}-\x{3451}\x{3453}' . +'\x{3457}-\x{345F}\x{3463}-\x{3467}\x{346E}-\x{3471}\x{3473}-\x{3477}\x{3479}-\x{348E}\x{3491}-\x{3497}' . +'\x{3499}-\x{34A1}\x{34A4}-\x{34AD}\x{34AF}-\x{34B0}\x{34B2}-\x{34BF}\x{34C2}-\x{34C5}\x{34C7}-\x{34CC}' . +'\x{34CE}-\x{34D1}\x{34D3}-\x{34D8}\x{34DA}-\x{34E4}\x{34E7}-\x{34E9}\x{34EC}-\x{34EF}\x{34F1}-\x{34FE}' . +'\x{3500}-\x{3507}\x{350A}-\x{3513}\x{3515}\x{3517}-\x{351A}\x{351C}-\x{351E}\x{3520}-\x{352A}' . +'\x{352C}-\x{3552}\x{3554}-\x{355C}\x{355E}-\x{3567}\x{3569}-\x{3573}\x{3575}-\x{357C}\x{3580}-\x{3588}' . +'\x{358F}-\x{3598}\x{359E}-\x{35AB}\x{35B4}-\x{35CD}\x{35D0}\x{35D3}-\x{35DC}\x{35E2}-\x{35ED}' . +'\x{35F0}-\x{35F6}\x{35FB}-\x{3602}\x{3605}-\x{360E}\x{3610}-\x{3611}\x{3613}-\x{3616}\x{3619}-\x{362D}' . +'\x{362F}-\x{3634}\x{3636}-\x{363B}\x{363F}-\x{3645}\x{3647}-\x{364B}\x{364D}-\x{3653}\x{3655}' . +'\x{3659}-\x{365E}\x{3660}-\x{3665}\x{3667}-\x{367C}\x{367E}\x{3680}-\x{3685}\x{3687}' . +'\x{3689}-\x{3690}\x{3692}-\x{3698}\x{369A}\x{369C}-\x{36AE}\x{36B0}-\x{36BF}\x{36C1}-\x{36C5}' . +'\x{36C9}-\x{36CA}\x{36CD}-\x{36DE}\x{36E1}-\x{36E2}\x{36E5}-\x{36FE}\x{3701}-\x{3713}\x{3715}-\x{371E}' . +'\x{3720}-\x{372C}\x{372E}-\x{3745}\x{3747}-\x{3748}\x{374A}\x{374C}-\x{3759}\x{375B}-\x{3760}' . +'\x{3762}-\x{3767}\x{3769}-\x{3772}\x{3774}-\x{378C}\x{378F}-\x{379C}\x{379F}\x{37A1}-\x{37AD}' . +'\x{37AF}-\x{37B7}\x{37B9}-\x{37C1}\x{37C3}-\x{37C5}\x{37C7}-\x{37D4}\x{37D6}-\x{37E0}\x{37E2}' . +'\x{37E5}-\x{37ED}\x{37EF}-\x{37F6}\x{37F8}-\x{3802}\x{3804}-\x{381D}\x{3820}-\x{3822}\x{3825}-\x{382A}' . +'\x{382D}-\x{382F}\x{3831}-\x{3832}\x{3834}-\x{384C}\x{384E}-\x{3860}\x{3862}-\x{3863}\x{3865}-\x{386B}' . +'\x{386D}-\x{3886}\x{3888}-\x{38A1}\x{38A3}\x{38A5}-\x{38AA}\x{38AC}\x{38AE}-\x{38B0}' . +'\x{38B2}-\x{38B6}\x{38B8}\x{38BA}-\x{38BE}\x{38C0}-\x{38C9}\x{38CB}-\x{38D4}\x{38D8}-\x{38E0}' . +'\x{38E2}-\x{38E6}\x{38EB}-\x{38ED}\x{38EF}-\x{38F2}\x{38F5}-\x{38F7}\x{38FA}-\x{38FF}\x{3901}-\x{392A}' . +'\x{392C}\x{392E}-\x{393B}\x{393E}-\x{3956}\x{395A}-\x{3969}\x{396B}-\x{397A}\x{397C}-\x{3987}' . +'\x{3989}-\x{3998}\x{399A}-\x{39B0}\x{39B2}\x{39B4}-\x{39D0}\x{39D2}-\x{39DA}\x{39DE}-\x{39DF}' . +'\x{39E1}-\x{39EF}\x{39F1}-\x{3A17}\x{3A19}-\x{3A2A}\x{3A2D}-\x{3A40}\x{3A43}-\x{3A4E}\x{3A50}' . +'\x{3A52}-\x{3A5E}\x{3A60}-\x{3A6D}\x{3A6F}-\x{3A77}\x{3A79}-\x{3A82}\x{3A84}-\x{3A85}\x{3A87}-\x{3A89}' . +'\x{3A8B}-\x{3A8F}\x{3A91}-\x{3A93}\x{3A95}-\x{3A96}\x{3A9A}\x{3A9C}-\x{3AA6}\x{3AA8}-\x{3AA9}' . +'\x{3AAB}-\x{3AB1}\x{3AB4}-\x{3ABC}\x{3ABE}-\x{3AC5}\x{3ACA}-\x{3ACB}\x{3ACD}-\x{3AD5}\x{3AD7}-\x{3AE1}' . +'\x{3AE4}-\x{3AE7}\x{3AE9}-\x{3AEC}\x{3AEE}-\x{3AFD}\x{3B01}-\x{3B10}\x{3B12}-\x{3B15}\x{3B17}-\x{3B1E}' . +'\x{3B20}-\x{3B23}\x{3B25}-\x{3B27}\x{3B29}-\x{3B36}\x{3B38}-\x{3B39}\x{3B3B}-\x{3B3C}\x{3B3F}' . +'\x{3B41}-\x{3B44}\x{3B47}-\x{3B4C}\x{3B4E}\x{3B51}-\x{3B55}\x{3B58}-\x{3B62}\x{3B68}-\x{3B72}' . +'\x{3B78}-\x{3B88}\x{3B8B}-\x{3B9F}\x{3BA1}\x{3BA3}-\x{3BBA}\x{3BBC}\x{3BBF}-\x{3BD0}' . +'\x{3BD3}-\x{3BE6}\x{3BEA}-\x{3BFB}\x{3BFE}-\x{3C12}\x{3C14}-\x{3C1B}\x{3C1D}-\x{3C37}\x{3C39}-\x{3C4F}' . +'\x{3C52}\x{3C54}-\x{3C5C}\x{3C5E}-\x{3C68}\x{3C6A}-\x{3C76}\x{3C78}-\x{3C8F}\x{3C91}-\x{3CA8}' . +'\x{3CAA}-\x{3CAD}\x{3CAF}-\x{3CBE}\x{3CC0}-\x{3CC8}\x{3CCA}-\x{3CD3}\x{3CD6}-\x{3CE0}\x{3CE4}-\x{3CEE}' . +'\x{3CF3}-\x{3D0A}\x{3D0E}-\x{3D1E}\x{3D20}-\x{3D21}\x{3D25}-\x{3D38}\x{3D3B}-\x{3D46}\x{3D4A}-\x{3D59}' . +'\x{3D5D}-\x{3D7B}\x{3D7D}-\x{3D81}\x{3D84}-\x{3D88}\x{3D8C}-\x{3D8F}\x{3D91}-\x{3D98}\x{3D9A}-\x{3D9C}' . +'\x{3D9E}-\x{3DA1}\x{3DA3}-\x{3DB0}\x{3DB2}-\x{3DB5}\x{3DB9}-\x{3DBC}\x{3DBE}-\x{3DCB}\x{3DCD}-\x{3DDB}' . +'\x{3DDF}-\x{3DE8}\x{3DEB}-\x{3DF0}\x{3DF3}-\x{3DF9}\x{3DFB}-\x{3DFC}\x{3DFE}-\x{3E05}\x{3E08}-\x{3E33}' . +'\x{3E35}-\x{3E3E}\x{3E40}-\x{3E47}\x{3E49}-\x{3E67}\x{3E6B}-\x{3E6F}\x{3E71}-\x{3E85}\x{3E87}-\x{3E8C}' . +'\x{3E8E}-\x{3E98}\x{3E9A}-\x{3EA1}\x{3EA3}-\x{3EAE}\x{3EB0}-\x{3EB5}\x{3EB7}-\x{3EBA}\x{3EBD}' . +'\x{3EBF}-\x{3EC4}\x{3EC7}-\x{3ECE}\x{3ED1}-\x{3ED7}\x{3ED9}-\x{3EDA}\x{3EDD}-\x{3EE3}\x{3EE7}-\x{3EE8}' . +'\x{3EEB}-\x{3EF2}\x{3EF5}-\x{3EFF}\x{3F01}-\x{3F02}\x{3F04}-\x{3F07}\x{3F09}-\x{3F44}\x{3F46}-\x{3F4E}' . +'\x{3F50}-\x{3F53}\x{3F55}-\x{3F72}\x{3F74}-\x{3F75}\x{3F77}-\x{3F7B}\x{3F7D}-\x{3FB0}\x{3FB6}-\x{3FBF}' . +'\x{3FC1}-\x{3FCF}\x{3FD1}-\x{3FD3}\x{3FD5}-\x{3FDF}\x{3FE1}-\x{400B}\x{400D}-\x{401C}\x{401E}-\x{4024}' . +'\x{4027}-\x{403F}\x{4041}-\x{4060}\x{4062}-\x{4069}\x{406B}-\x{408A}\x{408C}-\x{40A7}\x{40A9}-\x{40B4}' . +'\x{40B6}-\x{40C2}\x{40C7}-\x{40CF}\x{40D1}-\x{40DE}\x{40E0}-\x{40E7}\x{40E9}-\x{40EE}\x{40F0}-\x{40FB}' . +'\x{40FD}-\x{4109}\x{410B}-\x{4115}\x{4118}-\x{411D}\x{411F}-\x{4122}\x{4124}-\x{4133}\x{4136}-\x{4138}' . +'\x{413A}-\x{4148}\x{414A}-\x{4169}\x{416C}-\x{4185}\x{4188}-\x{418B}\x{418D}-\x{41AD}\x{41AF}-\x{41B3}' . +'\x{41B5}-\x{41C3}\x{41C5}-\x{41C9}\x{41CB}-\x{41F2}\x{41F5}-\x{41FE}\x{4200}-\x{4227}\x{422A}-\x{4246}' . +'\x{4248}-\x{4263}\x{4265}-\x{428B}\x{428D}-\x{42A1}\x{42A3}-\x{42C4}\x{42C8}-\x{42DC}\x{42DE}-\x{430A}' . +'\x{430C}-\x{4335}\x{4337}\x{4342}-\x{435F}\x{4361}-\x{439A}\x{439C}-\x{439D}\x{439F}-\x{43A4}' . +'\x{43A6}-\x{43EC}\x{43EF}-\x{4405}\x{4407}-\x{4429}\x{442B}-\x{4455}\x{4457}-\x{4468}\x{446A}-\x{446D}' . +'\x{446F}-\x{4476}\x{4479}-\x{447D}\x{447F}-\x{4486}\x{4488}-\x{4490}\x{4492}-\x{4498}\x{449A}-\x{44AD}' . +'\x{44B0}-\x{44BD}\x{44C1}-\x{44D3}\x{44D6}-\x{44E7}\x{44EA}\x{44EC}-\x{44FA}\x{44FC}-\x{4541}' . +'\x{4543}-\x{454F}\x{4551}-\x{4562}\x{4564}-\x{4575}\x{4577}-\x{45AB}\x{45AD}-\x{45BD}\x{45BF}-\x{45D5}' . +'\x{45D7}-\x{45EC}\x{45EE}-\x{45F2}\x{45F4}-\x{45FA}\x{45FC}-\x{461A}\x{461C}-\x{461D}\x{461F}-\x{4631}' . +'\x{4633}-\x{4649}\x{464C}\x{464E}-\x{4652}\x{4654}-\x{466A}\x{466C}-\x{4675}\x{4677}-\x{467A}' . +'\x{467C}-\x{4694}\x{4696}-\x{46A3}\x{46A5}-\x{46AB}\x{46AD}-\x{46D2}\x{46D4}-\x{4723}\x{4729}-\x{4732}' . +'\x{4734}-\x{4758}\x{475A}\x{475C}-\x{478B}\x{478D}\x{4791}-\x{47B1}\x{47B3}-\x{47F1}' . +'\x{47F3}-\x{480B}\x{480D}-\x{4815}\x{4817}-\x{4839}\x{483B}-\x{4870}\x{4872}-\x{487A}\x{487C}-\x{487F}' . +'\x{4883}-\x{488E}\x{4890}-\x{4896}\x{4899}-\x{48A2}\x{48A4}-\x{48B9}\x{48BB}-\x{48C8}\x{48CA}-\x{48D1}' . +'\x{48D3}-\x{48E5}\x{48E7}-\x{48F2}\x{48F4}-\x{48FF}\x{4901}-\x{4922}\x{4924}-\x{4928}\x{492A}-\x{4931}' . +'\x{4933}-\x{495B}\x{495D}-\x{4978}\x{497A}\x{497D}\x{4982}-\x{4983}\x{4985}-\x{49A8}' . +'\x{49AA}-\x{49AF}\x{49B1}-\x{49B7}\x{49B9}-\x{49BD}\x{49C1}-\x{49C7}\x{49C9}-\x{49CE}\x{49D0}-\x{49E8}' . +'\x{49EA}\x{49EC}\x{49EE}-\x{4A19}\x{4A1B}-\x{4A43}\x{4A45}-\x{4A4D}\x{4A4F}-\x{4A9E}' . +'\x{4AA0}-\x{4AA9}\x{4AAB}-\x{4B4E}\x{4B50}-\x{4B5B}\x{4B5D}-\x{4B69}\x{4B6B}-\x{4BC2}\x{4BC6}-\x{4BE8}' . +'\x{4BEA}-\x{4BFA}\x{4BFC}-\x{4C06}\x{4C08}-\x{4C2D}\x{4C2F}-\x{4C32}\x{4C34}-\x{4C35}\x{4C37}-\x{4C69}' . +'\x{4C6B}-\x{4C73}\x{4C75}-\x{4C86}\x{4C88}-\x{4C97}\x{4C99}-\x{4C9C}\x{4C9F}-\x{4CA3}\x{4CA5}-\x{4CB5}' . +'\x{4CB7}-\x{4CF8}\x{4CFA}-\x{4D27}\x{4D29}-\x{4DAC}\x{4DAE}-\x{4DB1}\x{4DB3}-\x{4DB5}\x{4E00}-\x{4E54}' . +'\x{4E56}-\x{4E89}\x{4E8B}-\x{4EEC}\x{4EEE}-\x{4FAC}\x{4FAE}-\x{503C}\x{503E}-\x{51E5}\x{51E7}-\x{5270}' . +'\x{5272}-\x{56A1}\x{56A3}-\x{5840}\x{5842}-\x{58B5}\x{58B7}-\x{58CB}\x{58CD}-\x{5BC8}\x{5BCA}-\x{5C01}' . +'\x{5C03}-\x{5C25}\x{5C27}-\x{5D5B}\x{5D5D}-\x{5F08}\x{5F0A}-\x{61F3}\x{61F5}-\x{63BA}\x{63BC}-\x{6441}' . +'\x{6443}-\x{657C}\x{657E}-\x{663E}\x{6640}-\x{66FC}\x{66FE}-\x{6728}\x{672A}-\x{6766}\x{6768}-\x{67A8}' . +'\x{67AA}-\x{685B}\x{685D}-\x{685E}\x{6860}-\x{68B9}\x{68BB}-\x{6AC8}\x{6ACA}-\x{6BB0}\x{6BB2}-\x{6C16}' . +'\x{6C18}-\x{6D9B}\x{6D9D}-\x{6E12}\x{6E14}-\x{6E8B}\x{6E8D}-\x{704D}\x{704F}-\x{7113}\x{7115}-\x{713B}' . +'\x{713D}-\x{7154}\x{7156}-\x{729F}\x{72A1}-\x{731E}\x{7320}-\x{7362}\x{7364}-\x{7533}\x{7535}-\x{7551}' . +'\x{7553}-\x{7572}\x{7574}-\x{75E8}\x{75EA}-\x{7679}\x{767B}-\x{783E}\x{7840}-\x{7A62}\x{7A64}-\x{7AC2}' . +'\x{7AC4}-\x{7B06}\x{7B08}-\x{7B79}\x{7B7B}-\x{7BCE}\x{7BD0}-\x{7D99}\x{7D9B}-\x{7E49}\x{7E4C}-\x{8132}' . +'\x{8134}\x{8136}-\x{81D2}\x{81D4}-\x{8216}\x{8218}-\x{822D}\x{822F}-\x{83B4}\x{83B6}-\x{841F}' . +'\x{8421}-\x{86CC}\x{86CE}-\x{874A}\x{874C}-\x{877E}\x{8780}-\x{8A32}\x{8A34}-\x{8B71}\x{8B73}-\x{8B8E}' . +'\x{8B90}-\x{8DE4}\x{8DE6}-\x{8E9A}\x{8E9C}-\x{8EE1}\x{8EE4}-\x{8F0B}\x{8F0D}-\x{8FB9}\x{8FBB}-\x{9038}' . +'\x{903A}-\x{9196}\x{9198}-\x{91A3}\x{91A5}-\x{91B7}\x{91B9}-\x{91C7}\x{91C9}-\x{91E0}\x{91E2}-\x{91FB}' . +'\x{91FD}-\x{922B}\x{922D}-\x{9270}\x{9272}-\x{9420}\x{9422}-\x{9664}\x{9666}-\x{9679}\x{967B}-\x{9770}' . +'\x{9772}-\x{982B}\x{982D}-\x{98ED}\x{98EF}-\x{99C4}\x{99C6}-\x{9A11}\x{9A14}-\x{9A27}\x{9A29}-\x{9D0D}' . +'\x{9D0F}-\x{9D2B}\x{9D2D}-\x{9D8E}\x{9D90}-\x{9DC5}\x{9DC7}-\x{9E77}\x{9E79}-\x{9EB8}\x{9EBB}-\x{9F20}' . +'\x{9F22}-\x{9F61}\x{9F63}-\x{9FA5}\x{FA28}]{1,20}$/iu', + 6 => '/^[\x{002d}0-9A-Za-z]{1,63}$/iu', + 7 => '/^[\x{00A1}-\x{00FF}]{1,63}$/iu', + 8 => '/^[\x{0100}-\x{017f}]{1,63}$/iu', + 9 => '/^[\x{0180}-\x{024f}]{1,63}$/iu', + 10 => '/^[\x{0250}-\x{02af}]{1,63}$/iu', + 11 => '/^[\x{02b0}-\x{02ff}]{1,63}$/iu', + 12 => '/^[\x{0300}-\x{036f}]{1,63}$/iu', + 13 => '/^[\x{0370}-\x{03ff}]{1,63}$/iu', + 14 => '/^[\x{0400}-\x{04ff}]{1,63}$/iu', + 15 => '/^[\x{0500}-\x{052f}]{1,63}$/iu', + 16 => '/^[\x{0530}-\x{058F}]{1,63}$/iu', + 17 => '/^[\x{0590}-\x{05FF}]{1,63}$/iu', + 18 => '/^[\x{0600}-\x{06FF}]{1,63}$/iu', + 19 => '/^[\x{0700}-\x{074F}]{1,63}$/iu', + 20 => '/^[\x{0780}-\x{07BF}]{1,63}$/iu', + 21 => '/^[\x{0900}-\x{097F}]{1,63}$/iu', + 22 => '/^[\x{0980}-\x{09FF}]{1,63}$/iu', + 23 => '/^[\x{0A00}-\x{0A7F}]{1,63}$/iu', + 24 => '/^[\x{0A80}-\x{0AFF}]{1,63}$/iu', + 25 => '/^[\x{0B00}-\x{0B7F}]{1,63}$/iu', + 26 => '/^[\x{0B80}-\x{0BFF}]{1,63}$/iu', + 27 => '/^[\x{0C00}-\x{0C7F}]{1,63}$/iu', + 28 => '/^[\x{0C80}-\x{0CFF}]{1,63}$/iu', + 29 => '/^[\x{0D00}-\x{0D7F}]{1,63}$/iu', + 30 => '/^[\x{0D80}-\x{0DFF}]{1,63}$/iu', + 31 => '/^[\x{0E00}-\x{0E7F}]{1,63}$/iu', + 32 => '/^[\x{0E80}-\x{0EFF}]{1,63}$/iu', + 33 => '/^[\x{0F00}-\x{0FFF}]{1,63}$/iu', + 34 => '/^[\x{1000}-\x{109F}]{1,63}$/iu', + 35 => '/^[\x{10A0}-\x{10FF}]{1,63}$/iu', + 36 => '/^[\x{1100}-\x{11FF}]{1,63}$/iu', + 37 => '/^[\x{1200}-\x{137F}]{1,63}$/iu', + 38 => '/^[\x{13A0}-\x{13FF}]{1,63}$/iu', + 39 => '/^[\x{1400}-\x{167F}]{1,63}$/iu', + 40 => '/^[\x{1680}-\x{169F}]{1,63}$/iu', + 41 => '/^[\x{16A0}-\x{16FF}]{1,63}$/iu', + 42 => '/^[\x{1700}-\x{171F}]{1,63}$/iu', + 43 => '/^[\x{1720}-\x{173F}]{1,63}$/iu', + 44 => '/^[\x{1740}-\x{175F}]{1,63}$/iu', + 45 => '/^[\x{1760}-\x{177F}]{1,63}$/iu', + 46 => '/^[\x{1780}-\x{17FF}]{1,63}$/iu', + 47 => '/^[\x{1800}-\x{18AF}]{1,63}$/iu', + 48 => '/^[\x{1E00}-\x{1EFF}]{1,63}$/iu', + 49 => '/^[\x{1F00}-\x{1FFF}]{1,63}$/iu', + 50 => '/^[\x{2070}-\x{209F}]{1,63}$/iu', + 51 => '/^[\x{2100}-\x{214F}]{1,63}$/iu', + 52 => '/^[\x{2150}-\x{218F}]{1,63}$/iu', + 53 => '/^[\x{2460}-\x{24FF}]{1,63}$/iu', + 54 => '/^[\x{2E80}-\x{2EFF}]{1,63}$/iu', + 55 => '/^[\x{2F00}-\x{2FDF}]{1,63}$/iu', + 56 => '/^[\x{2FF0}-\x{2FFF}]{1,63}$/iu', + 57 => '/^[\x{3040}-\x{309F}]{1,63}$/iu', + 58 => '/^[\x{30A0}-\x{30FF}]{1,63}$/iu', + 59 => '/^[\x{3100}-\x{312F}]{1,63}$/iu', + 60 => '/^[\x{3130}-\x{318F}]{1,63}$/iu', + 61 => '/^[\x{3190}-\x{319F}]{1,63}$/iu', + 62 => '/^[\x{31A0}-\x{31BF}]{1,63}$/iu', + 63 => '/^[\x{31F0}-\x{31FF}]{1,63}$/iu', + 64 => '/^[\x{3200}-\x{32FF}]{1,63}$/iu', + 65 => '/^[\x{3300}-\x{33FF}]{1,63}$/iu', + 66 => '/^[\x{3400}-\x{4DBF}]{1,63}$/iu', + 67 => '/^[\x{4E00}-\x{9FFF}]{1,63}$/iu', + 68 => '/^[\x{A000}-\x{A48F}]{1,63}$/iu', + 69 => '/^[\x{A490}-\x{A4CF}]{1,63}$/iu', + 70 => '/^[\x{AC00}-\x{D7AF}]{1,63}$/iu', + 73 => '/^[\x{F900}-\x{FAFF}]{1,63}$/iu', + 74 => '/^[\x{FB00}-\x{FB4F}]{1,63}$/iu', + 75 => '/^[\x{FB50}-\x{FDFF}]{1,63}$/iu', + 76 => '/^[\x{FE20}-\x{FE2F}]{1,63}$/iu', + 77 => '/^[\x{FE70}-\x{FEFF}]{1,63}$/iu', + 78 => '/^[\x{FF00}-\x{FFEF}]{1,63}$/iu', + 79 => '/^[\x{20000}-\x{2A6DF}]{1,63}$/iu', + 80 => '/^[\x{2F800}-\x{2FA1F}]{1,63}$/iu', +]; diff --git a/lib/laminas/laminas-validator/src/Hostname/Jp.php b/lib/laminas/laminas-validator/src/Hostname/Jp.php new file mode 100644 index 000000000..160349c16 --- /dev/null +++ b/lib/laminas/laminas-validator/src/Hostname/Jp.php @@ -0,0 +1,724 @@ + '/^[\x{002d}0-9a-z\x{3005}-\x{3007}\x{3041}-\x{3093}\x{309D}\x{309E}' . + '\x{30A1}-\x{30F6}\x{30FC}' . + '\x{30FD}\x{30FE}\x{4E00}\x{4E01}\x{4E03}\x{4E07}\x{4E08}\x{4E09}\x{4E0A}' . + '\x{4E0B}\x{4E0D}\x{4E0E}\x{4E10}\x{4E11}\x{4E14}\x{4E15}\x{4E16}\x{4E17}' . + '\x{4E18}\x{4E19}\x{4E1E}\x{4E21}\x{4E26}\x{4E2A}\x{4E2D}\x{4E31}\x{4E32}' . + '\x{4E36}\x{4E38}\x{4E39}\x{4E3B}\x{4E3C}\x{4E3F}\x{4E42}\x{4E43}\x{4E45}' . + '\x{4E4B}\x{4E4D}\x{4E4E}\x{4E4F}\x{4E55}\x{4E56}\x{4E57}\x{4E58}\x{4E59}' . + '\x{4E5D}\x{4E5E}\x{4E5F}\x{4E62}\x{4E71}\x{4E73}\x{4E7E}\x{4E80}\x{4E82}' . + '\x{4E85}\x{4E86}\x{4E88}\x{4E89}\x{4E8A}\x{4E8B}\x{4E8C}\x{4E8E}\x{4E91}' . + '\x{4E92}\x{4E94}\x{4E95}\x{4E98}\x{4E99}\x{4E9B}\x{4E9C}\x{4E9E}\x{4E9F}' . + '\x{4EA0}\x{4EA1}\x{4EA2}\x{4EA4}\x{4EA5}\x{4EA6}\x{4EA8}\x{4EAB}\x{4EAC}' . + '\x{4EAD}\x{4EAE}\x{4EB0}\x{4EB3}\x{4EB6}\x{4EBA}\x{4EC0}\x{4EC1}\x{4EC2}' . + '\x{4EC4}\x{4EC6}\x{4EC7}\x{4ECA}\x{4ECB}\x{4ECD}\x{4ECE}\x{4ECF}\x{4ED4}' . + '\x{4ED5}\x{4ED6}\x{4ED7}\x{4ED8}\x{4ED9}\x{4EDD}\x{4EDE}\x{4EDF}\x{4EE3}' . + '\x{4EE4}\x{4EE5}\x{4EED}\x{4EEE}\x{4EF0}\x{4EF2}\x{4EF6}\x{4EF7}\x{4EFB}' . + '\x{4F01}\x{4F09}\x{4F0A}\x{4F0D}\x{4F0E}\x{4F0F}\x{4F10}\x{4F11}\x{4F1A}' . + '\x{4F1C}\x{4F1D}\x{4F2F}\x{4F30}\x{4F34}\x{4F36}\x{4F38}\x{4F3A}\x{4F3C}' . + '\x{4F3D}\x{4F43}\x{4F46}\x{4F47}\x{4F4D}\x{4F4E}\x{4F4F}\x{4F50}\x{4F51}' . + '\x{4F53}\x{4F55}\x{4F57}\x{4F59}\x{4F5A}\x{4F5B}\x{4F5C}\x{4F5D}\x{4F5E}' . + '\x{4F69}\x{4F6F}\x{4F70}\x{4F73}\x{4F75}\x{4F76}\x{4F7B}\x{4F7C}\x{4F7F}' . + '\x{4F83}\x{4F86}\x{4F88}\x{4F8B}\x{4F8D}\x{4F8F}\x{4F91}\x{4F96}\x{4F98}' . + '\x{4F9B}\x{4F9D}\x{4FA0}\x{4FA1}\x{4FAB}\x{4FAD}\x{4FAE}\x{4FAF}\x{4FB5}' . + '\x{4FB6}\x{4FBF}\x{4FC2}\x{4FC3}\x{4FC4}\x{4FCA}\x{4FCE}\x{4FD0}\x{4FD1}' . + '\x{4FD4}\x{4FD7}\x{4FD8}\x{4FDA}\x{4FDB}\x{4FDD}\x{4FDF}\x{4FE1}\x{4FE3}' . + '\x{4FE4}\x{4FE5}\x{4FEE}\x{4FEF}\x{4FF3}\x{4FF5}\x{4FF6}\x{4FF8}\x{4FFA}' . + '\x{4FFE}\x{5005}\x{5006}\x{5009}\x{500B}\x{500D}\x{500F}\x{5011}\x{5012}' . + '\x{5014}\x{5016}\x{5019}\x{501A}\x{501F}\x{5021}\x{5023}\x{5024}\x{5025}' . + '\x{5026}\x{5028}\x{5029}\x{502A}\x{502B}\x{502C}\x{502D}\x{5036}\x{5039}' . + '\x{5043}\x{5047}\x{5048}\x{5049}\x{504F}\x{5050}\x{5055}\x{5056}\x{505A}' . + '\x{505C}\x{5065}\x{506C}\x{5072}\x{5074}\x{5075}\x{5076}\x{5078}\x{507D}' . + '\x{5080}\x{5085}\x{508D}\x{5091}\x{5098}\x{5099}\x{509A}\x{50AC}\x{50AD}' . + '\x{50B2}\x{50B3}\x{50B4}\x{50B5}\x{50B7}\x{50BE}\x{50C2}\x{50C5}\x{50C9}' . + '\x{50CA}\x{50CD}\x{50CF}\x{50D1}\x{50D5}\x{50D6}\x{50DA}\x{50DE}\x{50E3}' . + '\x{50E5}\x{50E7}\x{50ED}\x{50EE}\x{50F5}\x{50F9}\x{50FB}\x{5100}\x{5101}' . + '\x{5102}\x{5104}\x{5109}\x{5112}\x{5114}\x{5115}\x{5116}\x{5118}\x{511A}' . + '\x{511F}\x{5121}\x{512A}\x{5132}\x{5137}\x{513A}\x{513B}\x{513C}\x{513F}' . + '\x{5140}\x{5141}\x{5143}\x{5144}\x{5145}\x{5146}\x{5147}\x{5148}\x{5149}' . + '\x{514B}\x{514C}\x{514D}\x{514E}\x{5150}\x{5152}\x{5154}\x{515A}\x{515C}' . + '\x{5162}\x{5165}\x{5168}\x{5169}\x{516A}\x{516B}\x{516C}\x{516D}\x{516E}' . + '\x{5171}\x{5175}\x{5176}\x{5177}\x{5178}\x{517C}\x{5180}\x{5182}\x{5185}' . + '\x{5186}\x{5189}\x{518A}\x{518C}\x{518D}\x{518F}\x{5190}\x{5191}\x{5192}' . + '\x{5193}\x{5195}\x{5196}\x{5197}\x{5199}\x{51A0}\x{51A2}\x{51A4}\x{51A5}' . + '\x{51A6}\x{51A8}\x{51A9}\x{51AA}\x{51AB}\x{51AC}\x{51B0}\x{51B1}\x{51B2}' . + '\x{51B3}\x{51B4}\x{51B5}\x{51B6}\x{51B7}\x{51BD}\x{51C4}\x{51C5}\x{51C6}' . + '\x{51C9}\x{51CB}\x{51CC}\x{51CD}\x{51D6}\x{51DB}\x{51DC}\x{51DD}\x{51E0}' . + '\x{51E1}\x{51E6}\x{51E7}\x{51E9}\x{51EA}\x{51ED}\x{51F0}\x{51F1}\x{51F5}' . + '\x{51F6}\x{51F8}\x{51F9}\x{51FA}\x{51FD}\x{51FE}\x{5200}\x{5203}\x{5204}' . + '\x{5206}\x{5207}\x{5208}\x{520A}\x{520B}\x{520E}\x{5211}\x{5214}\x{5217}' . + '\x{521D}\x{5224}\x{5225}\x{5227}\x{5229}\x{522A}\x{522E}\x{5230}\x{5233}' . + '\x{5236}\x{5237}\x{5238}\x{5239}\x{523A}\x{523B}\x{5243}\x{5244}\x{5247}' . + '\x{524A}\x{524B}\x{524C}\x{524D}\x{524F}\x{5254}\x{5256}\x{525B}\x{525E}' . + '\x{5263}\x{5264}\x{5265}\x{5269}\x{526A}\x{526F}\x{5270}\x{5271}\x{5272}' . + '\x{5273}\x{5274}\x{5275}\x{527D}\x{527F}\x{5283}\x{5287}\x{5288}\x{5289}' . + '\x{528D}\x{5291}\x{5292}\x{5294}\x{529B}\x{529F}\x{52A0}\x{52A3}\x{52A9}' . + '\x{52AA}\x{52AB}\x{52AC}\x{52AD}\x{52B1}\x{52B4}\x{52B5}\x{52B9}\x{52BC}' . + '\x{52BE}\x{52C1}\x{52C3}\x{52C5}\x{52C7}\x{52C9}\x{52CD}\x{52D2}\x{52D5}' . + '\x{52D7}\x{52D8}\x{52D9}\x{52DD}\x{52DE}\x{52DF}\x{52E0}\x{52E2}\x{52E3}' . + '\x{52E4}\x{52E6}\x{52E7}\x{52F2}\x{52F3}\x{52F5}\x{52F8}\x{52F9}\x{52FA}' . + '\x{52FE}\x{52FF}\x{5301}\x{5302}\x{5305}\x{5306}\x{5308}\x{530D}\x{530F}' . + '\x{5310}\x{5315}\x{5316}\x{5317}\x{5319}\x{531A}\x{531D}\x{5320}\x{5321}' . + '\x{5323}\x{532A}\x{532F}\x{5331}\x{5333}\x{5338}\x{5339}\x{533A}\x{533B}' . + '\x{533F}\x{5340}\x{5341}\x{5343}\x{5345}\x{5346}\x{5347}\x{5348}\x{5349}' . + '\x{534A}\x{534D}\x{5351}\x{5352}\x{5353}\x{5354}\x{5357}\x{5358}\x{535A}' . + '\x{535C}\x{535E}\x{5360}\x{5366}\x{5369}\x{536E}\x{536F}\x{5370}\x{5371}' . + '\x{5373}\x{5374}\x{5375}\x{5377}\x{5378}\x{537B}\x{537F}\x{5382}\x{5384}' . + '\x{5396}\x{5398}\x{539A}\x{539F}\x{53A0}\x{53A5}\x{53A6}\x{53A8}\x{53A9}' . + '\x{53AD}\x{53AE}\x{53B0}\x{53B3}\x{53B6}\x{53BB}\x{53C2}\x{53C3}\x{53C8}' . + '\x{53C9}\x{53CA}\x{53CB}\x{53CC}\x{53CD}\x{53CE}\x{53D4}\x{53D6}\x{53D7}' . + '\x{53D9}\x{53DB}\x{53DF}\x{53E1}\x{53E2}\x{53E3}\x{53E4}\x{53E5}\x{53E8}' . + '\x{53E9}\x{53EA}\x{53EB}\x{53EC}\x{53ED}\x{53EE}\x{53EF}\x{53F0}\x{53F1}' . + '\x{53F2}\x{53F3}\x{53F6}\x{53F7}\x{53F8}\x{53FA}\x{5401}\x{5403}\x{5404}' . + '\x{5408}\x{5409}\x{540A}\x{540B}\x{540C}\x{540D}\x{540E}\x{540F}\x{5410}' . + '\x{5411}\x{541B}\x{541D}\x{541F}\x{5420}\x{5426}\x{5429}\x{542B}\x{542C}' . + '\x{542D}\x{542E}\x{5436}\x{5438}\x{5439}\x{543B}\x{543C}\x{543D}\x{543E}' . + '\x{5440}\x{5442}\x{5446}\x{5448}\x{5449}\x{544A}\x{544E}\x{5451}\x{545F}' . + '\x{5468}\x{546A}\x{5470}\x{5471}\x{5473}\x{5475}\x{5476}\x{5477}\x{547B}' . + '\x{547C}\x{547D}\x{5480}\x{5484}\x{5486}\x{548B}\x{548C}\x{548E}\x{548F}' . + '\x{5490}\x{5492}\x{54A2}\x{54A4}\x{54A5}\x{54A8}\x{54AB}\x{54AC}\x{54AF}' . + '\x{54B2}\x{54B3}\x{54B8}\x{54BC}\x{54BD}\x{54BE}\x{54C0}\x{54C1}\x{54C2}' . + '\x{54C4}\x{54C7}\x{54C8}\x{54C9}\x{54D8}\x{54E1}\x{54E2}\x{54E5}\x{54E6}' . + '\x{54E8}\x{54E9}\x{54ED}\x{54EE}\x{54F2}\x{54FA}\x{54FD}\x{5504}\x{5506}' . + '\x{5507}\x{550F}\x{5510}\x{5514}\x{5516}\x{552E}\x{552F}\x{5531}\x{5533}' . + '\x{5538}\x{5539}\x{553E}\x{5540}\x{5544}\x{5545}\x{5546}\x{554C}\x{554F}' . + '\x{5553}\x{5556}\x{5557}\x{555C}\x{555D}\x{5563}\x{557B}\x{557C}\x{557E}' . + '\x{5580}\x{5583}\x{5584}\x{5587}\x{5589}\x{558A}\x{558B}\x{5598}\x{5599}' . + '\x{559A}\x{559C}\x{559D}\x{559E}\x{559F}\x{55A7}\x{55A8}\x{55A9}\x{55AA}' . + '\x{55AB}\x{55AC}\x{55AE}\x{55B0}\x{55B6}\x{55C4}\x{55C5}\x{55C7}\x{55D4}' . + '\x{55DA}\x{55DC}\x{55DF}\x{55E3}\x{55E4}\x{55F7}\x{55F9}\x{55FD}\x{55FE}' . + '\x{5606}\x{5609}\x{5614}\x{5616}\x{5617}\x{5618}\x{561B}\x{5629}\x{562F}' . + '\x{5631}\x{5632}\x{5634}\x{5636}\x{5638}\x{5642}\x{564C}\x{564E}\x{5650}' . + '\x{565B}\x{5664}\x{5668}\x{566A}\x{566B}\x{566C}\x{5674}\x{5678}\x{567A}' . + '\x{5680}\x{5686}\x{5687}\x{568A}\x{568F}\x{5694}\x{56A0}\x{56A2}\x{56A5}' . + '\x{56AE}\x{56B4}\x{56B6}\x{56BC}\x{56C0}\x{56C1}\x{56C2}\x{56C3}\x{56C8}' . + '\x{56CE}\x{56D1}\x{56D3}\x{56D7}\x{56D8}\x{56DA}\x{56DB}\x{56DE}\x{56E0}' . + '\x{56E3}\x{56EE}\x{56F0}\x{56F2}\x{56F3}\x{56F9}\x{56FA}\x{56FD}\x{56FF}' . + '\x{5700}\x{5703}\x{5704}\x{5708}\x{5709}\x{570B}\x{570D}\x{570F}\x{5712}' . + '\x{5713}\x{5716}\x{5718}\x{571C}\x{571F}\x{5726}\x{5727}\x{5728}\x{572D}' . + '\x{5730}\x{5737}\x{5738}\x{573B}\x{5740}\x{5742}\x{5747}\x{574A}\x{574E}' . + '\x{574F}\x{5750}\x{5751}\x{5761}\x{5764}\x{5766}\x{5769}\x{576A}\x{577F}' . + '\x{5782}\x{5788}\x{5789}\x{578B}\x{5793}\x{57A0}\x{57A2}\x{57A3}\x{57A4}' . + '\x{57AA}\x{57B0}\x{57B3}\x{57C0}\x{57C3}\x{57C6}\x{57CB}\x{57CE}\x{57D2}' . + '\x{57D3}\x{57D4}\x{57D6}\x{57DC}\x{57DF}\x{57E0}\x{57E3}\x{57F4}\x{57F7}' . + '\x{57F9}\x{57FA}\x{57FC}\x{5800}\x{5802}\x{5805}\x{5806}\x{580A}\x{580B}' . + '\x{5815}\x{5819}\x{581D}\x{5821}\x{5824}\x{582A}\x{582F}\x{5830}\x{5831}' . + '\x{5834}\x{5835}\x{583A}\x{583D}\x{5840}\x{5841}\x{584A}\x{584B}\x{5851}' . + '\x{5852}\x{5854}\x{5857}\x{5858}\x{5859}\x{585A}\x{585E}\x{5862}\x{5869}' . + '\x{586B}\x{5870}\x{5872}\x{5875}\x{5879}\x{587E}\x{5883}\x{5885}\x{5893}' . + '\x{5897}\x{589C}\x{589F}\x{58A8}\x{58AB}\x{58AE}\x{58B3}\x{58B8}\x{58B9}' . + '\x{58BA}\x{58BB}\x{58BE}\x{58C1}\x{58C5}\x{58C7}\x{58CA}\x{58CC}\x{58D1}' . + '\x{58D3}\x{58D5}\x{58D7}\x{58D8}\x{58D9}\x{58DC}\x{58DE}\x{58DF}\x{58E4}' . + '\x{58E5}\x{58EB}\x{58EC}\x{58EE}\x{58EF}\x{58F0}\x{58F1}\x{58F2}\x{58F7}' . + '\x{58F9}\x{58FA}\x{58FB}\x{58FC}\x{58FD}\x{5902}\x{5909}\x{590A}\x{590F}' . + '\x{5910}\x{5915}\x{5916}\x{5918}\x{5919}\x{591A}\x{591B}\x{591C}\x{5922}' . + '\x{5925}\x{5927}\x{5929}\x{592A}\x{592B}\x{592C}\x{592D}\x{592E}\x{5931}' . + '\x{5932}\x{5937}\x{5938}\x{593E}\x{5944}\x{5947}\x{5948}\x{5949}\x{594E}' . + '\x{594F}\x{5950}\x{5951}\x{5954}\x{5955}\x{5957}\x{5958}\x{595A}\x{5960}' . + '\x{5962}\x{5965}\x{5967}\x{5968}\x{5969}\x{596A}\x{596C}\x{596E}\x{5973}' . + '\x{5974}\x{5978}\x{597D}\x{5981}\x{5982}\x{5983}\x{5984}\x{598A}\x{598D}' . + '\x{5993}\x{5996}\x{5999}\x{599B}\x{599D}\x{59A3}\x{59A5}\x{59A8}\x{59AC}' . + '\x{59B2}\x{59B9}\x{59BB}\x{59BE}\x{59C6}\x{59C9}\x{59CB}\x{59D0}\x{59D1}' . + '\x{59D3}\x{59D4}\x{59D9}\x{59DA}\x{59DC}\x{59E5}\x{59E6}\x{59E8}\x{59EA}' . + '\x{59EB}\x{59F6}\x{59FB}\x{59FF}\x{5A01}\x{5A03}\x{5A09}\x{5A11}\x{5A18}' . + '\x{5A1A}\x{5A1C}\x{5A1F}\x{5A20}\x{5A25}\x{5A29}\x{5A2F}\x{5A35}\x{5A36}' . + '\x{5A3C}\x{5A40}\x{5A41}\x{5A46}\x{5A49}\x{5A5A}\x{5A62}\x{5A66}\x{5A6A}' . + '\x{5A6C}\x{5A7F}\x{5A92}\x{5A9A}\x{5A9B}\x{5ABC}\x{5ABD}\x{5ABE}\x{5AC1}' . + '\x{5AC2}\x{5AC9}\x{5ACB}\x{5ACC}\x{5AD0}\x{5AD6}\x{5AD7}\x{5AE1}\x{5AE3}' . + '\x{5AE6}\x{5AE9}\x{5AFA}\x{5AFB}\x{5B09}\x{5B0B}\x{5B0C}\x{5B16}\x{5B22}' . + '\x{5B2A}\x{5B2C}\x{5B30}\x{5B32}\x{5B36}\x{5B3E}\x{5B40}\x{5B43}\x{5B45}' . + '\x{5B50}\x{5B51}\x{5B54}\x{5B55}\x{5B57}\x{5B58}\x{5B5A}\x{5B5B}\x{5B5C}' . + '\x{5B5D}\x{5B5F}\x{5B63}\x{5B64}\x{5B65}\x{5B66}\x{5B69}\x{5B6B}\x{5B70}' . + '\x{5B71}\x{5B73}\x{5B75}\x{5B78}\x{5B7A}\x{5B80}\x{5B83}\x{5B85}\x{5B87}' . + '\x{5B88}\x{5B89}\x{5B8B}\x{5B8C}\x{5B8D}\x{5B8F}\x{5B95}\x{5B97}\x{5B98}' . + '\x{5B99}\x{5B9A}\x{5B9B}\x{5B9C}\x{5B9D}\x{5B9F}\x{5BA2}\x{5BA3}\x{5BA4}' . + '\x{5BA5}\x{5BA6}\x{5BAE}\x{5BB0}\x{5BB3}\x{5BB4}\x{5BB5}\x{5BB6}\x{5BB8}' . + '\x{5BB9}\x{5BBF}\x{5BC2}\x{5BC3}\x{5BC4}\x{5BC5}\x{5BC6}\x{5BC7}\x{5BC9}' . + '\x{5BCC}\x{5BD0}\x{5BD2}\x{5BD3}\x{5BD4}\x{5BDB}\x{5BDD}\x{5BDE}\x{5BDF}' . + '\x{5BE1}\x{5BE2}\x{5BE4}\x{5BE5}\x{5BE6}\x{5BE7}\x{5BE8}\x{5BE9}\x{5BEB}' . + '\x{5BEE}\x{5BF0}\x{5BF3}\x{5BF5}\x{5BF6}\x{5BF8}\x{5BFA}\x{5BFE}\x{5BFF}' . + '\x{5C01}\x{5C02}\x{5C04}\x{5C05}\x{5C06}\x{5C07}\x{5C08}\x{5C09}\x{5C0A}' . + '\x{5C0B}\x{5C0D}\x{5C0E}\x{5C0F}\x{5C11}\x{5C13}\x{5C16}\x{5C1A}\x{5C20}' . + '\x{5C22}\x{5C24}\x{5C28}\x{5C2D}\x{5C31}\x{5C38}\x{5C39}\x{5C3A}\x{5C3B}' . + '\x{5C3C}\x{5C3D}\x{5C3E}\x{5C3F}\x{5C40}\x{5C41}\x{5C45}\x{5C46}\x{5C48}' . + '\x{5C4A}\x{5C4B}\x{5C4D}\x{5C4E}\x{5C4F}\x{5C50}\x{5C51}\x{5C53}\x{5C55}' . + '\x{5C5E}\x{5C60}\x{5C61}\x{5C64}\x{5C65}\x{5C6C}\x{5C6E}\x{5C6F}\x{5C71}' . + '\x{5C76}\x{5C79}\x{5C8C}\x{5C90}\x{5C91}\x{5C94}\x{5CA1}\x{5CA8}\x{5CA9}' . + '\x{5CAB}\x{5CAC}\x{5CB1}\x{5CB3}\x{5CB6}\x{5CB7}\x{5CB8}\x{5CBB}\x{5CBC}' . + '\x{5CBE}\x{5CC5}\x{5CC7}\x{5CD9}\x{5CE0}\x{5CE1}\x{5CE8}\x{5CE9}\x{5CEA}' . + '\x{5CED}\x{5CEF}\x{5CF0}\x{5CF6}\x{5CFA}\x{5CFB}\x{5CFD}\x{5D07}\x{5D0B}' . + '\x{5D0E}\x{5D11}\x{5D14}\x{5D15}\x{5D16}\x{5D17}\x{5D18}\x{5D19}\x{5D1A}' . + '\x{5D1B}\x{5D1F}\x{5D22}\x{5D29}\x{5D4B}\x{5D4C}\x{5D4E}\x{5D50}\x{5D52}' . + '\x{5D5C}\x{5D69}\x{5D6C}\x{5D6F}\x{5D73}\x{5D76}\x{5D82}\x{5D84}\x{5D87}' . + '\x{5D8B}\x{5D8C}\x{5D90}\x{5D9D}\x{5DA2}\x{5DAC}\x{5DAE}\x{5DB7}\x{5DBA}' . + '\x{5DBC}\x{5DBD}\x{5DC9}\x{5DCC}\x{5DCD}\x{5DD2}\x{5DD3}\x{5DD6}\x{5DDB}' . + '\x{5DDD}\x{5DDE}\x{5DE1}\x{5DE3}\x{5DE5}\x{5DE6}\x{5DE7}\x{5DE8}\x{5DEB}' . + '\x{5DEE}\x{5DF1}\x{5DF2}\x{5DF3}\x{5DF4}\x{5DF5}\x{5DF7}\x{5DFB}\x{5DFD}' . + '\x{5DFE}\x{5E02}\x{5E03}\x{5E06}\x{5E0B}\x{5E0C}\x{5E11}\x{5E16}\x{5E19}' . + '\x{5E1A}\x{5E1B}\x{5E1D}\x{5E25}\x{5E2B}\x{5E2D}\x{5E2F}\x{5E30}\x{5E33}' . + '\x{5E36}\x{5E37}\x{5E38}\x{5E3D}\x{5E40}\x{5E43}\x{5E44}\x{5E45}\x{5E47}' . + '\x{5E4C}\x{5E4E}\x{5E54}\x{5E55}\x{5E57}\x{5E5F}\x{5E61}\x{5E62}\x{5E63}' . + '\x{5E64}\x{5E72}\x{5E73}\x{5E74}\x{5E75}\x{5E76}\x{5E78}\x{5E79}\x{5E7A}' . + '\x{5E7B}\x{5E7C}\x{5E7D}\x{5E7E}\x{5E7F}\x{5E81}\x{5E83}\x{5E84}\x{5E87}' . + '\x{5E8A}\x{5E8F}\x{5E95}\x{5E96}\x{5E97}\x{5E9A}\x{5E9C}\x{5EA0}\x{5EA6}' . + '\x{5EA7}\x{5EAB}\x{5EAD}\x{5EB5}\x{5EB6}\x{5EB7}\x{5EB8}\x{5EC1}\x{5EC2}' . + '\x{5EC3}\x{5EC8}\x{5EC9}\x{5ECA}\x{5ECF}\x{5ED0}\x{5ED3}\x{5ED6}\x{5EDA}' . + '\x{5EDB}\x{5EDD}\x{5EDF}\x{5EE0}\x{5EE1}\x{5EE2}\x{5EE3}\x{5EE8}\x{5EE9}' . + '\x{5EEC}\x{5EF0}\x{5EF1}\x{5EF3}\x{5EF4}\x{5EF6}\x{5EF7}\x{5EF8}\x{5EFA}' . + '\x{5EFB}\x{5EFC}\x{5EFE}\x{5EFF}\x{5F01}\x{5F03}\x{5F04}\x{5F09}\x{5F0A}' . + '\x{5F0B}\x{5F0C}\x{5F0D}\x{5F0F}\x{5F10}\x{5F11}\x{5F13}\x{5F14}\x{5F15}' . + '\x{5F16}\x{5F17}\x{5F18}\x{5F1B}\x{5F1F}\x{5F25}\x{5F26}\x{5F27}\x{5F29}' . + '\x{5F2D}\x{5F2F}\x{5F31}\x{5F35}\x{5F37}\x{5F38}\x{5F3C}\x{5F3E}\x{5F41}' . + '\x{5F48}\x{5F4A}\x{5F4C}\x{5F4E}\x{5F51}\x{5F53}\x{5F56}\x{5F57}\x{5F59}' . + '\x{5F5C}\x{5F5D}\x{5F61}\x{5F62}\x{5F66}\x{5F69}\x{5F6A}\x{5F6B}\x{5F6C}' . + '\x{5F6D}\x{5F70}\x{5F71}\x{5F73}\x{5F77}\x{5F79}\x{5F7C}\x{5F7F}\x{5F80}' . + '\x{5F81}\x{5F82}\x{5F83}\x{5F84}\x{5F85}\x{5F87}\x{5F88}\x{5F8A}\x{5F8B}' . + '\x{5F8C}\x{5F90}\x{5F91}\x{5F92}\x{5F93}\x{5F97}\x{5F98}\x{5F99}\x{5F9E}' . + '\x{5FA0}\x{5FA1}\x{5FA8}\x{5FA9}\x{5FAA}\x{5FAD}\x{5FAE}\x{5FB3}\x{5FB4}' . + '\x{5FB9}\x{5FBC}\x{5FBD}\x{5FC3}\x{5FC5}\x{5FCC}\x{5FCD}\x{5FD6}\x{5FD7}' . + '\x{5FD8}\x{5FD9}\x{5FDC}\x{5FDD}\x{5FE0}\x{5FE4}\x{5FEB}\x{5FF0}\x{5FF1}' . + '\x{5FF5}\x{5FF8}\x{5FFB}\x{5FFD}\x{5FFF}\x{600E}\x{600F}\x{6010}\x{6012}' . + '\x{6015}\x{6016}\x{6019}\x{601B}\x{601C}\x{601D}\x{6020}\x{6021}\x{6025}' . + '\x{6026}\x{6027}\x{6028}\x{6029}\x{602A}\x{602B}\x{602F}\x{6031}\x{603A}' . + '\x{6041}\x{6042}\x{6043}\x{6046}\x{604A}\x{604B}\x{604D}\x{6050}\x{6052}' . + '\x{6055}\x{6059}\x{605A}\x{605F}\x{6060}\x{6062}\x{6063}\x{6064}\x{6065}' . + '\x{6068}\x{6069}\x{606A}\x{606B}\x{606C}\x{606D}\x{606F}\x{6070}\x{6075}' . + '\x{6077}\x{6081}\x{6083}\x{6084}\x{6089}\x{608B}\x{608C}\x{608D}\x{6092}' . + '\x{6094}\x{6096}\x{6097}\x{609A}\x{609B}\x{609F}\x{60A0}\x{60A3}\x{60A6}' . + '\x{60A7}\x{60A9}\x{60AA}\x{60B2}\x{60B3}\x{60B4}\x{60B5}\x{60B6}\x{60B8}' . + '\x{60BC}\x{60BD}\x{60C5}\x{60C6}\x{60C7}\x{60D1}\x{60D3}\x{60D8}\x{60DA}' . + '\x{60DC}\x{60DF}\x{60E0}\x{60E1}\x{60E3}\x{60E7}\x{60E8}\x{60F0}\x{60F1}' . + '\x{60F3}\x{60F4}\x{60F6}\x{60F7}\x{60F9}\x{60FA}\x{60FB}\x{6100}\x{6101}' . + '\x{6103}\x{6106}\x{6108}\x{6109}\x{610D}\x{610E}\x{610F}\x{6115}\x{611A}' . + '\x{611B}\x{611F}\x{6121}\x{6127}\x{6128}\x{612C}\x{6134}\x{613C}\x{613D}' . + '\x{613E}\x{613F}\x{6142}\x{6144}\x{6147}\x{6148}\x{614A}\x{614B}\x{614C}' . + '\x{614D}\x{614E}\x{6153}\x{6155}\x{6158}\x{6159}\x{615A}\x{615D}\x{615F}' . + '\x{6162}\x{6163}\x{6165}\x{6167}\x{6168}\x{616B}\x{616E}\x{616F}\x{6170}' . + '\x{6171}\x{6173}\x{6174}\x{6175}\x{6176}\x{6177}\x{617E}\x{6182}\x{6187}' . + '\x{618A}\x{618E}\x{6190}\x{6191}\x{6194}\x{6196}\x{6199}\x{619A}\x{61A4}' . + '\x{61A7}\x{61A9}\x{61AB}\x{61AC}\x{61AE}\x{61B2}\x{61B6}\x{61BA}\x{61BE}' . + '\x{61C3}\x{61C6}\x{61C7}\x{61C8}\x{61C9}\x{61CA}\x{61CB}\x{61CC}\x{61CD}' . + '\x{61D0}\x{61E3}\x{61E6}\x{61F2}\x{61F4}\x{61F6}\x{61F7}\x{61F8}\x{61FA}' . + '\x{61FC}\x{61FD}\x{61FE}\x{61FF}\x{6200}\x{6208}\x{6209}\x{620A}\x{620C}' . + '\x{620D}\x{620E}\x{6210}\x{6211}\x{6212}\x{6214}\x{6216}\x{621A}\x{621B}' . + '\x{621D}\x{621E}\x{621F}\x{6221}\x{6226}\x{622A}\x{622E}\x{622F}\x{6230}' . + '\x{6232}\x{6233}\x{6234}\x{6238}\x{623B}\x{623F}\x{6240}\x{6241}\x{6247}' . + '\x{6248}\x{6249}\x{624B}\x{624D}\x{624E}\x{6253}\x{6255}\x{6258}\x{625B}' . + '\x{625E}\x{6260}\x{6263}\x{6268}\x{626E}\x{6271}\x{6276}\x{6279}\x{627C}' . + '\x{627E}\x{627F}\x{6280}\x{6282}\x{6283}\x{6284}\x{6289}\x{628A}\x{6291}' . + '\x{6292}\x{6293}\x{6294}\x{6295}\x{6296}\x{6297}\x{6298}\x{629B}\x{629C}' . + '\x{629E}\x{62AB}\x{62AC}\x{62B1}\x{62B5}\x{62B9}\x{62BB}\x{62BC}\x{62BD}' . + '\x{62C2}\x{62C5}\x{62C6}\x{62C7}\x{62C8}\x{62C9}\x{62CA}\x{62CC}\x{62CD}' . + '\x{62CF}\x{62D0}\x{62D1}\x{62D2}\x{62D3}\x{62D4}\x{62D7}\x{62D8}\x{62D9}' . + '\x{62DB}\x{62DC}\x{62DD}\x{62E0}\x{62E1}\x{62EC}\x{62ED}\x{62EE}\x{62EF}' . + '\x{62F1}\x{62F3}\x{62F5}\x{62F6}\x{62F7}\x{62FE}\x{62FF}\x{6301}\x{6302}' . + '\x{6307}\x{6308}\x{6309}\x{630C}\x{6311}\x{6319}\x{631F}\x{6327}\x{6328}' . + '\x{632B}\x{632F}\x{633A}\x{633D}\x{633E}\x{633F}\x{6349}\x{634C}\x{634D}' . + '\x{634F}\x{6350}\x{6355}\x{6357}\x{635C}\x{6367}\x{6368}\x{6369}\x{636B}' . + '\x{636E}\x{6372}\x{6376}\x{6377}\x{637A}\x{637B}\x{6380}\x{6383}\x{6388}' . + '\x{6389}\x{638C}\x{638E}\x{638F}\x{6392}\x{6396}\x{6398}\x{639B}\x{639F}' . + '\x{63A0}\x{63A1}\x{63A2}\x{63A3}\x{63A5}\x{63A7}\x{63A8}\x{63A9}\x{63AA}' . + '\x{63AB}\x{63AC}\x{63B2}\x{63B4}\x{63B5}\x{63BB}\x{63BE}\x{63C0}\x{63C3}' . + '\x{63C4}\x{63C6}\x{63C9}\x{63CF}\x{63D0}\x{63D2}\x{63D6}\x{63DA}\x{63DB}' . + '\x{63E1}\x{63E3}\x{63E9}\x{63EE}\x{63F4}\x{63F6}\x{63FA}\x{6406}\x{640D}' . + '\x{640F}\x{6413}\x{6416}\x{6417}\x{641C}\x{6426}\x{6428}\x{642C}\x{642D}' . + '\x{6434}\x{6436}\x{643A}\x{643E}\x{6442}\x{644E}\x{6458}\x{6467}\x{6469}' . + '\x{646F}\x{6476}\x{6478}\x{647A}\x{6483}\x{6488}\x{6492}\x{6493}\x{6495}' . + '\x{649A}\x{649E}\x{64A4}\x{64A5}\x{64A9}\x{64AB}\x{64AD}\x{64AE}\x{64B0}' . + '\x{64B2}\x{64B9}\x{64BB}\x{64BC}\x{64C1}\x{64C2}\x{64C5}\x{64C7}\x{64CD}' . + '\x{64D2}\x{64D4}\x{64D8}\x{64DA}\x{64E0}\x{64E1}\x{64E2}\x{64E3}\x{64E6}' . + '\x{64E7}\x{64EC}\x{64EF}\x{64F1}\x{64F2}\x{64F4}\x{64F6}\x{64FA}\x{64FD}' . + '\x{64FE}\x{6500}\x{6505}\x{6518}\x{651C}\x{651D}\x{6523}\x{6524}\x{652A}' . + '\x{652B}\x{652C}\x{652F}\x{6534}\x{6535}\x{6536}\x{6537}\x{6538}\x{6539}' . + '\x{653B}\x{653E}\x{653F}\x{6545}\x{6548}\x{654D}\x{654F}\x{6551}\x{6555}' . + '\x{6556}\x{6557}\x{6558}\x{6559}\x{655D}\x{655E}\x{6562}\x{6563}\x{6566}' . + '\x{656C}\x{6570}\x{6572}\x{6574}\x{6575}\x{6577}\x{6578}\x{6582}\x{6583}' . + '\x{6587}\x{6588}\x{6589}\x{658C}\x{658E}\x{6590}\x{6591}\x{6597}\x{6599}' . + '\x{659B}\x{659C}\x{659F}\x{65A1}\x{65A4}\x{65A5}\x{65A7}\x{65AB}\x{65AC}' . + '\x{65AD}\x{65AF}\x{65B0}\x{65B7}\x{65B9}\x{65BC}\x{65BD}\x{65C1}\x{65C3}' . + '\x{65C4}\x{65C5}\x{65C6}\x{65CB}\x{65CC}\x{65CF}\x{65D2}\x{65D7}\x{65D9}' . + '\x{65DB}\x{65E0}\x{65E1}\x{65E2}\x{65E5}\x{65E6}\x{65E7}\x{65E8}\x{65E9}' . + '\x{65EC}\x{65ED}\x{65F1}\x{65FA}\x{65FB}\x{6602}\x{6603}\x{6606}\x{6607}' . + '\x{660A}\x{660C}\x{660E}\x{660F}\x{6613}\x{6614}\x{661C}\x{661F}\x{6620}' . + '\x{6625}\x{6627}\x{6628}\x{662D}\x{662F}\x{6634}\x{6635}\x{6636}\x{663C}' . + '\x{663F}\x{6641}\x{6642}\x{6643}\x{6644}\x{6649}\x{664B}\x{664F}\x{6652}' . + '\x{665D}\x{665E}\x{665F}\x{6662}\x{6664}\x{6666}\x{6667}\x{6668}\x{6669}' . + '\x{666E}\x{666F}\x{6670}\x{6674}\x{6676}\x{667A}\x{6681}\x{6683}\x{6684}' . + '\x{6687}\x{6688}\x{6689}\x{668E}\x{6691}\x{6696}\x{6697}\x{6698}\x{669D}' . + '\x{66A2}\x{66A6}\x{66AB}\x{66AE}\x{66B4}\x{66B8}\x{66B9}\x{66BC}\x{66BE}' . + '\x{66C1}\x{66C4}\x{66C7}\x{66C9}\x{66D6}\x{66D9}\x{66DA}\x{66DC}\x{66DD}' . + '\x{66E0}\x{66E6}\x{66E9}\x{66F0}\x{66F2}\x{66F3}\x{66F4}\x{66F5}\x{66F7}' . + '\x{66F8}\x{66F9}\x{66FC}\x{66FD}\x{66FE}\x{66FF}\x{6700}\x{6703}\x{6708}' . + '\x{6709}\x{670B}\x{670D}\x{670F}\x{6714}\x{6715}\x{6716}\x{6717}\x{671B}' . + '\x{671D}\x{671E}\x{671F}\x{6726}\x{6727}\x{6728}\x{672A}\x{672B}\x{672C}' . + '\x{672D}\x{672E}\x{6731}\x{6734}\x{6736}\x{6737}\x{6738}\x{673A}\x{673D}' . + '\x{673F}\x{6741}\x{6746}\x{6749}\x{674E}\x{674F}\x{6750}\x{6751}\x{6753}' . + '\x{6756}\x{6759}\x{675C}\x{675E}\x{675F}\x{6760}\x{6761}\x{6762}\x{6763}' . + '\x{6764}\x{6765}\x{676A}\x{676D}\x{676F}\x{6770}\x{6771}\x{6772}\x{6773}' . + '\x{6775}\x{6777}\x{677C}\x{677E}\x{677F}\x{6785}\x{6787}\x{6789}\x{678B}' . + '\x{678C}\x{6790}\x{6795}\x{6797}\x{679A}\x{679C}\x{679D}\x{67A0}\x{67A1}' . + '\x{67A2}\x{67A6}\x{67A9}\x{67AF}\x{67B3}\x{67B4}\x{67B6}\x{67B7}\x{67B8}' . + '\x{67B9}\x{67C1}\x{67C4}\x{67C6}\x{67CA}\x{67CE}\x{67CF}\x{67D0}\x{67D1}' . + '\x{67D3}\x{67D4}\x{67D8}\x{67DA}\x{67DD}\x{67DE}\x{67E2}\x{67E4}\x{67E7}' . + '\x{67E9}\x{67EC}\x{67EE}\x{67EF}\x{67F1}\x{67F3}\x{67F4}\x{67F5}\x{67FB}' . + '\x{67FE}\x{67FF}\x{6802}\x{6803}\x{6804}\x{6813}\x{6816}\x{6817}\x{681E}' . + '\x{6821}\x{6822}\x{6829}\x{682A}\x{682B}\x{6832}\x{6834}\x{6838}\x{6839}' . + '\x{683C}\x{683D}\x{6840}\x{6841}\x{6842}\x{6843}\x{6846}\x{6848}\x{684D}' . + '\x{684E}\x{6850}\x{6851}\x{6853}\x{6854}\x{6859}\x{685C}\x{685D}\x{685F}' . + '\x{6863}\x{6867}\x{6874}\x{6876}\x{6877}\x{687E}\x{687F}\x{6881}\x{6883}' . + '\x{6885}\x{688D}\x{688F}\x{6893}\x{6894}\x{6897}\x{689B}\x{689D}\x{689F}' . + '\x{68A0}\x{68A2}\x{68A6}\x{68A7}\x{68A8}\x{68AD}\x{68AF}\x{68B0}\x{68B1}' . + '\x{68B3}\x{68B5}\x{68B6}\x{68B9}\x{68BA}\x{68BC}\x{68C4}\x{68C6}\x{68C9}' . + '\x{68CA}\x{68CB}\x{68CD}\x{68D2}\x{68D4}\x{68D5}\x{68D7}\x{68D8}\x{68DA}' . + '\x{68DF}\x{68E0}\x{68E1}\x{68E3}\x{68E7}\x{68EE}\x{68EF}\x{68F2}\x{68F9}' . + '\x{68FA}\x{6900}\x{6901}\x{6904}\x{6905}\x{6908}\x{690B}\x{690C}\x{690D}' . + '\x{690E}\x{690F}\x{6912}\x{6919}\x{691A}\x{691B}\x{691C}\x{6921}\x{6922}' . + '\x{6923}\x{6925}\x{6926}\x{6928}\x{692A}\x{6930}\x{6934}\x{6936}\x{6939}' . + '\x{693D}\x{693F}\x{694A}\x{6953}\x{6954}\x{6955}\x{6959}\x{695A}\x{695C}' . + '\x{695D}\x{695E}\x{6960}\x{6961}\x{6962}\x{696A}\x{696B}\x{696D}\x{696E}' . + '\x{696F}\x{6973}\x{6974}\x{6975}\x{6977}\x{6978}\x{6979}\x{697C}\x{697D}' . + '\x{697E}\x{6981}\x{6982}\x{698A}\x{698E}\x{6991}\x{6994}\x{6995}\x{699B}' . + '\x{699C}\x{69A0}\x{69A7}\x{69AE}\x{69B1}\x{69B2}\x{69B4}\x{69BB}\x{69BE}' . + '\x{69BF}\x{69C1}\x{69C3}\x{69C7}\x{69CA}\x{69CB}\x{69CC}\x{69CD}\x{69CE}' . + '\x{69D0}\x{69D3}\x{69D8}\x{69D9}\x{69DD}\x{69DE}\x{69E7}\x{69E8}\x{69EB}' . + '\x{69ED}\x{69F2}\x{69F9}\x{69FB}\x{69FD}\x{69FF}\x{6A02}\x{6A05}\x{6A0A}' . + '\x{6A0B}\x{6A0C}\x{6A12}\x{6A13}\x{6A14}\x{6A17}\x{6A19}\x{6A1B}\x{6A1E}' . + '\x{6A1F}\x{6A21}\x{6A22}\x{6A23}\x{6A29}\x{6A2A}\x{6A2B}\x{6A2E}\x{6A35}' . + '\x{6A36}\x{6A38}\x{6A39}\x{6A3A}\x{6A3D}\x{6A44}\x{6A47}\x{6A48}\x{6A4B}' . + '\x{6A58}\x{6A59}\x{6A5F}\x{6A61}\x{6A62}\x{6A66}\x{6A72}\x{6A78}\x{6A7F}' . + '\x{6A80}\x{6A84}\x{6A8D}\x{6A8E}\x{6A90}\x{6A97}\x{6A9C}\x{6AA0}\x{6AA2}' . + '\x{6AA3}\x{6AAA}\x{6AAC}\x{6AAE}\x{6AB3}\x{6AB8}\x{6ABB}\x{6AC1}\x{6AC2}' . + '\x{6AC3}\x{6AD1}\x{6AD3}\x{6ADA}\x{6ADB}\x{6ADE}\x{6ADF}\x{6AE8}\x{6AEA}' . + '\x{6AFA}\x{6AFB}\x{6B04}\x{6B05}\x{6B0A}\x{6B12}\x{6B16}\x{6B1D}\x{6B1F}' . + '\x{6B20}\x{6B21}\x{6B23}\x{6B27}\x{6B32}\x{6B37}\x{6B38}\x{6B39}\x{6B3A}' . + '\x{6B3D}\x{6B3E}\x{6B43}\x{6B47}\x{6B49}\x{6B4C}\x{6B4E}\x{6B50}\x{6B53}' . + '\x{6B54}\x{6B59}\x{6B5B}\x{6B5F}\x{6B61}\x{6B62}\x{6B63}\x{6B64}\x{6B66}' . + '\x{6B69}\x{6B6A}\x{6B6F}\x{6B73}\x{6B74}\x{6B78}\x{6B79}\x{6B7B}\x{6B7F}' . + '\x{6B80}\x{6B83}\x{6B84}\x{6B86}\x{6B89}\x{6B8A}\x{6B8B}\x{6B8D}\x{6B95}' . + '\x{6B96}\x{6B98}\x{6B9E}\x{6BA4}\x{6BAA}\x{6BAB}\x{6BAF}\x{6BB1}\x{6BB2}' . + '\x{6BB3}\x{6BB4}\x{6BB5}\x{6BB7}\x{6BBA}\x{6BBB}\x{6BBC}\x{6BBF}\x{6BC0}' . + '\x{6BC5}\x{6BC6}\x{6BCB}\x{6BCD}\x{6BCE}\x{6BD2}\x{6BD3}\x{6BD4}\x{6BD8}' . + '\x{6BDB}\x{6BDF}\x{6BEB}\x{6BEC}\x{6BEF}\x{6BF3}\x{6C08}\x{6C0F}\x{6C11}' . + '\x{6C13}\x{6C14}\x{6C17}\x{6C1B}\x{6C23}\x{6C24}\x{6C34}\x{6C37}\x{6C38}' . + '\x{6C3E}\x{6C40}\x{6C41}\x{6C42}\x{6C4E}\x{6C50}\x{6C55}\x{6C57}\x{6C5A}' . + '\x{6C5D}\x{6C5E}\x{6C5F}\x{6C60}\x{6C62}\x{6C68}\x{6C6A}\x{6C70}\x{6C72}' . + '\x{6C73}\x{6C7A}\x{6C7D}\x{6C7E}\x{6C81}\x{6C82}\x{6C83}\x{6C88}\x{6C8C}' . + '\x{6C8D}\x{6C90}\x{6C92}\x{6C93}\x{6C96}\x{6C99}\x{6C9A}\x{6C9B}\x{6CA1}' . + '\x{6CA2}\x{6CAB}\x{6CAE}\x{6CB1}\x{6CB3}\x{6CB8}\x{6CB9}\x{6CBA}\x{6CBB}' . + '\x{6CBC}\x{6CBD}\x{6CBE}\x{6CBF}\x{6CC1}\x{6CC4}\x{6CC5}\x{6CC9}\x{6CCA}' . + '\x{6CCC}\x{6CD3}\x{6CD5}\x{6CD7}\x{6CD9}\x{6CDB}\x{6CDD}\x{6CE1}\x{6CE2}' . + '\x{6CE3}\x{6CE5}\x{6CE8}\x{6CEA}\x{6CEF}\x{6CF0}\x{6CF1}\x{6CF3}\x{6D0B}' . + '\x{6D0C}\x{6D12}\x{6D17}\x{6D19}\x{6D1B}\x{6D1E}\x{6D1F}\x{6D25}\x{6D29}' . + '\x{6D2A}\x{6D2B}\x{6D32}\x{6D33}\x{6D35}\x{6D36}\x{6D38}\x{6D3B}\x{6D3D}' . + '\x{6D3E}\x{6D41}\x{6D44}\x{6D45}\x{6D59}\x{6D5A}\x{6D5C}\x{6D63}\x{6D64}' . + '\x{6D66}\x{6D69}\x{6D6A}\x{6D6C}\x{6D6E}\x{6D74}\x{6D77}\x{6D78}\x{6D79}' . + '\x{6D85}\x{6D88}\x{6D8C}\x{6D8E}\x{6D93}\x{6D95}\x{6D99}\x{6D9B}\x{6D9C}' . + '\x{6DAF}\x{6DB2}\x{6DB5}\x{6DB8}\x{6DBC}\x{6DC0}\x{6DC5}\x{6DC6}\x{6DC7}' . + '\x{6DCB}\x{6DCC}\x{6DD1}\x{6DD2}\x{6DD5}\x{6DD8}\x{6DD9}\x{6DDE}\x{6DE1}' . + '\x{6DE4}\x{6DE6}\x{6DE8}\x{6DEA}\x{6DEB}\x{6DEC}\x{6DEE}\x{6DF1}\x{6DF3}' . + '\x{6DF5}\x{6DF7}\x{6DF9}\x{6DFA}\x{6DFB}\x{6E05}\x{6E07}\x{6E08}\x{6E09}' . + '\x{6E0A}\x{6E0B}\x{6E13}\x{6E15}\x{6E19}\x{6E1A}\x{6E1B}\x{6E1D}\x{6E1F}' . + '\x{6E20}\x{6E21}\x{6E23}\x{6E24}\x{6E25}\x{6E26}\x{6E29}\x{6E2B}\x{6E2C}' . + '\x{6E2D}\x{6E2E}\x{6E2F}\x{6E38}\x{6E3A}\x{6E3E}\x{6E43}\x{6E4A}\x{6E4D}' . + '\x{6E4E}\x{6E56}\x{6E58}\x{6E5B}\x{6E5F}\x{6E67}\x{6E6B}\x{6E6E}\x{6E6F}' . + '\x{6E72}\x{6E76}\x{6E7E}\x{6E7F}\x{6E80}\x{6E82}\x{6E8C}\x{6E8F}\x{6E90}' . + '\x{6E96}\x{6E98}\x{6E9C}\x{6E9D}\x{6E9F}\x{6EA2}\x{6EA5}\x{6EAA}\x{6EAF}' . + '\x{6EB2}\x{6EB6}\x{6EB7}\x{6EBA}\x{6EBD}\x{6EC2}\x{6EC4}\x{6EC5}\x{6EC9}' . + '\x{6ECB}\x{6ECC}\x{6ED1}\x{6ED3}\x{6ED4}\x{6ED5}\x{6EDD}\x{6EDE}\x{6EEC}' . + '\x{6EEF}\x{6EF2}\x{6EF4}\x{6EF7}\x{6EF8}\x{6EFE}\x{6EFF}\x{6F01}\x{6F02}' . + '\x{6F06}\x{6F09}\x{6F0F}\x{6F11}\x{6F13}\x{6F14}\x{6F15}\x{6F20}\x{6F22}' . + '\x{6F23}\x{6F2B}\x{6F2C}\x{6F31}\x{6F32}\x{6F38}\x{6F3E}\x{6F3F}\x{6F41}' . + '\x{6F45}\x{6F54}\x{6F58}\x{6F5B}\x{6F5C}\x{6F5F}\x{6F64}\x{6F66}\x{6F6D}' . + '\x{6F6E}\x{6F6F}\x{6F70}\x{6F74}\x{6F78}\x{6F7A}\x{6F7C}\x{6F80}\x{6F81}' . + '\x{6F82}\x{6F84}\x{6F86}\x{6F8E}\x{6F91}\x{6F97}\x{6FA1}\x{6FA3}\x{6FA4}' . + '\x{6FAA}\x{6FB1}\x{6FB3}\x{6FB9}\x{6FC0}\x{6FC1}\x{6FC2}\x{6FC3}\x{6FC6}' . + '\x{6FD4}\x{6FD5}\x{6FD8}\x{6FDB}\x{6FDF}\x{6FE0}\x{6FE1}\x{6FE4}\x{6FEB}' . + '\x{6FEC}\x{6FEE}\x{6FEF}\x{6FF1}\x{6FF3}\x{6FF6}\x{6FFA}\x{6FFE}\x{7001}' . + '\x{7009}\x{700B}\x{700F}\x{7011}\x{7015}\x{7018}\x{701A}\x{701B}\x{701D}' . + '\x{701E}\x{701F}\x{7026}\x{7027}\x{702C}\x{7030}\x{7032}\x{703E}\x{704C}' . + '\x{7051}\x{7058}\x{7063}\x{706B}\x{706F}\x{7070}\x{7078}\x{707C}\x{707D}' . + '\x{7089}\x{708A}\x{708E}\x{7092}\x{7099}\x{70AC}\x{70AD}\x{70AE}\x{70AF}' . + '\x{70B3}\x{70B8}\x{70B9}\x{70BA}\x{70C8}\x{70CB}\x{70CF}\x{70D9}\x{70DD}' . + '\x{70DF}\x{70F1}\x{70F9}\x{70FD}\x{7109}\x{7114}\x{7119}\x{711A}\x{711C}' . + '\x{7121}\x{7126}\x{7136}\x{713C}\x{7149}\x{714C}\x{714E}\x{7155}\x{7156}' . + '\x{7159}\x{7162}\x{7164}\x{7165}\x{7166}\x{7167}\x{7169}\x{716C}\x{716E}' . + '\x{717D}\x{7184}\x{7188}\x{718A}\x{718F}\x{7194}\x{7195}\x{7199}\x{719F}' . + '\x{71A8}\x{71AC}\x{71B1}\x{71B9}\x{71BE}\x{71C3}\x{71C8}\x{71C9}\x{71CE}' . + '\x{71D0}\x{71D2}\x{71D4}\x{71D5}\x{71D7}\x{71DF}\x{71E0}\x{71E5}\x{71E6}' . + '\x{71E7}\x{71EC}\x{71ED}\x{71EE}\x{71F5}\x{71F9}\x{71FB}\x{71FC}\x{71FF}' . + '\x{7206}\x{720D}\x{7210}\x{721B}\x{7228}\x{722A}\x{722C}\x{722D}\x{7230}' . + '\x{7232}\x{7235}\x{7236}\x{723A}\x{723B}\x{723C}\x{723D}\x{723E}\x{723F}' . + '\x{7240}\x{7246}\x{7247}\x{7248}\x{724B}\x{724C}\x{7252}\x{7258}\x{7259}' . + '\x{725B}\x{725D}\x{725F}\x{7261}\x{7262}\x{7267}\x{7269}\x{7272}\x{7274}' . + '\x{7279}\x{727D}\x{727E}\x{7280}\x{7281}\x{7282}\x{7287}\x{7292}\x{7296}' . + '\x{72A0}\x{72A2}\x{72A7}\x{72AC}\x{72AF}\x{72B2}\x{72B6}\x{72B9}\x{72C2}' . + '\x{72C3}\x{72C4}\x{72C6}\x{72CE}\x{72D0}\x{72D2}\x{72D7}\x{72D9}\x{72DB}' . + '\x{72E0}\x{72E1}\x{72E2}\x{72E9}\x{72EC}\x{72ED}\x{72F7}\x{72F8}\x{72F9}' . + '\x{72FC}\x{72FD}\x{730A}\x{7316}\x{7317}\x{731B}\x{731C}\x{731D}\x{731F}' . + '\x{7325}\x{7329}\x{732A}\x{732B}\x{732E}\x{732F}\x{7334}\x{7336}\x{7337}' . + '\x{733E}\x{733F}\x{7344}\x{7345}\x{734E}\x{734F}\x{7357}\x{7363}\x{7368}' . + '\x{736A}\x{7370}\x{7372}\x{7375}\x{7378}\x{737A}\x{737B}\x{7384}\x{7387}' . + '\x{7389}\x{738B}\x{7396}\x{73A9}\x{73B2}\x{73B3}\x{73BB}\x{73C0}\x{73C2}' . + '\x{73C8}\x{73CA}\x{73CD}\x{73CE}\x{73DE}\x{73E0}\x{73E5}\x{73EA}\x{73ED}' . + '\x{73EE}\x{73F1}\x{73F8}\x{73FE}\x{7403}\x{7405}\x{7406}\x{7409}\x{7422}' . + '\x{7425}\x{7432}\x{7433}\x{7434}\x{7435}\x{7436}\x{743A}\x{743F}\x{7441}' . + '\x{7455}\x{7459}\x{745A}\x{745B}\x{745C}\x{745E}\x{745F}\x{7460}\x{7463}' . + '\x{7464}\x{7469}\x{746A}\x{746F}\x{7470}\x{7473}\x{7476}\x{747E}\x{7483}' . + '\x{748B}\x{749E}\x{74A2}\x{74A7}\x{74B0}\x{74BD}\x{74CA}\x{74CF}\x{74D4}' . + '\x{74DC}\x{74E0}\x{74E2}\x{74E3}\x{74E6}\x{74E7}\x{74E9}\x{74EE}\x{74F0}' . + '\x{74F1}\x{74F2}\x{74F6}\x{74F7}\x{74F8}\x{7503}\x{7504}\x{7505}\x{750C}' . + '\x{750D}\x{750E}\x{7511}\x{7513}\x{7515}\x{7518}\x{751A}\x{751C}\x{751E}' . + '\x{751F}\x{7523}\x{7525}\x{7526}\x{7528}\x{752B}\x{752C}\x{7530}\x{7531}' . + '\x{7532}\x{7533}\x{7537}\x{7538}\x{753A}\x{753B}\x{753C}\x{7544}\x{7546}' . + '\x{7549}\x{754A}\x{754B}\x{754C}\x{754D}\x{754F}\x{7551}\x{7554}\x{7559}' . + '\x{755A}\x{755B}\x{755C}\x{755D}\x{7560}\x{7562}\x{7564}\x{7565}\x{7566}' . + '\x{7567}\x{7569}\x{756A}\x{756B}\x{756D}\x{7570}\x{7573}\x{7574}\x{7576}' . + '\x{7577}\x{7578}\x{757F}\x{7582}\x{7586}\x{7587}\x{7589}\x{758A}\x{758B}' . + '\x{758E}\x{758F}\x{7591}\x{7594}\x{759A}\x{759D}\x{75A3}\x{75A5}\x{75AB}' . + '\x{75B1}\x{75B2}\x{75B3}\x{75B5}\x{75B8}\x{75B9}\x{75BC}\x{75BD}\x{75BE}' . + '\x{75C2}\x{75C3}\x{75C5}\x{75C7}\x{75CA}\x{75CD}\x{75D2}\x{75D4}\x{75D5}' . + '\x{75D8}\x{75D9}\x{75DB}\x{75DE}\x{75E2}\x{75E3}\x{75E9}\x{75F0}\x{75F2}' . + '\x{75F3}\x{75F4}\x{75FA}\x{75FC}\x{75FE}\x{75FF}\x{7601}\x{7609}\x{760B}' . + '\x{760D}\x{761F}\x{7620}\x{7621}\x{7622}\x{7624}\x{7627}\x{7630}\x{7634}' . + '\x{763B}\x{7642}\x{7646}\x{7647}\x{7648}\x{764C}\x{7652}\x{7656}\x{7658}' . + '\x{765C}\x{7661}\x{7662}\x{7667}\x{7668}\x{7669}\x{766A}\x{766C}\x{7670}' . + '\x{7672}\x{7676}\x{7678}\x{767A}\x{767B}\x{767C}\x{767D}\x{767E}\x{7680}' . + '\x{7683}\x{7684}\x{7686}\x{7687}\x{7688}\x{768B}\x{768E}\x{7690}\x{7693}' . + '\x{7696}\x{7699}\x{769A}\x{76AE}\x{76B0}\x{76B4}\x{76B7}\x{76B8}\x{76B9}' . + '\x{76BA}\x{76BF}\x{76C2}\x{76C3}\x{76C6}\x{76C8}\x{76CA}\x{76CD}\x{76D2}' . + '\x{76D6}\x{76D7}\x{76DB}\x{76DC}\x{76DE}\x{76DF}\x{76E1}\x{76E3}\x{76E4}' . + '\x{76E5}\x{76E7}\x{76EA}\x{76EE}\x{76F2}\x{76F4}\x{76F8}\x{76FB}\x{76FE}' . + '\x{7701}\x{7704}\x{7707}\x{7708}\x{7709}\x{770B}\x{770C}\x{771B}\x{771E}' . + '\x{771F}\x{7720}\x{7724}\x{7725}\x{7726}\x{7729}\x{7737}\x{7738}\x{773A}' . + '\x{773C}\x{7740}\x{7747}\x{775A}\x{775B}\x{7761}\x{7763}\x{7765}\x{7766}' . + '\x{7768}\x{776B}\x{7779}\x{777E}\x{777F}\x{778B}\x{778E}\x{7791}\x{779E}' . + '\x{77A0}\x{77A5}\x{77AC}\x{77AD}\x{77B0}\x{77B3}\x{77B6}\x{77B9}\x{77BB}' . + '\x{77BC}\x{77BD}\x{77BF}\x{77C7}\x{77CD}\x{77D7}\x{77DA}\x{77DB}\x{77DC}' . + '\x{77E2}\x{77E3}\x{77E5}\x{77E7}\x{77E9}\x{77ED}\x{77EE}\x{77EF}\x{77F3}' . + '\x{77FC}\x{7802}\x{780C}\x{7812}\x{7814}\x{7815}\x{7820}\x{7825}\x{7826}' . + '\x{7827}\x{7832}\x{7834}\x{783A}\x{783F}\x{7845}\x{785D}\x{786B}\x{786C}' . + '\x{786F}\x{7872}\x{7874}\x{787C}\x{7881}\x{7886}\x{7887}\x{788C}\x{788D}' . + '\x{788E}\x{7891}\x{7893}\x{7895}\x{7897}\x{789A}\x{78A3}\x{78A7}\x{78A9}' . + '\x{78AA}\x{78AF}\x{78B5}\x{78BA}\x{78BC}\x{78BE}\x{78C1}\x{78C5}\x{78C6}' . + '\x{78CA}\x{78CB}\x{78D0}\x{78D1}\x{78D4}\x{78DA}\x{78E7}\x{78E8}\x{78EC}' . + '\x{78EF}\x{78F4}\x{78FD}\x{7901}\x{7907}\x{790E}\x{7911}\x{7912}\x{7919}' . + '\x{7926}\x{792A}\x{792B}\x{792C}\x{793A}\x{793C}\x{793E}\x{7940}\x{7941}' . + '\x{7947}\x{7948}\x{7949}\x{7950}\x{7953}\x{7955}\x{7956}\x{7957}\x{795A}' . + '\x{795D}\x{795E}\x{795F}\x{7960}\x{7962}\x{7965}\x{7968}\x{796D}\x{7977}' . + '\x{797A}\x{797F}\x{7980}\x{7981}\x{7984}\x{7985}\x{798A}\x{798D}\x{798E}' . + '\x{798F}\x{799D}\x{79A6}\x{79A7}\x{79AA}\x{79AE}\x{79B0}\x{79B3}\x{79B9}' . + '\x{79BA}\x{79BD}\x{79BE}\x{79BF}\x{79C0}\x{79C1}\x{79C9}\x{79CB}\x{79D1}' . + '\x{79D2}\x{79D5}\x{79D8}\x{79DF}\x{79E1}\x{79E3}\x{79E4}\x{79E6}\x{79E7}' . + '\x{79E9}\x{79EC}\x{79F0}\x{79FB}\x{7A00}\x{7A08}\x{7A0B}\x{7A0D}\x{7A0E}' . + '\x{7A14}\x{7A17}\x{7A18}\x{7A19}\x{7A1A}\x{7A1C}\x{7A1F}\x{7A20}\x{7A2E}' . + '\x{7A31}\x{7A32}\x{7A37}\x{7A3B}\x{7A3C}\x{7A3D}\x{7A3E}\x{7A3F}\x{7A40}' . + '\x{7A42}\x{7A43}\x{7A46}\x{7A49}\x{7A4D}\x{7A4E}\x{7A4F}\x{7A50}\x{7A57}' . + '\x{7A61}\x{7A62}\x{7A63}\x{7A69}\x{7A6B}\x{7A70}\x{7A74}\x{7A76}\x{7A79}' . + '\x{7A7A}\x{7A7D}\x{7A7F}\x{7A81}\x{7A83}\x{7A84}\x{7A88}\x{7A92}\x{7A93}' . + '\x{7A95}\x{7A96}\x{7A97}\x{7A98}\x{7A9F}\x{7AA9}\x{7AAA}\x{7AAE}\x{7AAF}' . + '\x{7AB0}\x{7AB6}\x{7ABA}\x{7ABF}\x{7AC3}\x{7AC4}\x{7AC5}\x{7AC7}\x{7AC8}' . + '\x{7ACA}\x{7ACB}\x{7ACD}\x{7ACF}\x{7AD2}\x{7AD3}\x{7AD5}\x{7AD9}\x{7ADA}' . + '\x{7ADC}\x{7ADD}\x{7ADF}\x{7AE0}\x{7AE1}\x{7AE2}\x{7AE3}\x{7AE5}\x{7AE6}' . + '\x{7AEA}\x{7AED}\x{7AEF}\x{7AF0}\x{7AF6}\x{7AF8}\x{7AF9}\x{7AFA}\x{7AFF}' . + '\x{7B02}\x{7B04}\x{7B06}\x{7B08}\x{7B0A}\x{7B0B}\x{7B0F}\x{7B11}\x{7B18}' . + '\x{7B19}\x{7B1B}\x{7B1E}\x{7B20}\x{7B25}\x{7B26}\x{7B28}\x{7B2C}\x{7B33}' . + '\x{7B35}\x{7B36}\x{7B39}\x{7B45}\x{7B46}\x{7B48}\x{7B49}\x{7B4B}\x{7B4C}' . + '\x{7B4D}\x{7B4F}\x{7B50}\x{7B51}\x{7B52}\x{7B54}\x{7B56}\x{7B5D}\x{7B65}' . + '\x{7B67}\x{7B6C}\x{7B6E}\x{7B70}\x{7B71}\x{7B74}\x{7B75}\x{7B7A}\x{7B86}' . + '\x{7B87}\x{7B8B}\x{7B8D}\x{7B8F}\x{7B92}\x{7B94}\x{7B95}\x{7B97}\x{7B98}' . + '\x{7B99}\x{7B9A}\x{7B9C}\x{7B9D}\x{7B9F}\x{7BA1}\x{7BAA}\x{7BAD}\x{7BB1}' . + '\x{7BB4}\x{7BB8}\x{7BC0}\x{7BC1}\x{7BC4}\x{7BC6}\x{7BC7}\x{7BC9}\x{7BCB}' . + '\x{7BCC}\x{7BCF}\x{7BDD}\x{7BE0}\x{7BE4}\x{7BE5}\x{7BE6}\x{7BE9}\x{7BED}' . + '\x{7BF3}\x{7BF6}\x{7BF7}\x{7C00}\x{7C07}\x{7C0D}\x{7C11}\x{7C12}\x{7C13}' . + '\x{7C14}\x{7C17}\x{7C1F}\x{7C21}\x{7C23}\x{7C27}\x{7C2A}\x{7C2B}\x{7C37}' . + '\x{7C38}\x{7C3D}\x{7C3E}\x{7C3F}\x{7C40}\x{7C43}\x{7C4C}\x{7C4D}\x{7C4F}' . + '\x{7C50}\x{7C54}\x{7C56}\x{7C58}\x{7C5F}\x{7C60}\x{7C64}\x{7C65}\x{7C6C}' . + '\x{7C73}\x{7C75}\x{7C7E}\x{7C81}\x{7C82}\x{7C83}\x{7C89}\x{7C8B}\x{7C8D}' . + '\x{7C90}\x{7C92}\x{7C95}\x{7C97}\x{7C98}\x{7C9B}\x{7C9F}\x{7CA1}\x{7CA2}' . + '\x{7CA4}\x{7CA5}\x{7CA7}\x{7CA8}\x{7CAB}\x{7CAD}\x{7CAE}\x{7CB1}\x{7CB2}' . + '\x{7CB3}\x{7CB9}\x{7CBD}\x{7CBE}\x{7CC0}\x{7CC2}\x{7CC5}\x{7CCA}\x{7CCE}' . + '\x{7CD2}\x{7CD6}\x{7CD8}\x{7CDC}\x{7CDE}\x{7CDF}\x{7CE0}\x{7CE2}\x{7CE7}' . + '\x{7CEF}\x{7CF2}\x{7CF4}\x{7CF6}\x{7CF8}\x{7CFA}\x{7CFB}\x{7CFE}\x{7D00}' . + '\x{7D02}\x{7D04}\x{7D05}\x{7D06}\x{7D0A}\x{7D0B}\x{7D0D}\x{7D10}\x{7D14}' . + '\x{7D15}\x{7D17}\x{7D18}\x{7D19}\x{7D1A}\x{7D1B}\x{7D1C}\x{7D20}\x{7D21}' . + '\x{7D22}\x{7D2B}\x{7D2C}\x{7D2E}\x{7D2F}\x{7D30}\x{7D32}\x{7D33}\x{7D35}' . + '\x{7D39}\x{7D3A}\x{7D3F}\x{7D42}\x{7D43}\x{7D44}\x{7D45}\x{7D46}\x{7D4B}' . + '\x{7D4C}\x{7D4E}\x{7D4F}\x{7D50}\x{7D56}\x{7D5B}\x{7D5E}\x{7D61}\x{7D62}' . + '\x{7D63}\x{7D66}\x{7D68}\x{7D6E}\x{7D71}\x{7D72}\x{7D73}\x{7D75}\x{7D76}' . + '\x{7D79}\x{7D7D}\x{7D89}\x{7D8F}\x{7D93}\x{7D99}\x{7D9A}\x{7D9B}\x{7D9C}' . + '\x{7D9F}\x{7DA2}\x{7DA3}\x{7DAB}\x{7DAC}\x{7DAD}\x{7DAE}\x{7DAF}\x{7DB0}' . + '\x{7DB1}\x{7DB2}\x{7DB4}\x{7DB5}\x{7DB8}\x{7DBA}\x{7DBB}\x{7DBD}\x{7DBE}' . + '\x{7DBF}\x{7DC7}\x{7DCA}\x{7DCB}\x{7DCF}\x{7DD1}\x{7DD2}\x{7DD5}\x{7DD8}' . + '\x{7DDA}\x{7DDC}\x{7DDD}\x{7DDE}\x{7DE0}\x{7DE1}\x{7DE4}\x{7DE8}\x{7DE9}' . + '\x{7DEC}\x{7DEF}\x{7DF2}\x{7DF4}\x{7DFB}\x{7E01}\x{7E04}\x{7E05}\x{7E09}' . + '\x{7E0A}\x{7E0B}\x{7E12}\x{7E1B}\x{7E1E}\x{7E1F}\x{7E21}\x{7E22}\x{7E23}' . + '\x{7E26}\x{7E2B}\x{7E2E}\x{7E31}\x{7E32}\x{7E35}\x{7E37}\x{7E39}\x{7E3A}' . + '\x{7E3B}\x{7E3D}\x{7E3E}\x{7E41}\x{7E43}\x{7E46}\x{7E4A}\x{7E4B}\x{7E4D}' . + '\x{7E54}\x{7E55}\x{7E56}\x{7E59}\x{7E5A}\x{7E5D}\x{7E5E}\x{7E66}\x{7E67}' . + '\x{7E69}\x{7E6A}\x{7E6D}\x{7E70}\x{7E79}\x{7E7B}\x{7E7C}\x{7E7D}\x{7E7F}' . + '\x{7E82}\x{7E83}\x{7E88}\x{7E89}\x{7E8C}\x{7E8E}\x{7E8F}\x{7E90}\x{7E92}' . + '\x{7E93}\x{7E94}\x{7E96}\x{7E9B}\x{7E9C}\x{7F36}\x{7F38}\x{7F3A}\x{7F45}' . + '\x{7F4C}\x{7F4D}\x{7F4E}\x{7F50}\x{7F51}\x{7F54}\x{7F55}\x{7F58}\x{7F5F}' . + '\x{7F60}\x{7F67}\x{7F68}\x{7F69}\x{7F6A}\x{7F6B}\x{7F6E}\x{7F70}\x{7F72}' . + '\x{7F75}\x{7F77}\x{7F78}\x{7F79}\x{7F82}\x{7F83}\x{7F85}\x{7F86}\x{7F87}' . + '\x{7F88}\x{7F8A}\x{7F8C}\x{7F8E}\x{7F94}\x{7F9A}\x{7F9D}\x{7F9E}\x{7FA3}' . + '\x{7FA4}\x{7FA8}\x{7FA9}\x{7FAE}\x{7FAF}\x{7FB2}\x{7FB6}\x{7FB8}\x{7FB9}' . + '\x{7FBD}\x{7FC1}\x{7FC5}\x{7FC6}\x{7FCA}\x{7FCC}\x{7FD2}\x{7FD4}\x{7FD5}' . + '\x{7FE0}\x{7FE1}\x{7FE6}\x{7FE9}\x{7FEB}\x{7FF0}\x{7FF3}\x{7FF9}\x{7FFB}' . + '\x{7FFC}\x{8000}\x{8001}\x{8003}\x{8004}\x{8005}\x{8006}\x{800B}\x{800C}' . + '\x{8010}\x{8012}\x{8015}\x{8017}\x{8018}\x{8019}\x{801C}\x{8021}\x{8028}' . + '\x{8033}\x{8036}\x{803B}\x{803D}\x{803F}\x{8046}\x{804A}\x{8052}\x{8056}' . + '\x{8058}\x{805A}\x{805E}\x{805F}\x{8061}\x{8062}\x{8068}\x{806F}\x{8070}' . + '\x{8072}\x{8073}\x{8074}\x{8076}\x{8077}\x{8079}\x{807D}\x{807E}\x{807F}' . + '\x{8084}\x{8085}\x{8086}\x{8087}\x{8089}\x{808B}\x{808C}\x{8093}\x{8096}' . + '\x{8098}\x{809A}\x{809B}\x{809D}\x{80A1}\x{80A2}\x{80A5}\x{80A9}\x{80AA}' . + '\x{80AC}\x{80AD}\x{80AF}\x{80B1}\x{80B2}\x{80B4}\x{80BA}\x{80C3}\x{80C4}' . + '\x{80C6}\x{80CC}\x{80CE}\x{80D6}\x{80D9}\x{80DA}\x{80DB}\x{80DD}\x{80DE}' . + '\x{80E1}\x{80E4}\x{80E5}\x{80EF}\x{80F1}\x{80F4}\x{80F8}\x{80FC}\x{80FD}' . + '\x{8102}\x{8105}\x{8106}\x{8107}\x{8108}\x{8109}\x{810A}\x{811A}\x{811B}' . + '\x{8123}\x{8129}\x{812F}\x{8131}\x{8133}\x{8139}\x{813E}\x{8146}\x{814B}' . + '\x{814E}\x{8150}\x{8151}\x{8153}\x{8154}\x{8155}\x{815F}\x{8165}\x{8166}' . + '\x{816B}\x{816E}\x{8170}\x{8171}\x{8174}\x{8178}\x{8179}\x{817A}\x{817F}' . + '\x{8180}\x{8182}\x{8183}\x{8188}\x{818A}\x{818F}\x{8193}\x{8195}\x{819A}' . + '\x{819C}\x{819D}\x{81A0}\x{81A3}\x{81A4}\x{81A8}\x{81A9}\x{81B0}\x{81B3}' . + '\x{81B5}\x{81B8}\x{81BA}\x{81BD}\x{81BE}\x{81BF}\x{81C0}\x{81C2}\x{81C6}' . + '\x{81C8}\x{81C9}\x{81CD}\x{81D1}\x{81D3}\x{81D8}\x{81D9}\x{81DA}\x{81DF}' . + '\x{81E0}\x{81E3}\x{81E5}\x{81E7}\x{81E8}\x{81EA}\x{81ED}\x{81F3}\x{81F4}' . + '\x{81FA}\x{81FB}\x{81FC}\x{81FE}\x{8201}\x{8202}\x{8205}\x{8207}\x{8208}' . + '\x{8209}\x{820A}\x{820C}\x{820D}\x{820E}\x{8210}\x{8212}\x{8216}\x{8217}' . + '\x{8218}\x{821B}\x{821C}\x{821E}\x{821F}\x{8229}\x{822A}\x{822B}\x{822C}' . + '\x{822E}\x{8233}\x{8235}\x{8236}\x{8237}\x{8238}\x{8239}\x{8240}\x{8247}' . + '\x{8258}\x{8259}\x{825A}\x{825D}\x{825F}\x{8262}\x{8264}\x{8266}\x{8268}' . + '\x{826A}\x{826B}\x{826E}\x{826F}\x{8271}\x{8272}\x{8276}\x{8277}\x{8278}' . + '\x{827E}\x{828B}\x{828D}\x{8292}\x{8299}\x{829D}\x{829F}\x{82A5}\x{82A6}' . + '\x{82AB}\x{82AC}\x{82AD}\x{82AF}\x{82B1}\x{82B3}\x{82B8}\x{82B9}\x{82BB}' . + '\x{82BD}\x{82C5}\x{82D1}\x{82D2}\x{82D3}\x{82D4}\x{82D7}\x{82D9}\x{82DB}' . + '\x{82DC}\x{82DE}\x{82DF}\x{82E1}\x{82E3}\x{82E5}\x{82E6}\x{82E7}\x{82EB}' . + '\x{82F1}\x{82F3}\x{82F4}\x{82F9}\x{82FA}\x{82FB}\x{8302}\x{8303}\x{8304}' . + '\x{8305}\x{8306}\x{8309}\x{830E}\x{8316}\x{8317}\x{8318}\x{831C}\x{8323}' . + '\x{8328}\x{832B}\x{832F}\x{8331}\x{8332}\x{8334}\x{8335}\x{8336}\x{8338}' . + '\x{8339}\x{8340}\x{8345}\x{8349}\x{834A}\x{834F}\x{8350}\x{8352}\x{8358}' . + '\x{8373}\x{8375}\x{8377}\x{837B}\x{837C}\x{8385}\x{8387}\x{8389}\x{838A}' . + '\x{838E}\x{8393}\x{8396}\x{839A}\x{839E}\x{839F}\x{83A0}\x{83A2}\x{83A8}' . + '\x{83AA}\x{83AB}\x{83B1}\x{83B5}\x{83BD}\x{83C1}\x{83C5}\x{83CA}\x{83CC}' . + '\x{83CE}\x{83D3}\x{83D6}\x{83D8}\x{83DC}\x{83DF}\x{83E0}\x{83E9}\x{83EB}' . + '\x{83EF}\x{83F0}\x{83F1}\x{83F2}\x{83F4}\x{83F7}\x{83FB}\x{83FD}\x{8403}' . + '\x{8404}\x{8407}\x{840B}\x{840C}\x{840D}\x{840E}\x{8413}\x{8420}\x{8422}' . + '\x{8429}\x{842A}\x{842C}\x{8431}\x{8435}\x{8438}\x{843C}\x{843D}\x{8446}' . + '\x{8449}\x{844E}\x{8457}\x{845B}\x{8461}\x{8462}\x{8463}\x{8466}\x{8469}' . + '\x{846B}\x{846C}\x{846D}\x{846E}\x{846F}\x{8471}\x{8475}\x{8477}\x{8479}' . + '\x{847A}\x{8482}\x{8484}\x{848B}\x{8490}\x{8494}\x{8499}\x{849C}\x{849F}' . + '\x{84A1}\x{84AD}\x{84B2}\x{84B8}\x{84B9}\x{84BB}\x{84BC}\x{84BF}\x{84C1}' . + '\x{84C4}\x{84C6}\x{84C9}\x{84CA}\x{84CB}\x{84CD}\x{84D0}\x{84D1}\x{84D6}' . + '\x{84D9}\x{84DA}\x{84EC}\x{84EE}\x{84F4}\x{84FC}\x{84FF}\x{8500}\x{8506}' . + '\x{8511}\x{8513}\x{8514}\x{8515}\x{8517}\x{8518}\x{851A}\x{851F}\x{8521}' . + '\x{8526}\x{852C}\x{852D}\x{8535}\x{853D}\x{8540}\x{8541}\x{8543}\x{8548}' . + '\x{8549}\x{854A}\x{854B}\x{854E}\x{8555}\x{8557}\x{8558}\x{855A}\x{8563}' . + '\x{8568}\x{8569}\x{856A}\x{856D}\x{8577}\x{857E}\x{8580}\x{8584}\x{8587}' . + '\x{8588}\x{858A}\x{8590}\x{8591}\x{8594}\x{8597}\x{8599}\x{859B}\x{859C}' . + '\x{85A4}\x{85A6}\x{85A8}\x{85A9}\x{85AA}\x{85AB}\x{85AC}\x{85AE}\x{85AF}' . + '\x{85B9}\x{85BA}\x{85C1}\x{85C9}\x{85CD}\x{85CF}\x{85D0}\x{85D5}\x{85DC}' . + '\x{85DD}\x{85E4}\x{85E5}\x{85E9}\x{85EA}\x{85F7}\x{85F9}\x{85FA}\x{85FB}' . + '\x{85FE}\x{8602}\x{8606}\x{8607}\x{860A}\x{860B}\x{8613}\x{8616}\x{8617}' . + '\x{861A}\x{8622}\x{862D}\x{862F}\x{8630}\x{863F}\x{864D}\x{864E}\x{8650}' . + '\x{8654}\x{8655}\x{865A}\x{865C}\x{865E}\x{865F}\x{8667}\x{866B}\x{8671}' . + '\x{8679}\x{867B}\x{868A}\x{868B}\x{868C}\x{8693}\x{8695}\x{86A3}\x{86A4}' . + '\x{86A9}\x{86AA}\x{86AB}\x{86AF}\x{86B0}\x{86B6}\x{86C4}\x{86C6}\x{86C7}' . + '\x{86C9}\x{86CB}\x{86CD}\x{86CE}\x{86D4}\x{86D9}\x{86DB}\x{86DE}\x{86DF}' . + '\x{86E4}\x{86E9}\x{86EC}\x{86ED}\x{86EE}\x{86EF}\x{86F8}\x{86F9}\x{86FB}' . + '\x{86FE}\x{8700}\x{8702}\x{8703}\x{8706}\x{8708}\x{8709}\x{870A}\x{870D}' . + '\x{8711}\x{8712}\x{8718}\x{871A}\x{871C}\x{8725}\x{8729}\x{8734}\x{8737}' . + '\x{873B}\x{873F}\x{8749}\x{874B}\x{874C}\x{874E}\x{8753}\x{8755}\x{8757}' . + '\x{8759}\x{875F}\x{8760}\x{8763}\x{8766}\x{8768}\x{876A}\x{876E}\x{8774}' . + '\x{8776}\x{8778}\x{877F}\x{8782}\x{878D}\x{879F}\x{87A2}\x{87AB}\x{87AF}' . + '\x{87B3}\x{87BA}\x{87BB}\x{87BD}\x{87C0}\x{87C4}\x{87C6}\x{87C7}\x{87CB}' . + '\x{87D0}\x{87D2}\x{87E0}\x{87EF}\x{87F2}\x{87F6}\x{87F7}\x{87F9}\x{87FB}' . + '\x{87FE}\x{8805}\x{880D}\x{880E}\x{880F}\x{8811}\x{8815}\x{8816}\x{8821}' . + '\x{8822}\x{8823}\x{8827}\x{8831}\x{8836}\x{8839}\x{883B}\x{8840}\x{8842}' . + '\x{8844}\x{8846}\x{884C}\x{884D}\x{8852}\x{8853}\x{8857}\x{8859}\x{885B}' . + '\x{885D}\x{885E}\x{8861}\x{8862}\x{8863}\x{8868}\x{886B}\x{8870}\x{8872}' . + '\x{8875}\x{8877}\x{887D}\x{887E}\x{887F}\x{8881}\x{8882}\x{8888}\x{888B}' . + '\x{888D}\x{8892}\x{8896}\x{8897}\x{8899}\x{889E}\x{88A2}\x{88A4}\x{88AB}' . + '\x{88AE}\x{88B0}\x{88B1}\x{88B4}\x{88B5}\x{88B7}\x{88BF}\x{88C1}\x{88C2}' . + '\x{88C3}\x{88C4}\x{88C5}\x{88CF}\x{88D4}\x{88D5}\x{88D8}\x{88D9}\x{88DC}' . + '\x{88DD}\x{88DF}\x{88E1}\x{88E8}\x{88F2}\x{88F3}\x{88F4}\x{88F8}\x{88F9}' . + '\x{88FC}\x{88FD}\x{88FE}\x{8902}\x{8904}\x{8907}\x{890A}\x{890C}\x{8910}' . + '\x{8912}\x{8913}\x{891D}\x{891E}\x{8925}\x{892A}\x{892B}\x{8936}\x{8938}' . + '\x{893B}\x{8941}\x{8943}\x{8944}\x{894C}\x{894D}\x{8956}\x{895E}\x{895F}' . + '\x{8960}\x{8964}\x{8966}\x{896A}\x{896D}\x{896F}\x{8972}\x{8974}\x{8977}' . + '\x{897E}\x{897F}\x{8981}\x{8983}\x{8986}\x{8987}\x{8988}\x{898A}\x{898B}' . + '\x{898F}\x{8993}\x{8996}\x{8997}\x{8998}\x{899A}\x{89A1}\x{89A6}\x{89A7}' . + '\x{89A9}\x{89AA}\x{89AC}\x{89AF}\x{89B2}\x{89B3}\x{89BA}\x{89BD}\x{89BF}' . + '\x{89C0}\x{89D2}\x{89DA}\x{89DC}\x{89DD}\x{89E3}\x{89E6}\x{89E7}\x{89F4}' . + '\x{89F8}\x{8A00}\x{8A02}\x{8A03}\x{8A08}\x{8A0A}\x{8A0C}\x{8A0E}\x{8A10}' . + '\x{8A13}\x{8A16}\x{8A17}\x{8A18}\x{8A1B}\x{8A1D}\x{8A1F}\x{8A23}\x{8A25}' . + '\x{8A2A}\x{8A2D}\x{8A31}\x{8A33}\x{8A34}\x{8A36}\x{8A3A}\x{8A3B}\x{8A3C}' . + '\x{8A41}\x{8A46}\x{8A48}\x{8A50}\x{8A51}\x{8A52}\x{8A54}\x{8A55}\x{8A5B}' . + '\x{8A5E}\x{8A60}\x{8A62}\x{8A63}\x{8A66}\x{8A69}\x{8A6B}\x{8A6C}\x{8A6D}' . + '\x{8A6E}\x{8A70}\x{8A71}\x{8A72}\x{8A73}\x{8A7C}\x{8A82}\x{8A84}\x{8A85}' . + '\x{8A87}\x{8A89}\x{8A8C}\x{8A8D}\x{8A91}\x{8A93}\x{8A95}\x{8A98}\x{8A9A}' . + '\x{8A9E}\x{8AA0}\x{8AA1}\x{8AA3}\x{8AA4}\x{8AA5}\x{8AA6}\x{8AA8}\x{8AAC}' . + '\x{8AAD}\x{8AB0}\x{8AB2}\x{8AB9}\x{8ABC}\x{8ABF}\x{8AC2}\x{8AC4}\x{8AC7}' . + '\x{8ACB}\x{8ACC}\x{8ACD}\x{8ACF}\x{8AD2}\x{8AD6}\x{8ADA}\x{8ADB}\x{8ADC}' . + '\x{8ADE}\x{8AE0}\x{8AE1}\x{8AE2}\x{8AE4}\x{8AE6}\x{8AE7}\x{8AEB}\x{8AED}' . + '\x{8AEE}\x{8AF1}\x{8AF3}\x{8AF7}\x{8AF8}\x{8AFA}\x{8AFE}\x{8B00}\x{8B01}' . + '\x{8B02}\x{8B04}\x{8B07}\x{8B0C}\x{8B0E}\x{8B10}\x{8B14}\x{8B16}\x{8B17}' . + '\x{8B19}\x{8B1A}\x{8B1B}\x{8B1D}\x{8B20}\x{8B21}\x{8B26}\x{8B28}\x{8B2B}' . + '\x{8B2C}\x{8B33}\x{8B39}\x{8B3E}\x{8B41}\x{8B49}\x{8B4C}\x{8B4E}\x{8B4F}' . + '\x{8B56}\x{8B58}\x{8B5A}\x{8B5B}\x{8B5C}\x{8B5F}\x{8B66}\x{8B6B}\x{8B6C}' . + '\x{8B6F}\x{8B70}\x{8B71}\x{8B72}\x{8B74}\x{8B77}\x{8B7D}\x{8B80}\x{8B83}' . + '\x{8B8A}\x{8B8C}\x{8B8E}\x{8B90}\x{8B92}\x{8B93}\x{8B96}\x{8B99}\x{8B9A}' . + '\x{8C37}\x{8C3A}\x{8C3F}\x{8C41}\x{8C46}\x{8C48}\x{8C4A}\x{8C4C}\x{8C4E}' . + '\x{8C50}\x{8C55}\x{8C5A}\x{8C61}\x{8C62}\x{8C6A}\x{8C6B}\x{8C6C}\x{8C78}' . + '\x{8C79}\x{8C7A}\x{8C7C}\x{8C82}\x{8C85}\x{8C89}\x{8C8A}\x{8C8C}\x{8C8D}' . + '\x{8C8E}\x{8C94}\x{8C98}\x{8C9D}\x{8C9E}\x{8CA0}\x{8CA1}\x{8CA2}\x{8CA7}' . + '\x{8CA8}\x{8CA9}\x{8CAA}\x{8CAB}\x{8CAC}\x{8CAD}\x{8CAE}\x{8CAF}\x{8CB0}' . + '\x{8CB2}\x{8CB3}\x{8CB4}\x{8CB6}\x{8CB7}\x{8CB8}\x{8CBB}\x{8CBC}\x{8CBD}' . + '\x{8CBF}\x{8CC0}\x{8CC1}\x{8CC2}\x{8CC3}\x{8CC4}\x{8CC7}\x{8CC8}\x{8CCA}' . + '\x{8CCD}\x{8CCE}\x{8CD1}\x{8CD3}\x{8CDA}\x{8CDB}\x{8CDC}\x{8CDE}\x{8CE0}' . + '\x{8CE2}\x{8CE3}\x{8CE4}\x{8CE6}\x{8CEA}\x{8CED}\x{8CFA}\x{8CFB}\x{8CFC}' . + '\x{8CFD}\x{8D04}\x{8D05}\x{8D07}\x{8D08}\x{8D0A}\x{8D0B}\x{8D0D}\x{8D0F}' . + '\x{8D10}\x{8D13}\x{8D14}\x{8D16}\x{8D64}\x{8D66}\x{8D67}\x{8D6B}\x{8D6D}' . + '\x{8D70}\x{8D71}\x{8D73}\x{8D74}\x{8D77}\x{8D81}\x{8D85}\x{8D8A}\x{8D99}' . + '\x{8DA3}\x{8DA8}\x{8DB3}\x{8DBA}\x{8DBE}\x{8DC2}\x{8DCB}\x{8DCC}\x{8DCF}' . + '\x{8DD6}\x{8DDA}\x{8DDB}\x{8DDD}\x{8DDF}\x{8DE1}\x{8DE3}\x{8DE8}\x{8DEA}' . + '\x{8DEB}\x{8DEF}\x{8DF3}\x{8DF5}\x{8DFC}\x{8DFF}\x{8E08}\x{8E09}\x{8E0A}' . + '\x{8E0F}\x{8E10}\x{8E1D}\x{8E1E}\x{8E1F}\x{8E2A}\x{8E30}\x{8E34}\x{8E35}' . + '\x{8E42}\x{8E44}\x{8E47}\x{8E48}\x{8E49}\x{8E4A}\x{8E4C}\x{8E50}\x{8E55}' . + '\x{8E59}\x{8E5F}\x{8E60}\x{8E63}\x{8E64}\x{8E72}\x{8E74}\x{8E76}\x{8E7C}' . + '\x{8E81}\x{8E84}\x{8E85}\x{8E87}\x{8E8A}\x{8E8B}\x{8E8D}\x{8E91}\x{8E93}' . + '\x{8E94}\x{8E99}\x{8EA1}\x{8EAA}\x{8EAB}\x{8EAC}\x{8EAF}\x{8EB0}\x{8EB1}' . + '\x{8EBE}\x{8EC5}\x{8EC6}\x{8EC8}\x{8ECA}\x{8ECB}\x{8ECC}\x{8ECD}\x{8ED2}' . + '\x{8EDB}\x{8EDF}\x{8EE2}\x{8EE3}\x{8EEB}\x{8EF8}\x{8EFB}\x{8EFC}\x{8EFD}' . + '\x{8EFE}\x{8F03}\x{8F05}\x{8F09}\x{8F0A}\x{8F0C}\x{8F12}\x{8F13}\x{8F14}' . + '\x{8F15}\x{8F19}\x{8F1B}\x{8F1C}\x{8F1D}\x{8F1F}\x{8F26}\x{8F29}\x{8F2A}' . + '\x{8F2F}\x{8F33}\x{8F38}\x{8F39}\x{8F3B}\x{8F3E}\x{8F3F}\x{8F42}\x{8F44}' . + '\x{8F45}\x{8F46}\x{8F49}\x{8F4C}\x{8F4D}\x{8F4E}\x{8F57}\x{8F5C}\x{8F5F}' . + '\x{8F61}\x{8F62}\x{8F63}\x{8F64}\x{8F9B}\x{8F9C}\x{8F9E}\x{8F9F}\x{8FA3}' . + '\x{8FA7}\x{8FA8}\x{8FAD}\x{8FAE}\x{8FAF}\x{8FB0}\x{8FB1}\x{8FB2}\x{8FB7}' . + '\x{8FBA}\x{8FBB}\x{8FBC}\x{8FBF}\x{8FC2}\x{8FC4}\x{8FC5}\x{8FCE}\x{8FD1}' . + '\x{8FD4}\x{8FDA}\x{8FE2}\x{8FE5}\x{8FE6}\x{8FE9}\x{8FEA}\x{8FEB}\x{8FED}' . + '\x{8FEF}\x{8FF0}\x{8FF4}\x{8FF7}\x{8FF8}\x{8FF9}\x{8FFA}\x{8FFD}\x{9000}' . + '\x{9001}\x{9003}\x{9005}\x{9006}\x{900B}\x{900D}\x{900E}\x{900F}\x{9010}' . + '\x{9011}\x{9013}\x{9014}\x{9015}\x{9016}\x{9017}\x{9019}\x{901A}\x{901D}' . + '\x{901E}\x{901F}\x{9020}\x{9021}\x{9022}\x{9023}\x{9027}\x{902E}\x{9031}' . + '\x{9032}\x{9035}\x{9036}\x{9038}\x{9039}\x{903C}\x{903E}\x{9041}\x{9042}' . + '\x{9045}\x{9047}\x{9049}\x{904A}\x{904B}\x{904D}\x{904E}\x{904F}\x{9050}' . + '\x{9051}\x{9052}\x{9053}\x{9054}\x{9055}\x{9056}\x{9058}\x{9059}\x{905C}' . + '\x{905E}\x{9060}\x{9061}\x{9063}\x{9065}\x{9068}\x{9069}\x{906D}\x{906E}' . + '\x{906F}\x{9072}\x{9075}\x{9076}\x{9077}\x{9078}\x{907A}\x{907C}\x{907D}' . + '\x{907F}\x{9080}\x{9081}\x{9082}\x{9083}\x{9084}\x{9087}\x{9089}\x{908A}' . + '\x{908F}\x{9091}\x{90A3}\x{90A6}\x{90A8}\x{90AA}\x{90AF}\x{90B1}\x{90B5}' . + '\x{90B8}\x{90C1}\x{90CA}\x{90CE}\x{90DB}\x{90E1}\x{90E2}\x{90E4}\x{90E8}' . + '\x{90ED}\x{90F5}\x{90F7}\x{90FD}\x{9102}\x{9112}\x{9119}\x{912D}\x{9130}' . + '\x{9132}\x{9149}\x{914A}\x{914B}\x{914C}\x{914D}\x{914E}\x{9152}\x{9154}' . + '\x{9156}\x{9158}\x{9162}\x{9163}\x{9165}\x{9169}\x{916A}\x{916C}\x{9172}' . + '\x{9173}\x{9175}\x{9177}\x{9178}\x{9182}\x{9187}\x{9189}\x{918B}\x{918D}' . + '\x{9190}\x{9192}\x{9197}\x{919C}\x{91A2}\x{91A4}\x{91AA}\x{91AB}\x{91AF}' . + '\x{91B4}\x{91B5}\x{91B8}\x{91BA}\x{91C0}\x{91C1}\x{91C6}\x{91C7}\x{91C8}' . + '\x{91C9}\x{91CB}\x{91CC}\x{91CD}\x{91CE}\x{91CF}\x{91D0}\x{91D1}\x{91D6}' . + '\x{91D8}\x{91DB}\x{91DC}\x{91DD}\x{91DF}\x{91E1}\x{91E3}\x{91E6}\x{91E7}' . + '\x{91F5}\x{91F6}\x{91FC}\x{91FF}\x{920D}\x{920E}\x{9211}\x{9214}\x{9215}' . + '\x{921E}\x{9229}\x{922C}\x{9234}\x{9237}\x{923F}\x{9244}\x{9245}\x{9248}' . + '\x{9249}\x{924B}\x{9250}\x{9257}\x{925A}\x{925B}\x{925E}\x{9262}\x{9264}' . + '\x{9266}\x{9271}\x{927E}\x{9280}\x{9283}\x{9285}\x{9291}\x{9293}\x{9295}' . + '\x{9296}\x{9298}\x{929A}\x{929B}\x{929C}\x{92AD}\x{92B7}\x{92B9}\x{92CF}' . + '\x{92D2}\x{92E4}\x{92E9}\x{92EA}\x{92ED}\x{92F2}\x{92F3}\x{92F8}\x{92FA}' . + '\x{92FC}\x{9306}\x{930F}\x{9310}\x{9318}\x{9319}\x{931A}\x{9320}\x{9322}' . + '\x{9323}\x{9326}\x{9328}\x{932B}\x{932C}\x{932E}\x{932F}\x{9332}\x{9335}' . + '\x{933A}\x{933B}\x{9344}\x{934B}\x{934D}\x{9354}\x{9356}\x{935B}\x{935C}' . + '\x{9360}\x{936C}\x{936E}\x{9375}\x{937C}\x{937E}\x{938C}\x{9394}\x{9396}' . + '\x{9397}\x{939A}\x{93A7}\x{93AC}\x{93AD}\x{93AE}\x{93B0}\x{93B9}\x{93C3}' . + '\x{93C8}\x{93D0}\x{93D1}\x{93D6}\x{93D7}\x{93D8}\x{93DD}\x{93E1}\x{93E4}' . + '\x{93E5}\x{93E8}\x{9403}\x{9407}\x{9410}\x{9413}\x{9414}\x{9418}\x{9419}' . + '\x{941A}\x{9421}\x{942B}\x{9435}\x{9436}\x{9438}\x{943A}\x{9441}\x{9444}' . + '\x{9451}\x{9452}\x{9453}\x{945A}\x{945B}\x{945E}\x{9460}\x{9462}\x{946A}' . + '\x{9470}\x{9475}\x{9477}\x{947C}\x{947D}\x{947E}\x{947F}\x{9481}\x{9577}' . + '\x{9580}\x{9582}\x{9583}\x{9587}\x{9589}\x{958A}\x{958B}\x{958F}\x{9591}' . + '\x{9593}\x{9594}\x{9596}\x{9598}\x{9599}\x{95A0}\x{95A2}\x{95A3}\x{95A4}' . + '\x{95A5}\x{95A7}\x{95A8}\x{95AD}\x{95B2}\x{95B9}\x{95BB}\x{95BC}\x{95BE}' . + '\x{95C3}\x{95C7}\x{95CA}\x{95CC}\x{95CD}\x{95D4}\x{95D5}\x{95D6}\x{95D8}' . + '\x{95DC}\x{95E1}\x{95E2}\x{95E5}\x{961C}\x{9621}\x{9628}\x{962A}\x{962E}' . + '\x{962F}\x{9632}\x{963B}\x{963F}\x{9640}\x{9642}\x{9644}\x{964B}\x{964C}' . + '\x{964D}\x{964F}\x{9650}\x{965B}\x{965C}\x{965D}\x{965E}\x{965F}\x{9662}' . + '\x{9663}\x{9664}\x{9665}\x{9666}\x{966A}\x{966C}\x{9670}\x{9672}\x{9673}' . + '\x{9675}\x{9676}\x{9677}\x{9678}\x{967A}\x{967D}\x{9685}\x{9686}\x{9688}' . + '\x{968A}\x{968B}\x{968D}\x{968E}\x{968F}\x{9694}\x{9695}\x{9697}\x{9698}' . + '\x{9699}\x{969B}\x{969C}\x{96A0}\x{96A3}\x{96A7}\x{96A8}\x{96AA}\x{96B0}' . + '\x{96B1}\x{96B2}\x{96B4}\x{96B6}\x{96B7}\x{96B8}\x{96B9}\x{96BB}\x{96BC}' . + '\x{96C0}\x{96C1}\x{96C4}\x{96C5}\x{96C6}\x{96C7}\x{96C9}\x{96CB}\x{96CC}' . + '\x{96CD}\x{96CE}\x{96D1}\x{96D5}\x{96D6}\x{96D9}\x{96DB}\x{96DC}\x{96E2}' . + '\x{96E3}\x{96E8}\x{96EA}\x{96EB}\x{96F0}\x{96F2}\x{96F6}\x{96F7}\x{96F9}' . + '\x{96FB}\x{9700}\x{9704}\x{9706}\x{9707}\x{9708}\x{970A}\x{970D}\x{970E}' . + '\x{970F}\x{9711}\x{9713}\x{9716}\x{9719}\x{971C}\x{971E}\x{9724}\x{9727}' . + '\x{972A}\x{9730}\x{9732}\x{9738}\x{9739}\x{973D}\x{973E}\x{9742}\x{9744}' . + '\x{9746}\x{9748}\x{9749}\x{9752}\x{9756}\x{9759}\x{975C}\x{975E}\x{9760}' . + '\x{9761}\x{9762}\x{9764}\x{9766}\x{9768}\x{9769}\x{976B}\x{976D}\x{9771}' . + '\x{9774}\x{9779}\x{977A}\x{977C}\x{9781}\x{9784}\x{9785}\x{9786}\x{978B}' . + '\x{978D}\x{978F}\x{9790}\x{9798}\x{979C}\x{97A0}\x{97A3}\x{97A6}\x{97A8}' . + '\x{97AB}\x{97AD}\x{97B3}\x{97B4}\x{97C3}\x{97C6}\x{97C8}\x{97CB}\x{97D3}' . + '\x{97DC}\x{97ED}\x{97EE}\x{97F2}\x{97F3}\x{97F5}\x{97F6}\x{97FB}\x{97FF}' . + '\x{9801}\x{9802}\x{9803}\x{9805}\x{9806}\x{9808}\x{980C}\x{980F}\x{9810}' . + '\x{9811}\x{9812}\x{9813}\x{9817}\x{9818}\x{981A}\x{9821}\x{9824}\x{982C}' . + '\x{982D}\x{9834}\x{9837}\x{9838}\x{983B}\x{983C}\x{983D}\x{9846}\x{984B}' . + '\x{984C}\x{984D}\x{984E}\x{984F}\x{9854}\x{9855}\x{9858}\x{985B}\x{985E}' . + '\x{9867}\x{986B}\x{986F}\x{9870}\x{9871}\x{9873}\x{9874}\x{98A8}\x{98AA}' . + '\x{98AF}\x{98B1}\x{98B6}\x{98C3}\x{98C4}\x{98C6}\x{98DB}\x{98DC}\x{98DF}' . + '\x{98E2}\x{98E9}\x{98EB}\x{98ED}\x{98EE}\x{98EF}\x{98F2}\x{98F4}\x{98FC}' . + '\x{98FD}\x{98FE}\x{9903}\x{9905}\x{9909}\x{990A}\x{990C}\x{9910}\x{9912}' . + '\x{9913}\x{9914}\x{9918}\x{991D}\x{991E}\x{9920}\x{9921}\x{9924}\x{9928}' . + '\x{992C}\x{992E}\x{993D}\x{993E}\x{9942}\x{9945}\x{9949}\x{994B}\x{994C}' . + '\x{9950}\x{9951}\x{9952}\x{9955}\x{9957}\x{9996}\x{9997}\x{9998}\x{9999}' . + '\x{99A5}\x{99A8}\x{99AC}\x{99AD}\x{99AE}\x{99B3}\x{99B4}\x{99BC}\x{99C1}' . + '\x{99C4}\x{99C5}\x{99C6}\x{99C8}\x{99D0}\x{99D1}\x{99D2}\x{99D5}\x{99D8}' . + '\x{99DB}\x{99DD}\x{99DF}\x{99E2}\x{99ED}\x{99EE}\x{99F1}\x{99F2}\x{99F8}' . + '\x{99FB}\x{99FF}\x{9A01}\x{9A05}\x{9A0E}\x{9A0F}\x{9A12}\x{9A13}\x{9A19}' . + '\x{9A28}\x{9A2B}\x{9A30}\x{9A37}\x{9A3E}\x{9A40}\x{9A42}\x{9A43}\x{9A45}' . + '\x{9A4D}\x{9A55}\x{9A57}\x{9A5A}\x{9A5B}\x{9A5F}\x{9A62}\x{9A64}\x{9A65}' . + '\x{9A69}\x{9A6A}\x{9A6B}\x{9AA8}\x{9AAD}\x{9AB0}\x{9AB8}\x{9ABC}\x{9AC0}' . + '\x{9AC4}\x{9ACF}\x{9AD1}\x{9AD3}\x{9AD4}\x{9AD8}\x{9ADE}\x{9ADF}\x{9AE2}' . + '\x{9AE3}\x{9AE6}\x{9AEA}\x{9AEB}\x{9AED}\x{9AEE}\x{9AEF}\x{9AF1}\x{9AF4}' . + '\x{9AF7}\x{9AFB}\x{9B06}\x{9B18}\x{9B1A}\x{9B1F}\x{9B22}\x{9B23}\x{9B25}' . + '\x{9B27}\x{9B28}\x{9B29}\x{9B2A}\x{9B2E}\x{9B2F}\x{9B31}\x{9B32}\x{9B3B}' . + '\x{9B3C}\x{9B41}\x{9B42}\x{9B43}\x{9B44}\x{9B45}\x{9B4D}\x{9B4E}\x{9B4F}' . + '\x{9B51}\x{9B54}\x{9B58}\x{9B5A}\x{9B6F}\x{9B74}\x{9B83}\x{9B8E}\x{9B91}' . + '\x{9B92}\x{9B93}\x{9B96}\x{9B97}\x{9B9F}\x{9BA0}\x{9BA8}\x{9BAA}\x{9BAB}' . + '\x{9BAD}\x{9BAE}\x{9BB4}\x{9BB9}\x{9BC0}\x{9BC6}\x{9BC9}\x{9BCA}\x{9BCF}' . + '\x{9BD1}\x{9BD2}\x{9BD4}\x{9BD6}\x{9BDB}\x{9BE1}\x{9BE2}\x{9BE3}\x{9BE4}' . + '\x{9BE8}\x{9BF0}\x{9BF1}\x{9BF2}\x{9BF5}\x{9C04}\x{9C06}\x{9C08}\x{9C09}' . + '\x{9C0A}\x{9C0C}\x{9C0D}\x{9C10}\x{9C12}\x{9C13}\x{9C14}\x{9C15}\x{9C1B}' . + '\x{9C21}\x{9C24}\x{9C25}\x{9C2D}\x{9C2E}\x{9C2F}\x{9C30}\x{9C32}\x{9C39}' . + '\x{9C3A}\x{9C3B}\x{9C3E}\x{9C46}\x{9C47}\x{9C48}\x{9C52}\x{9C57}\x{9C5A}' . + '\x{9C60}\x{9C67}\x{9C76}\x{9C78}\x{9CE5}\x{9CE7}\x{9CE9}\x{9CEB}\x{9CEC}' . + '\x{9CF0}\x{9CF3}\x{9CF4}\x{9CF6}\x{9D03}\x{9D06}\x{9D07}\x{9D08}\x{9D09}' . + '\x{9D0E}\x{9D12}\x{9D15}\x{9D1B}\x{9D1F}\x{9D23}\x{9D26}\x{9D28}\x{9D2A}' . + '\x{9D2B}\x{9D2C}\x{9D3B}\x{9D3E}\x{9D3F}\x{9D41}\x{9D44}\x{9D46}\x{9D48}' . + '\x{9D50}\x{9D51}\x{9D59}\x{9D5C}\x{9D5D}\x{9D5E}\x{9D60}\x{9D61}\x{9D64}' . + '\x{9D6C}\x{9D6F}\x{9D72}\x{9D7A}\x{9D87}\x{9D89}\x{9D8F}\x{9D9A}\x{9DA4}' . + '\x{9DA9}\x{9DAB}\x{9DAF}\x{9DB2}\x{9DB4}\x{9DB8}\x{9DBA}\x{9DBB}\x{9DC1}' . + '\x{9DC2}\x{9DC4}\x{9DC6}\x{9DCF}\x{9DD3}\x{9DD9}\x{9DE6}\x{9DED}\x{9DEF}' . + '\x{9DF2}\x{9DF8}\x{9DF9}\x{9DFA}\x{9DFD}\x{9E1A}\x{9E1B}\x{9E1E}\x{9E75}' . + '\x{9E78}\x{9E79}\x{9E7D}\x{9E7F}\x{9E81}\x{9E88}\x{9E8B}\x{9E8C}\x{9E91}' . + '\x{9E92}\x{9E93}\x{9E95}\x{9E97}\x{9E9D}\x{9E9F}\x{9EA5}\x{9EA6}\x{9EA9}' . + '\x{9EAA}\x{9EAD}\x{9EB8}\x{9EB9}\x{9EBA}\x{9EBB}\x{9EBC}\x{9EBE}\x{9EBF}' . + '\x{9EC4}\x{9ECC}\x{9ECD}\x{9ECE}\x{9ECF}\x{9ED0}\x{9ED2}\x{9ED4}\x{9ED8}' . + '\x{9ED9}\x{9EDB}\x{9EDC}\x{9EDD}\x{9EDE}\x{9EE0}\x{9EE5}\x{9EE8}\x{9EEF}' . + '\x{9EF4}\x{9EF6}\x{9EF7}\x{9EF9}\x{9EFB}\x{9EFC}\x{9EFD}\x{9F07}\x{9F08}' . + '\x{9F0E}\x{9F13}\x{9F15}\x{9F20}\x{9F21}\x{9F2C}\x{9F3B}\x{9F3E}\x{9F4A}' . + '\x{9F4B}\x{9F4E}\x{9F4F}\x{9F52}\x{9F54}\x{9F5F}\x{9F60}\x{9F61}\x{9F62}' . + '\x{9F63}\x{9F66}\x{9F67}\x{9F6A}\x{9F6C}\x{9F72}\x{9F76}\x{9F77}\x{9F8D}' . + '\x{9F95}\x{9F9C}\x{9F9D}\x{9FA0}]{1,15}$/iu', +]; diff --git a/lib/laminas/laminas-validator/src/Iban.php b/lib/laminas/laminas-validator/src/Iban.php new file mode 100644 index 000000000..2e7951b9e --- /dev/null +++ b/lib/laminas/laminas-validator/src/Iban.php @@ -0,0 +1,274 @@ + 'Unknown country within the IBAN', + self::SEPANOTSUPPORTED => 'Countries outside the Single Euro Payments Area (SEPA) are not supported', + self::FALSEFORMAT => 'The input has a false IBAN format', + self::CHECKFAILED => 'The input has failed the IBAN check', + ]; + + /** + * Optional country code by ISO 3166-1 + * + * @var string|null + */ + protected $countryCode; + + /** + * Optionally allow IBAN codes from non-SEPA countries. Defaults to true + * + * @var bool + */ + protected $allowNonSepa = true; + + /** + * The SEPA country codes + * + * @var array + */ + protected static $sepaCountries = [ + 'AT', 'BE', 'BG', 'CY', 'CZ', 'DK', 'FO', 'GL', 'EE', 'FI', 'FR', 'DE', + 'GI', 'GR', 'HU', 'IS', 'IE', 'IT', 'LV', 'LI', 'LT', 'LU', 'MT', 'MC', + 'NL', 'NO', 'PL', 'PT', 'RO', 'SK', 'SI', 'ES', 'SE', 'CH', 'GB', 'SM', + 'HR', + ]; + + /** + * IBAN regexes by country code + * + * @var array + */ + protected static $ibanRegex = [ + 'AD' => 'AD[0-9]{2}[0-9]{4}[0-9]{4}[A-Z0-9]{12}', + 'AE' => 'AE[0-9]{2}[0-9]{3}[0-9]{16}', + 'AL' => 'AL[0-9]{2}[0-9]{8}[A-Z0-9]{16}', + 'AT' => 'AT[0-9]{2}[0-9]{5}[0-9]{11}', + 'AZ' => 'AZ[0-9]{2}[A-Z]{4}[A-Z0-9]{20}', + 'BA' => 'BA[0-9]{2}[0-9]{3}[0-9]{3}[0-9]{8}[0-9]{2}', + 'BE' => 'BE[0-9]{2}[0-9]{3}[0-9]{7}[0-9]{2}', + 'BG' => 'BG[0-9]{2}[A-Z]{4}[0-9]{4}[0-9]{2}[A-Z0-9]{8}', + 'BH' => 'BH[0-9]{2}[A-Z]{4}[A-Z0-9]{14}', + 'BR' => 'BR[0-9]{2}[0-9]{8}[0-9]{5}[0-9]{10}[A-Z][A-Z0-9]', + 'BY' => 'BY[0-9]{2}[A-Z0-9]{4}[0-9]{4}[A-Z0-9]{16}', + 'CH' => 'CH[0-9]{2}[0-9]{5}[A-Z0-9]{12}', + 'CR' => 'CR[0-9]{2}[0-9]{3}[0-9]{14}', + 'CY' => 'CY[0-9]{2}[0-9]{3}[0-9]{5}[A-Z0-9]{16}', + 'CZ' => 'CZ[0-9]{2}[0-9]{20}', + 'DE' => 'DE[0-9]{2}[0-9]{8}[0-9]{10}', + 'DO' => 'DO[0-9]{2}[A-Z0-9]{4}[0-9]{20}', + 'DK' => 'DK[0-9]{2}[0-9]{14}', + 'EE' => 'EE[0-9]{2}[0-9]{2}[0-9]{2}[0-9]{11}[0-9]{1}', + 'ES' => 'ES[0-9]{2}[0-9]{4}[0-9]{4}[0-9]{1}[0-9]{1}[0-9]{10}', + 'FI' => 'FI[0-9]{2}[0-9]{6}[0-9]{7}[0-9]{1}', + 'FO' => 'FO[0-9]{2}[0-9]{4}[0-9]{9}[0-9]{1}', + 'FR' => 'FR[0-9]{2}[0-9]{5}[0-9]{5}[A-Z0-9]{11}[0-9]{2}', + 'GB' => 'GB[0-9]{2}[A-Z]{4}[0-9]{6}[0-9]{8}', + 'GE' => 'GE[0-9]{2}[A-Z]{2}[0-9]{16}', + 'GI' => 'GI[0-9]{2}[A-Z]{4}[A-Z0-9]{15}', + 'GL' => 'GL[0-9]{2}[0-9]{4}[0-9]{9}[0-9]{1}', + 'GR' => 'GR[0-9]{2}[0-9]{3}[0-9]{4}[A-Z0-9]{16}', + 'GT' => 'GT[0-9]{2}[A-Z0-9]{4}[A-Z0-9]{20}', + 'HR' => 'HR[0-9]{2}[0-9]{7}[0-9]{10}', + 'HU' => 'HU[0-9]{2}[0-9]{3}[0-9]{4}[0-9]{1}[0-9]{15}[0-9]{1}', + 'IE' => 'IE[0-9]{2}[A-Z]{4}[0-9]{6}[0-9]{8}', + 'IL' => 'IL[0-9]{2}[0-9]{3}[0-9]{3}[0-9]{13}', + 'IS' => 'IS[0-9]{2}[0-9]{4}[0-9]{2}[0-9]{6}[0-9]{10}', + 'IT' => 'IT[0-9]{2}[A-Z]{1}[0-9]{5}[0-9]{5}[A-Z0-9]{12}', + 'KW' => 'KW[0-9]{2}[A-Z]{4}[0-9]{22}', + 'KZ' => 'KZ[0-9]{2}[0-9]{3}[A-Z0-9]{13}', + 'LB' => 'LB[0-9]{2}[0-9]{4}[A-Z0-9]{20}', + 'LI' => 'LI[0-9]{2}[0-9]{5}[A-Z0-9]{12}', + 'LT' => 'LT[0-9]{2}[0-9]{5}[0-9]{11}', + 'LU' => 'LU[0-9]{2}[0-9]{3}[A-Z0-9]{13}', + 'LV' => 'LV[0-9]{2}[A-Z]{4}[A-Z0-9]{13}', + 'MC' => 'MC[0-9]{2}[0-9]{5}[0-9]{5}[A-Z0-9]{11}[0-9]{2}', + 'MD' => 'MD[0-9]{2}[A-Z0-9]{20}', + 'ME' => 'ME[0-9]{2}[0-9]{3}[0-9]{13}[0-9]{2}', + 'MK' => 'MK[0-9]{2}[0-9]{3}[A-Z0-9]{10}[0-9]{2}', + 'MR' => 'MR13[0-9]{5}[0-9]{5}[0-9]{11}[0-9]{2}', + 'MT' => 'MT[0-9]{2}[A-Z]{4}[0-9]{5}[A-Z0-9]{18}', + 'MU' => 'MU[0-9]{2}[A-Z]{4}[0-9]{2}[0-9]{2}[0-9]{12}[0-9]{3}[A-Z]{3}', + 'NL' => 'NL[0-9]{2}[A-Z]{4}[0-9]{10}', + 'NO' => 'NO[0-9]{2}[0-9]{4}[0-9]{6}[0-9]{1}', + 'PK' => 'PK[0-9]{2}[A-Z]{4}[A-Z0-9]{16}', + 'PL' => 'PL[0-9]{2}[0-9]{8}[0-9]{16}', + 'PS' => 'PS[0-9]{2}[A-Z]{4}[A-Z0-9]{21}', + 'PT' => 'PT[0-9]{2}[0-9]{4}[0-9]{4}[0-9]{11}[0-9]{2}', + 'RO' => 'RO[0-9]{2}[A-Z]{4}[A-Z0-9]{16}', + 'RS' => 'RS[0-9]{2}[0-9]{3}[0-9]{13}[0-9]{2}', + 'SA' => 'SA[0-9]{2}[0-9]{2}[A-Z0-9]{18}', + 'SE' => 'SE[0-9]{2}[0-9]{3}[0-9]{16}[0-9]{1}', + 'SI' => 'SI[0-9]{2}[0-9]{5}[0-9]{8}[0-9]{2}', + 'SK' => 'SK[0-9]{2}[0-9]{4}[0-9]{6}[0-9]{10}', + 'SM' => 'SM[0-9]{2}[A-Z]{1}[0-9]{5}[0-9]{5}[A-Z0-9]{12}', + 'TN' => 'TN59[0-9]{2}[0-9]{3}[0-9]{13}[0-9]{2}', + 'TR' => 'TR[0-9]{2}[0-9]{5}[A-Z0-9]{1}[A-Z0-9]{16}', + 'VG' => 'VG[0-9]{2}[A-Z]{4}[0-9]{16}', + ]; + + /** + * Sets validator options + * + * @param array|Traversable $options OPTIONAL + */ + public function __construct($options = []) + { + if ($options instanceof Traversable) { + $options = ArrayUtils::iteratorToArray($options); + } + + if (array_key_exists('country_code', $options)) { + $this->setCountryCode($options['country_code']); + } + + if (array_key_exists('allow_non_sepa', $options)) { + $this->setAllowNonSepa($options['allow_non_sepa']); + } + + parent::__construct($options); + } + + /** + * Returns the optional country code by ISO 3166-1 + * + * @return string|null + */ + public function getCountryCode() + { + return $this->countryCode; + } + + /** + * Sets an optional country code by ISO 3166-1 + * + * @param string|null $countryCode + * @return $this provides a fluent interface + * @throws Exception\InvalidArgumentException + */ + public function setCountryCode($countryCode = null) + { + if ($countryCode !== null) { + $countryCode = (string) $countryCode; + + if (! isset(static::$ibanRegex[$countryCode])) { + throw new Exception\InvalidArgumentException( + "Country code '{$countryCode}' invalid by ISO 3166-1 or not supported" + ); + } + } + + $this->countryCode = $countryCode; + return $this; + } + + /** + * Returns the optional allow non-sepa countries setting + * + * @return bool + */ + public function allowNonSepa() + { + return $this->allowNonSepa; + } + + /** + * Sets the optional allow non-sepa countries setting + * + * @param bool $allowNonSepa + * @return $this provides a fluent interface + */ + public function setAllowNonSepa($allowNonSepa) + { + $this->allowNonSepa = (bool) $allowNonSepa; + return $this; + } + + /** + * Returns true if $value is a valid IBAN + * + * @param string $value + * @return bool + */ + public function isValid($value) + { + if (! is_string($value)) { + $this->error(self::FALSEFORMAT); + return false; + } + + $value = str_replace(' ', '', strtoupper($value)); + $this->setValue($value); + + $countryCode = $this->getCountryCode(); + if ($countryCode === null) { + $countryCode = substr($value, 0, 2); + } + + if (! array_key_exists($countryCode, static::$ibanRegex)) { + $this->setValue($countryCode); + $this->error(self::NOTSUPPORTED); + return false; + } + + if (! $this->allowNonSepa && ! in_array($countryCode, static::$sepaCountries)) { + $this->setValue($countryCode); + $this->error(self::SEPANOTSUPPORTED); + return false; + } + + if (! preg_match('/^' . static::$ibanRegex[$countryCode] . '$/', $value)) { + $this->error(self::FALSEFORMAT); + return false; + } + + $format = substr($value, 4) . substr($value, 0, 4); + $format = str_replace( + ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', + 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z'], + ['10', '11', '12', '13', '14', '15', '16', '17', '18', '19', '20', '21', '22', + '23', '24', '25', '26', '27', '28', '29', '30', '31', '32', '33', '34', '35'], + $format + ); + + $temp = intval(substr($format, 0, 1)); + $len = strlen($format); + for ($x = 1; $x < $len; ++$x) { + $temp *= 10; + $temp += intval(substr($format, $x, 1)); + $temp %= 97; + } + + if ($temp != 1) { + $this->error(self::CHECKFAILED); + return false; + } + + return true; + } +} diff --git a/lib/laminas/laminas-validator/src/Identical.php b/lib/laminas/laminas-validator/src/Identical.php new file mode 100644 index 000000000..a42edab85 --- /dev/null +++ b/lib/laminas/laminas-validator/src/Identical.php @@ -0,0 +1,201 @@ + 'The two given tokens do not match', + self::MISSING_TOKEN => 'No token was provided to match against', + ]; + + /** + * @var array + */ + protected $messageVariables = [ + 'token' => 'tokenString', + ]; + + /** + * Original token against which to validate + * @var string + */ + protected $tokenString; + protected $token; + protected $strict = true; + protected $literal = false; + + /** + * Sets validator options + * + * @param mixed $token + */ + public function __construct($token = null) + { + if ($token instanceof Traversable) { + $token = ArrayUtils::iteratorToArray($token); + } + + if (is_array($token) && array_key_exists('token', $token)) { + if (array_key_exists('strict', $token)) { + $this->setStrict($token['strict']); + } + + if (array_key_exists('literal', $token)) { + $this->setLiteral($token['literal']); + } + + $this->setToken($token['token']); + } elseif (null !== $token) { + $this->setToken($token); + } + + parent::__construct(is_array($token) ? $token : null); + } + + /** + * Retrieve token + * + * @return mixed + */ + public function getToken() + { + return $this->token; + } + + /** + * Set token against which to compare + * + * @param mixed $token + * @return $this + */ + public function setToken($token) + { + $this->tokenString = is_array($token) ? var_export($token, true) : (string) $token; + $this->token = $token; + return $this; + } + + /** + * Returns the strict parameter + * + * @return bool + */ + public function getStrict() + { + return $this->strict; + } + + /** + * Sets the strict parameter + * + * @param bool $strict + * @return $this + */ + public function setStrict($strict) + { + $this->strict = (bool) $strict; + return $this; + } + + /** + * Returns the literal parameter + * + * @return bool + */ + public function getLiteral() + { + return $this->literal; + } + + /** + * Sets the literal parameter + * + * @param bool $literal + * @return $this + */ + public function setLiteral($literal) + { + $this->literal = (bool) $literal; + return $this; + } + + /** + * Returns true if and only if a token has been set and the provided value + * matches that token. + * + * @param mixed $value + * @param array|ArrayAccess $context + * @throws Exception\InvalidArgumentException If context is not array or ArrayObject + * @return bool + */ + public function isValid($value, $context = null) + { + $this->setValue($value); + + $token = $this->getToken(); + + if (! $this->getLiteral() && $context !== null) { + if (! is_array($context) && ! $context instanceof ArrayAccess) { + throw new Exception\InvalidArgumentException(sprintf( + 'Context passed to %s must be array, ArrayObject or null; received "%s"', + __METHOD__, + is_object($context) ? get_class($context) : gettype($context) + )); + } + + if (is_array($token)) { + while (is_array($token)) { + $key = key($token); + if (! isset($context[$key])) { + break; + } + $context = $context[$key]; + $token = $token[$key]; + } + } + + // if $token is an array it means the above loop didn't went all the way down to the leaf, + // so the $token structure doesn't match the $context structure + if (is_array($token) || ! isset($context[$token])) { + $token = $this->getToken(); + } else { + $token = $context[$token]; + } + } + + if ($token === null) { + $this->error(self::MISSING_TOKEN); + return false; + } + + $strict = $this->getStrict(); + if (($strict && ($value !== $token)) || (! $strict && ($value != $token))) { + $this->error(self::NOT_SAME); + return false; + } + + return true; + } +} diff --git a/lib/laminas/laminas-validator/src/InArray.php b/lib/laminas/laminas-validator/src/InArray.php new file mode 100644 index 000000000..b4dde85f9 --- /dev/null +++ b/lib/laminas/laminas-validator/src/InArray.php @@ -0,0 +1,229 @@ + 'The input was not found in the haystack', + ]; + + /** + * Haystack of possible values + * + * @var array + */ + protected $haystack; + + /** + * Type of strict check to be used. Due to "foo" == 0 === TRUE with in_array when strict = false, + * an option has been added to prevent this. When $strict = 0/false, the most + * secure non-strict check is implemented. if $strict = -1, the default in_array non-strict + * behaviour is used + * + * @var int + */ + protected $strict = self::COMPARE_NOT_STRICT_AND_PREVENT_STR_TO_INT_VULNERABILITY; + + /** + * Whether a recursive search should be done + * + * @var bool + */ + protected $recursive = false; + + /** + * Returns the haystack option + * + * @return mixed + * @throws Exception\RuntimeException if haystack option is not set + */ + public function getHaystack() + { + if ($this->haystack === null) { + throw new Exception\RuntimeException('haystack option is mandatory'); + } + return $this->haystack; + } + + /** + * Sets the haystack option + * + * @param mixed $haystack + * @return $this Provides a fluent interface + */ + public function setHaystack(array $haystack) + { + $this->haystack = $haystack; + return $this; + } + + /** + * Returns the strict option + * + * @return bool|int + */ + public function getStrict() + { + // To keep BC with new strict modes + if ($this->strict == self::COMPARE_NOT_STRICT_AND_PREVENT_STR_TO_INT_VULNERABILITY + || $this->strict == self::COMPARE_STRICT + ) { + return (bool) $this->strict; + } + return $this->strict; + } + + /** + * Sets the strict option mode + * InArray::COMPARE_STRICT + * InArray::COMPARE_NOT_STRICT_AND_PREVENT_STR_TO_INT_VULNERABILITY + * InArray::COMPARE_NOT_STRICT + * + * @param int $strict + * @return $this Provides a fluent interface + * @throws Exception\InvalidArgumentException + */ + public function setStrict($strict) + { + $checkTypes = [ + self::COMPARE_NOT_STRICT_AND_PREVENT_STR_TO_INT_VULNERABILITY, // 0 + self::COMPARE_STRICT, // 1 + self::COMPARE_NOT_STRICT, // -1 + ]; + + // validate strict value + if (! in_array($strict, $checkTypes)) { + throw new Exception\InvalidArgumentException('Strict option must be one of the COMPARE_ constants'); + } + + $this->strict = $strict; + return $this; + } + + /** + * Returns the recursive option + * + * @return bool + */ + public function getRecursive() + { + return $this->recursive; + } + + /** + * Sets the recursive option + * + * @param bool $recursive + * @return $this Provides a fluent interface + */ + public function setRecursive($recursive) + { + $this->recursive = (bool) $recursive; + return $this; + } + + /** + * Returns true if and only if $value is contained in the haystack option. If the strict + * option is true, then the type of $value is also checked. + * + * @param mixed $value + * See {@link http://php.net/manual/function.in-array.php#104501} + * @return bool + */ + public function isValid($value) + { + // we create a copy of the haystack in case we need to modify it + $haystack = $this->getHaystack(); + + // if the input is a string or float, and vulnerability protection is on + // we type cast the input to a string + if (self::COMPARE_NOT_STRICT_AND_PREVENT_STR_TO_INT_VULNERABILITY == $this->strict + && (is_int($value) || is_float($value))) { + $value = (string) $value; + } + + $this->setValue($value); + + if ($this->getRecursive()) { + $iterator = new RecursiveIteratorIterator(new RecursiveArrayIterator($haystack)); + foreach ($iterator as $element) { + if (self::COMPARE_STRICT == $this->strict) { + if ($element === $value) { + return true; + } + } else { + // add protection to prevent string to int vuln's + $el = $element; + if (self::COMPARE_NOT_STRICT_AND_PREVENT_STR_TO_INT_VULNERABILITY == $this->strict + && is_string($value) && (is_int($el) || is_float($el)) + ) { + $el = (string) $el; + } + + if ($el == $value) { + return true; + } + } + } + } else { + /** + * If the check is not strict, then, to prevent "asdf" being converted to 0 + * and returning a false positive if 0 is in haystack, we type cast + * the haystack to strings. To prevent "56asdf" == 56 === TRUE we also + * type cast values like 56 to strings as well. + * + * This occurs only if the input is a string and a haystack member is an int + */ + if (self::COMPARE_NOT_STRICT_AND_PREVENT_STR_TO_INT_VULNERABILITY == $this->strict + && is_string($value) + ) { + foreach ($haystack as &$h) { + if (is_int($h) || is_float($h)) { + $h = (string) $h; + } + } + } + + if (in_array($value, $haystack, self::COMPARE_STRICT == $this->strict)) { + return true; + } + } + + $this->error(self::NOT_IN_ARRAY); + return false; + } +} diff --git a/lib/laminas/laminas-validator/src/Ip.php b/lib/laminas/laminas-validator/src/Ip.php new file mode 100644 index 000000000..1aef04524 --- /dev/null +++ b/lib/laminas/laminas-validator/src/Ip.php @@ -0,0 +1,189 @@ + 'Invalid type given. String expected', + self::NOT_IP_ADDRESS => 'The input does not appear to be a valid IP address', + ]; + + /** + * Internal options + * + * @var array + */ + protected $options = [ + 'allowipv4' => true, // Enable IPv4 Validation + 'allowipv6' => true, // Enable IPv6 Validation + 'allowipvfuture' => false, // Enable IPvFuture Validation + 'allowliteral' => true, // Enable IPs in literal format (only IPv6 and IPvFuture) + ]; + + /** + * Sets the options for this validator + * + * @param array|Traversable $options + * @throws Exception\InvalidArgumentException If there is any kind of IP allowed or $options is not an array + * or Traversable. + * @return AbstractValidator + */ + public function setOptions($options = []) + { + parent::setOptions($options); + + if (! $this->options['allowipv4'] && ! $this->options['allowipv6'] && ! $this->options['allowipvfuture']) { + throw new Exception\InvalidArgumentException('Nothing to validate. Check your options'); + } + + return $this; + } + + /** + * Returns true if and only if $value is a valid IP address + * + * @param mixed $value + * @return bool + */ + public function isValid($value) + { + if (! is_string($value)) { + $this->error(self::INVALID); + return false; + } + + $this->setValue($value); + + if ($this->options['allowipv4'] && $this->validateIPv4($value)) { + return true; + } else { + if ((bool) $this->options['allowliteral']) { + static $regex = '/^\[(.*)\]$/'; + if ((bool) preg_match($regex, $value, $matches)) { + $value = $matches[1]; + } + } + + if (($this->options['allowipv6'] && $this->validateIPv6($value)) || + ($this->options['allowipvfuture'] && $this->validateIPvFuture($value)) + ) { + return true; + } + } + $this->error(self::NOT_IP_ADDRESS); + return false; + } + + /** + * Validates an IPv4 address + * + * @param string $value + * @return bool + */ + protected function validateIPv4($value) + { + if (preg_match('/^([01]{8}\.){3}[01]{8}\z/i', $value)) { + // binary format 00000000.00000000.00000000.00000000 + $value = bindec(substr($value, 0, 8)) . '.' . bindec(substr($value, 9, 8)) . '.' + . bindec(substr($value, 18, 8)) . '.' . bindec(substr($value, 27, 8)); + } elseif (preg_match('/^([0-9]{3}\.){3}[0-9]{3}\z/i', $value)) { + // octet format 777.777.777.777 + $value = (int) substr($value, 0, 3) . '.' . (int) substr($value, 4, 3) . '.' + . (int) substr($value, 8, 3) . '.' . (int) substr($value, 12, 3); + } elseif (preg_match('/^([0-9a-f]{2}\.){3}[0-9a-f]{2}\z/i', $value)) { + // hex format ff.ff.ff.ff + $value = hexdec(substr($value, 0, 2)) . '.' . hexdec(substr($value, 3, 2)) . '.' + . hexdec(substr($value, 6, 2)) . '.' . hexdec(substr($value, 9, 2)); + } + + $ip2long = ip2long($value); + if ($ip2long === false) { + return false; + } + + return $value == long2ip($ip2long); + } + + /** + * Validates an IPv6 address + * + * @param string $value Value to check against + * @return bool True when $value is a valid ipv6 address + * False otherwise + */ + protected function validateIPv6($value) + { + if (strlen($value) < 3) { + return $value == '::'; + } + + if (strpos($value, '.')) { + $lastcolon = strrpos($value, ':'); + if (! ($lastcolon && $this->validateIPv4(substr($value, $lastcolon + 1)))) { + return false; + } + + $value = substr($value, 0, $lastcolon) . ':0:0'; + } + + if (strpos($value, '::') === false) { + return preg_match('/\A(?:[a-f0-9]{1,4}:){7}[a-f0-9]{1,4}\z/i', $value); + } + + $colonCount = substr_count($value, ':'); + if ($colonCount < 8) { + return preg_match('/\A(?::|(?:[a-f0-9]{1,4}:)+):(?:(?:[a-f0-9]{1,4}:)*[a-f0-9]{1,4})?\z/i', $value); + } + + // special case with ending or starting double colon + if ($colonCount == 8) { + return preg_match('/\A(?:::)?(?:[a-f0-9]{1,4}:){6}[a-f0-9]{1,4}(?:::)?\z/i', $value); + } + + return false; + } + + /** + * Validates an IPvFuture address. + * + * IPvFuture is loosely defined in the Section 3.2.2 of RFC 3986 + * + * @param string $value Value to check against + * @return bool True when $value is a valid IPvFuture address + * False otherwise + */ + protected function validateIPvFuture($value) + { + /* + * ABNF: + * IPvFuture = "v" 1*HEXDIG "." 1*( unreserved / sub-delims / ":" ) + * unreserved = ALPHA / DIGIT / "-" / "." / "_" / "~" + * sub-delims = "!" / "$" / "&" / "'" / "(" / ")" / "*" / "+" / "," + * / ";" / "=" + */ + static $regex = '/^v([[:xdigit:]]+)\.[[:alnum:]\-\._~!\$&\'\(\)\*\+,;=:]+$/'; + + $result = (bool) preg_match($regex, $value, $matches); + + /* + * "As such, implementations must not provide the version flag for the + * existing IPv4 and IPv6 literal address forms described below." + */ + return $result && $matches[1] != 4 && $matches[1] != 6; + } +} diff --git a/lib/laminas/laminas-validator/src/IsCountable.php b/lib/laminas/laminas-validator/src/IsCountable.php new file mode 100644 index 000000000..b01bde39d --- /dev/null +++ b/lib/laminas/laminas-validator/src/IsCountable.php @@ -0,0 +1,198 @@ + 'The input must be an array or an instance of \\Countable', + self::NOT_EQUALS => "The input count must equal '%count%'", + self::GREATER_THAN => "The input count must be less than '%max%', inclusively", + self::LESS_THAN => "The input count must be greater than '%min%', inclusively", + ]; + + /** + * Additional variables available for validation failure messages + * + * @var array + */ + protected $messageVariables = [ + 'count' => ['options' => 'count'], + 'min' => ['options' => 'min'], + 'max' => ['options' => 'max'], + ]; + + /** + * Options for the between validator + * + * @var array + */ + protected $options = [ + 'count' => null, + 'min' => null, + 'max' => null, + ]; + + public function setOptions($options = []) + { + foreach (['count', 'min', 'max'] as $option) { + if (! is_array($options) || ! isset($options[$option])) { + continue; + } + + $method = sprintf('set%s', ucfirst($option)); + $this->$method($options[$option]); + unset($options[$option]); + } + + return parent::setOptions($options); + } + + /** + * Returns true if and only if $value is countable (and the count validates against optional values). + * + * @param iterable $value + * @return bool + */ + public function isValid($value) + { + if (! (is_array($value) || $value instanceof Countable)) { + $this->error(self::NOT_COUNTABLE); + return false; + } + + $count = count($value); + + if (is_numeric($this->getCount())) { + if ($count != $this->getCount()) { + $this->error(self::NOT_EQUALS); + return false; + } + + return true; + } + + if (is_numeric($this->getMax()) && $count > $this->getMax()) { + $this->error(self::GREATER_THAN); + return false; + } + + if (is_numeric($this->getMin()) && $count < $this->getMin()) { + $this->error(self::LESS_THAN); + return false; + } + + return true; + } + + /** + * Returns the count option + * + * @return mixed + */ + public function getCount() + { + return $this->options['count']; + } + + /** + * Returns the min option + * + * @return mixed + */ + public function getMin() + { + return $this->options['min']; + } + + /** + * Returns the max option + * + * @return mixed + */ + public function getMax() + { + return $this->options['max']; + } + + /** + * @param mixed $value + * @return void + * @throws Exception\InvalidArgumentException if either a min or max option + * was previously set. + */ + private function setCount($value) + { + if (isset($this->options['min']) || isset($this->options['max'])) { + throw new Exception\InvalidArgumentException( + 'Cannot set count; conflicts with either a min or max option previously set' + ); + } + $this->options['count'] = $value; + } + + /** + * @param mixed $value + * @return void + * @throws Exception\InvalidArgumentException if either a count or max option + * was previously set. + */ + private function setMin($value) + { + if (isset($this->options['count'])) { + throw new Exception\InvalidArgumentException( + 'Cannot set count; conflicts with either a count option previously set' + ); + } + $this->options['min'] = $value; + } + + /** + * @param mixed $value + * @return void + * @throws Exception\InvalidArgumentException if either a count or min option + * was previously set. + */ + private function setMax($value) + { + if (isset($this->options['count'])) { + throw new Exception\InvalidArgumentException( + 'Cannot set count; conflicts with either a count option previously set' + ); + } + $this->options['max'] = $value; + } +} diff --git a/lib/laminas/laminas-validator/src/IsInstanceOf.php b/lib/laminas/laminas-validator/src/IsInstanceOf.php new file mode 100644 index 000000000..44eb51c9e --- /dev/null +++ b/lib/laminas/laminas-validator/src/IsInstanceOf.php @@ -0,0 +1,106 @@ + "The input is not an instance of '%className%'", + ]; + + /** + * Additional variables available for validation failure messages + * + * @var array + */ + protected $messageVariables = [ + 'className' => 'className', + ]; + + /** + * Class name + * + * @var string + */ + protected $className; + + /** + * Sets validator options + * + * @param array|Traversable $options + * @throws Exception\InvalidArgumentException + */ + public function __construct($options = null) + { + if ($options instanceof Traversable) { + $options = iterator_to_array($options); + } + + // If argument is not an array, consider first argument as class name + if (! is_array($options)) { + $options = func_get_args(); + + $tmpOptions = []; + $tmpOptions['className'] = array_shift($options); + + $options = $tmpOptions; + } + + if (! array_key_exists('className', $options)) { + throw new Exception\InvalidArgumentException('Missing option "className"'); + } + + parent::__construct($options); + } + + /** + * Get class name + * + * @return string + */ + public function getClassName() + { + return $this->className; + } + + /** + * Set class name + * + * @param string $className + * @return $this + */ + public function setClassName($className) + { + $this->className = $className; + return $this; + } + + /** + * Returns true if $value is instance of $this->className + * + * @param mixed $value + * @return bool + */ + public function isValid($value) + { + if ($value instanceof $this->className) { + return true; + } + $this->error(self::NOT_INSTANCE_OF); + return false; + } +} diff --git a/lib/laminas/laminas-validator/src/Isbn.php b/lib/laminas/laminas-validator/src/Isbn.php new file mode 100644 index 000000000..eb2a729af --- /dev/null +++ b/lib/laminas/laminas-validator/src/Isbn.php @@ -0,0 +1,185 @@ + 'Invalid type given. String or integer expected', + self::NO_ISBN => 'The input is not a valid ISBN number', + ]; + + protected $options = [ + 'type' => self::AUTO, // Allowed type + 'separator' => '', // Separator character + ]; + + /** + * Detect input format. + * + * @return string + */ + protected function detectFormat() + { + // prepare separator and pattern list + $sep = quotemeta($this->getSeparator()); + $patterns = []; + $lengths = []; + $type = $this->getType(); + + // check for ISBN-10 + if ($type == self::ISBN10 || $type == self::AUTO) { + if (empty($sep)) { + $pattern = '/^[0-9]{9}[0-9X]{1}$/'; + $length = 10; + } else { + $pattern = "/^[0-9]{1,7}[{$sep}]{1}[0-9]{1,7}[{$sep}]{1}[0-9]{1,7}[{$sep}]{1}[0-9X]{1}$/"; + $length = 13; + } + + $patterns[$pattern] = self::ISBN10; + $lengths[$pattern] = $length; + } + + // check for ISBN-13 + if ($type == self::ISBN13 || $type == self::AUTO) { + if (empty($sep)) { + $pattern = '/^[0-9]{13}$/'; + $length = 13; + } else { + // @codingStandardsIgnoreStart + $pattern = "/^[0-9]{1,9}[{$sep}]{1}[0-9]{1,5}[{$sep}]{1}[0-9]{1,9}[{$sep}]{1}[0-9]{1,9}[{$sep}]{1}[0-9]{1}$/"; + // @codingStandardsIgnoreEnd + $length = 17; + } + + $patterns[$pattern] = self::ISBN13; + $lengths[$pattern] = $length; + } + + // check pattern list + foreach ($patterns as $pattern => $type) { + if ((strlen($this->getValue()) == $lengths[$pattern]) && preg_match($pattern, $this->getValue())) { + return $type; + } + } + + return; + } + + /** + * Returns true if and only if $value is a valid ISBN. + * + * @param string $value + * @return bool + */ + public function isValid($value) + { + if (! is_string($value) && ! is_int($value)) { + $this->error(self::INVALID); + return false; + } + + $value = (string) $value; + $this->setValue($value); + + switch ($this->detectFormat()) { + case self::ISBN10: + $isbn = new Isbn\Isbn10(); + break; + + case self::ISBN13: + $isbn = new Isbn\Isbn13(); + break; + + default: + $this->error(self::NO_ISBN); + return false; + } + + $value = str_replace($this->getSeparator(), '', $value); + $checksum = $isbn->getChecksum($value); + + // validate + if (substr($this->getValue(), -1) != $checksum) { + $this->error(self::NO_ISBN); + return false; + } + return true; + } + + /** + * Set separator characters. + * + * It is allowed only empty string, hyphen and space. + * + * @param string $separator + * @throws Exception\InvalidArgumentException When $separator is not valid + * @return $this Provides a fluent interface + */ + public function setSeparator($separator) + { + // check separator + if (! in_array($separator, ['-', ' ', ''])) { + throw new Exception\InvalidArgumentException('Invalid ISBN separator.'); + } + + $this->options['separator'] = $separator; + return $this; + } + + /** + * Get separator characters. + * + * @return string + */ + public function getSeparator() + { + return $this->options['separator']; + } + + /** + * Set allowed ISBN type. + * + * @param string $type + * @throws Exception\InvalidArgumentException When $type is not valid + * @return $this Provides a fluent interface + */ + public function setType($type) + { + // check type + if (! in_array($type, [self::AUTO, self::ISBN10, self::ISBN13])) { + throw new Exception\InvalidArgumentException('Invalid ISBN type'); + } + + $this->options['type'] = $type; + return $this; + } + + /** + * Get allowed ISBN type. + * + * @return string + */ + public function getType() + { + return $this->options['type']; + } +} diff --git a/lib/laminas/laminas-validator/src/Isbn/Isbn10.php b/lib/laminas/laminas-validator/src/Isbn/Isbn10.php new file mode 100755 index 000000000..734ac1fc2 --- /dev/null +++ b/lib/laminas/laminas-validator/src/Isbn/Isbn10.php @@ -0,0 +1,60 @@ +sum($value); + return $this->checksum($sum); + } + + /** + * Calculate the value sum. + * + * @param int|string $value + * @return int + */ + private function sum($value) + { + $sum = 0; + + for ($i = 0; $i < 9; $i++) { + $sum += (10 - $i) * $value[$i]; + } + + return $sum; + } + + /** + * Calculate the checksum for the value's sum. + * + * @param int $sum + * @return int|string + */ + private function checksum($sum) + { + $checksum = 11 - ($sum % 11); + + if ($checksum == 11) { + return '0'; + } + + if ($checksum == 10) { + return 'X'; + } + + return $checksum; + } +} diff --git a/lib/laminas/laminas-validator/src/Isbn/Isbn13.php b/lib/laminas/laminas-validator/src/Isbn/Isbn13.php new file mode 100755 index 000000000..75b4d6978 --- /dev/null +++ b/lib/laminas/laminas-validator/src/Isbn/Isbn13.php @@ -0,0 +1,61 @@ +sum($value); + return $this->checksum($sum); + } + + /** + * Calculate the value sum. + * + * @param int|string $value + * @return int + */ + private function sum($value) + { + $sum = 0; + + for ($i = 0; $i < 12; $i++) { + if ($i % 2 == 0) { + $sum += $value[$i]; + continue; + } + + $sum += 3 * $value[$i]; + } + + return $sum; + } + + /** + * Calculate the checksum for the value's sum. + * + * @param int $sum + * @return int|string + */ + private function checksum($sum) + { + $checksum = 10 - ($sum % 10); + + if ($checksum == 10) { + return '0'; + } + + return $checksum; + } +} diff --git a/lib/laminas/laminas-validator/src/LessThan.php b/lib/laminas/laminas-validator/src/LessThan.php new file mode 100644 index 000000000..6a0fa2d0b --- /dev/null +++ b/lib/laminas/laminas-validator/src/LessThan.php @@ -0,0 +1,160 @@ + "The input is not less than '%max%'", + self::NOT_LESS_INCLUSIVE => "The input is not less or equal than '%max%'", + ]; + + /** + * Additional variables available for validation failure messages + * + * @var array + */ + protected $messageVariables = [ + 'max' => 'max', + ]; + + /** + * Maximum value + * + * @var mixed + */ + protected $max; + + /** + * Whether to do inclusive comparisons, allowing equivalence to max + * + * If false, then strict comparisons are done, and the value may equal + * the max option + * + * @var bool + */ + protected $inclusive; + + /** + * Sets validator options + * + * @param array|Traversable $options + * @throws Exception\InvalidArgumentException + */ + public function __construct($options = null) + { + if ($options instanceof Traversable) { + $options = ArrayUtils::iteratorToArray($options); + } + if (! is_array($options)) { + $options = func_get_args(); + $temp['max'] = array_shift($options); + + if (! empty($options)) { + $temp['inclusive'] = array_shift($options); + } + + $options = $temp; + } + + if (! array_key_exists('max', $options)) { + throw new Exception\InvalidArgumentException("Missing option 'max'"); + } + + if (! array_key_exists('inclusive', $options)) { + $options['inclusive'] = false; + } + + $this->setMax($options['max']) + ->setInclusive($options['inclusive']); + + parent::__construct($options); + } + + /** + * Returns the max option + * + * @return mixed + */ + public function getMax() + { + return $this->max; + } + + /** + * Sets the max option + * + * @param mixed $max + * @return $this Provides a fluent interface + */ + public function setMax($max) + { + $this->max = $max; + return $this; + } + + /** + * Returns the inclusive option + * + * @return bool + */ + public function getInclusive() + { + return $this->inclusive; + } + + /** + * Sets the inclusive option + * + * @param bool $inclusive + * @return $this Provides a fluent interface + */ + public function setInclusive($inclusive) + { + $this->inclusive = $inclusive; + return $this; + } + + /** + * Returns true if and only if $value is less than max option, inclusively + * when the inclusive option is true + * + * @param mixed $value + * @return bool + */ + public function isValid($value) + { + $this->setValue($value); + + if ($this->inclusive) { + if ($value > $this->max) { + $this->error(self::NOT_LESS_INCLUSIVE); + return false; + } + } else { + if ($value >= $this->max) { + $this->error(self::NOT_LESS); + return false; + } + } + + return true; + } +} diff --git a/lib/laminas/laminas-validator/src/Module.php b/lib/laminas/laminas-validator/src/Module.php new file mode 100644 index 000000000..fb9415166 --- /dev/null +++ b/lib/laminas/laminas-validator/src/Module.php @@ -0,0 +1,44 @@ + $provider->getDependencyConfig(), + ]; + } + + /** + * Register a specification for the ValidatorManager with the ServiceListener. + * + * @param \Laminas\ModuleManager\ModuleManager $moduleManager + * @return void + */ + public function init($moduleManager) + { + $event = $moduleManager->getEvent(); + $container = $event->getParam('ServiceManager'); + $serviceListener = $container->get('ServiceListener'); + + $serviceListener->addServiceManager( + 'ValidatorManager', + 'validators', + ValidatorProviderInterface::class, + 'getValidatorConfig' + ); + } +} diff --git a/lib/laminas/laminas-validator/src/NotEmpty.php b/lib/laminas/laminas-validator/src/NotEmpty.php new file mode 100644 index 000000000..7fc433d2e --- /dev/null +++ b/lib/laminas/laminas-validator/src/NotEmpty.php @@ -0,0 +1,289 @@ + 'boolean', + self::INTEGER => 'integer', + self::FLOAT => 'float', + self::STRING => 'string', + self::ZERO => 'zero', + self::EMPTY_ARRAY => 'array', + self::NULL => 'null', + self::PHP => 'php', + self::SPACE => 'space', + self::OBJECT => 'object', + self::OBJECT_STRING => 'objectstring', + self::OBJECT_COUNT => 'objectcount', + self::ALL => 'all', + ]; + + /** + * Default value for types; value = 0b000111101001 + * + * @var array + */ + protected $defaultType = [ + self::OBJECT, + self::SPACE, + self::NULL, + self::EMPTY_ARRAY, + self::STRING, + self::BOOLEAN, + ]; + + /** + * @var array + */ + protected $messageTemplates = [ + self::IS_EMPTY => "Value is required and can't be empty", + self::INVALID => 'Invalid type given. String, integer, float, boolean or array expected', + ]; + + /** + * Options for this validator + * + * @var array + */ + protected $options = []; + + /** + * Constructor + * + * @param array|Traversable|int $options OPTIONAL + */ + public function __construct($options = null) + { + if ($options instanceof Traversable) { + $options = ArrayUtils::iteratorToArray($options); + } + + if (! is_array($options)) { + $options = func_get_args(); + $temp = []; + if (! empty($options)) { + $temp['type'] = array_shift($options); + } + + $options = $temp; + } + + if (! isset($options['type'])) { + if (($type = $this->calculateTypeValue($options)) != 0) { + $options['type'] = $type; + } else { + $options['type'] = $this->defaultType; + } + } + + parent::__construct($options); + } + + /** + * Returns the set types + * + * @return array + */ + public function getType() + { + return $this->options['type']; + } + + /** + * @return int + */ + public function getDefaultType() + { + return $this->calculateTypeValue($this->defaultType); + } + + /** + * @param array|int|string $type + * @return int + */ + protected function calculateTypeValue($type) + { + if (is_array($type)) { + $detected = 0; + foreach ($type as $value) { + if (is_int($value)) { + $detected |= $value; + } elseif (in_array($value, $this->constants, true)) { + $detected |= array_search($value, $this->constants, true); + } + } + + $type = $detected; + } elseif (is_string($type) && in_array($type, $this->constants, true)) { + $type = array_search($type, $this->constants, true); + } + + return $type; + } + + /** + * Set the types + * + * @param int|array $type + * @throws Exception\InvalidArgumentException + * @return $this + */ + public function setType($type = null) + { + $type = $this->calculateTypeValue($type); + + if (! is_int($type) || ($type < 0) || ($type > self::ALL)) { + throw new Exception\InvalidArgumentException('Unknown type'); + } + + $this->options['type'] = $type; + + return $this; + } + + /** + * Returns true if and only if $value is not an empty value. + * + * @param string $value + * @return bool + */ + public function isValid($value) + { + if ($value !== null && ! is_string($value) && ! is_int($value) && ! is_float($value) && + ! is_bool($value) && ! is_array($value) && ! is_object($value) + ) { + $this->error(self::INVALID); + return false; + } + + $type = $this->getType(); + $this->setValue($value); + $object = false; + + // OBJECT_COUNT (countable object) + if ($type & self::OBJECT_COUNT) { + $object = true; + + if (is_object($value) && $value instanceof \Countable && (count($value) == 0)) { + $this->error(self::IS_EMPTY); + return false; + } + } + + // OBJECT_STRING (object's toString) + if ($type & self::OBJECT_STRING) { + $object = true; + + if ((is_object($value) && (! method_exists($value, '__toString'))) || + (is_object($value) && (method_exists($value, '__toString')) && (((string) $value) == ''))) { + $this->error(self::IS_EMPTY); + return false; + } + } + + // OBJECT (object) + if ($type & self::OBJECT) { + // fall trough, objects are always not empty + } elseif ($object === false) { + // object not allowed but object given -> return false + if (is_object($value)) { + $this->error(self::IS_EMPTY); + return false; + } + } + + // SPACE (' ') + if ($type & self::SPACE) { + if (is_string($value) && (preg_match('/^\s+$/s', $value))) { + $this->error(self::IS_EMPTY); + return false; + } + } + + // NULL (null) + if ($type & self::NULL) { + if ($value === null) { + $this->error(self::IS_EMPTY); + return false; + } + } + + // EMPTY_ARRAY (array()) + if ($type & self::EMPTY_ARRAY) { + if (is_array($value) && ($value == [])) { + $this->error(self::IS_EMPTY); + return false; + } + } + + // ZERO ('0') + if ($type & self::ZERO) { + if (is_string($value) && ($value == '0')) { + $this->error(self::IS_EMPTY); + return false; + } + } + + // STRING ('') + if ($type & self::STRING) { + if (is_string($value) && ($value == '')) { + $this->error(self::IS_EMPTY); + return false; + } + } + + // FLOAT (0.0) + if ($type & self::FLOAT) { + if (is_float($value) && ($value == 0.0)) { + $this->error(self::IS_EMPTY); + return false; + } + } + + // INTEGER (0) + if ($type & self::INTEGER) { + if (is_int($value) && ($value == 0)) { + $this->error(self::IS_EMPTY); + return false; + } + } + + // BOOLEAN (false) + if ($type & self::BOOLEAN) { + if (is_bool($value) && ($value == false)) { + $this->error(self::IS_EMPTY); + return false; + } + } + + return true; + } +} diff --git a/lib/laminas/laminas-validator/src/Regex.php b/lib/laminas/laminas-validator/src/Regex.php new file mode 100644 index 000000000..bf1523b17 --- /dev/null +++ b/lib/laminas/laminas-validator/src/Regex.php @@ -0,0 +1,140 @@ + 'Invalid type given. String, integer or float expected', + self::NOT_MATCH => "The input does not match against pattern '%pattern%'", + self::ERROROUS => "There was an internal error while using the pattern '%pattern%'", + ]; + + /** + * @var array + */ + protected $messageVariables = [ + 'pattern' => 'pattern', + ]; + + /** + * Regular expression pattern + * + * @var string + */ + protected $pattern; + + /** + * Sets validator options + * + * @param string|array|Traversable $pattern + * @throws Exception\InvalidArgumentException On missing 'pattern' parameter + */ + public function __construct($pattern) + { + if (is_string($pattern)) { + $this->setPattern($pattern); + parent::__construct([]); + return; + } + + if ($pattern instanceof Traversable) { + $pattern = ArrayUtils::iteratorToArray($pattern); + } + + if (! is_array($pattern)) { + throw new Exception\InvalidArgumentException('Invalid options provided to constructor'); + } + + if (! array_key_exists('pattern', $pattern)) { + throw new Exception\InvalidArgumentException("Missing option 'pattern'"); + } + + $this->setPattern($pattern['pattern']); + unset($pattern['pattern']); + parent::__construct($pattern); + } + + /** + * Returns the pattern option + * + * @return string + */ + public function getPattern() + { + return $this->pattern; + } + + /** + * Sets the pattern option + * + * @param string $pattern + * @throws Exception\InvalidArgumentException if there is a fatal error in pattern matching + * @return $this Provides a fluent interface + */ + public function setPattern($pattern) + { + ErrorHandler::start(); + $this->pattern = (string) $pattern; + $status = preg_match($this->pattern, 'Test'); + $error = ErrorHandler::stop(); + + if (false === $status) { + throw new Exception\InvalidArgumentException( + "Internal error parsing the pattern '{$this->pattern}'", + 0, + $error + ); + } + + return $this; + } + + /** + * Returns true if and only if $value matches against the pattern option + * + * @param string $value + * @return bool + */ + public function isValid($value) + { + if (! is_string($value) && ! is_int($value) && ! is_float($value)) { + $this->error(self::INVALID); + return false; + } + + $this->setValue($value); + + ErrorHandler::start(); + $status = preg_match($this->pattern, $value); + ErrorHandler::stop(); + if (false === $status) { + $this->error(self::ERROROUS); + return false; + } + + if (! $status) { + $this->error(self::NOT_MATCH); + return false; + } + + return true; + } +} diff --git a/lib/laminas/laminas-validator/src/Sitemap/Changefreq.php b/lib/laminas/laminas-validator/src/Sitemap/Changefreq.php new file mode 100644 index 000000000..19bcc11a6 --- /dev/null +++ b/lib/laminas/laminas-validator/src/Sitemap/Changefreq.php @@ -0,0 +1,74 @@ + value + * + * @link http://www.sitemaps.org/protocol.php Sitemaps XML format + */ +class Changefreq extends AbstractValidator +{ + /** + * Validation key for not valid + * + */ + const NOT_VALID = 'sitemapChangefreqNotValid'; + const INVALID = 'sitemapChangefreqInvalid'; + + /** + * Validation failure message template definitions + * + * @var array + */ + protected $messageTemplates = [ + self::NOT_VALID => 'The input is not a valid sitemap changefreq', + self::INVALID => 'Invalid type given. String expected', + ]; + + /** + * Valid change frequencies + * + * @var array + */ + protected $changeFreqs = [ + 'always', 'hourly', 'daily', 'weekly', + 'monthly', 'yearly', 'never', + ]; + + /** + * Validates if a string is valid as a sitemap changefreq + * + * @link http://www.sitemaps.org/protocol.php#changefreqdef + * + * @param string $value value to validate + * @return bool + */ + public function isValid($value) + { + if (! is_string($value)) { + $this->error(self::INVALID); + return false; + } + + $this->setValue($value); + if (! is_string($value)) { + return false; + } + + if (! in_array($value, $this->changeFreqs, true)) { + $this->error(self::NOT_VALID); + return false; + } + + return true; + } +} diff --git a/lib/laminas/laminas-validator/src/Sitemap/Lastmod.php b/lib/laminas/laminas-validator/src/Sitemap/Lastmod.php new file mode 100644 index 000000000..39b0aaaba --- /dev/null +++ b/lib/laminas/laminas-validator/src/Sitemap/Lastmod.php @@ -0,0 +1,72 @@ + value + * + * @link http://www.sitemaps.org/protocol.php Sitemaps XML format + */ +class Lastmod extends AbstractValidator +{ + /** + * Regular expression to use when validating + * + */ + // @codingStandardsIgnoreStart + const LASTMOD_REGEX = '/^[0-9]{4}-(0[1-9]|1[0-2])-(0[1-9]|[1-2][0-9]|3[0-1])(T([0-1][0-9]|2[0-3])(:[0-5][0-9])(:[0-5][0-9])?(\\+|-)([0-1][0-9]|2[0-3]):[0-5][0-9])?$/'; + // @codingStandardsIgnoreEnd + + /** + * Validation key for not valid + * + */ + const NOT_VALID = 'sitemapLastmodNotValid'; + const INVALID = 'sitemapLastmodInvalid'; + + /** + * Validation failure message template definitions + * + * @var array + */ + protected $messageTemplates = [ + self::NOT_VALID => 'The input is not a valid sitemap lastmod', + self::INVALID => 'Invalid type given. String expected', + ]; + + /** + * Validates if a string is valid as a sitemap lastmod + * + * @link http://www.sitemaps.org/protocol.php#lastmoddef + * + * @param string $value value to validate + * @return bool + */ + public function isValid($value) + { + if (! is_string($value)) { + $this->error(self::INVALID); + return false; + } + + $this->setValue($value); + ErrorHandler::start(); + $result = preg_match(self::LASTMOD_REGEX, $value); + ErrorHandler::stop(); + if ($result != 1) { + $this->error(self::NOT_VALID); + return false; + } + + return true; + } +} diff --git a/lib/laminas/laminas-validator/src/Sitemap/Loc.php b/lib/laminas/laminas-validator/src/Sitemap/Loc.php new file mode 100644 index 000000000..3ef724324 --- /dev/null +++ b/lib/laminas/laminas-validator/src/Sitemap/Loc.php @@ -0,0 +1,64 @@ + value + * + * @link http://www.sitemaps.org/protocol.php Sitemaps XML format + * + * @see Laminas\Uri\Uri + */ +class Loc extends AbstractValidator +{ + /** + * Validation key for not valid + * + */ + const NOT_VALID = 'sitemapLocNotValid'; + const INVALID = 'sitemapLocInvalid'; + + /** + * Validation failure message template definitions + * + * @var array + */ + protected $messageTemplates = [ + self::NOT_VALID => 'The input is not a valid sitemap location', + self::INVALID => 'Invalid type given. String expected', + ]; + + /** + * Validates if a string is valid as a sitemap location + * + * @link http://www.sitemaps.org/protocol.php#locdef + * + * @param string $value value to validate + * @return bool + */ + public function isValid($value) + { + if (! is_string($value)) { + $this->error(self::INVALID); + return false; + } + + $this->setValue($value); + $uri = Uri\UriFactory::factory($value); + if (! $uri->isValid()) { + $this->error(self::NOT_VALID); + return false; + } + + return true; + } +} diff --git a/lib/laminas/laminas-validator/src/Sitemap/Priority.php b/lib/laminas/laminas-validator/src/Sitemap/Priority.php new file mode 100644 index 000000000..b4c3f1d54 --- /dev/null +++ b/lib/laminas/laminas-validator/src/Sitemap/Priority.php @@ -0,0 +1,61 @@ + value + * + * @link http://www.sitemaps.org/protocol.php Sitemaps XML format + */ +class Priority extends AbstractValidator +{ + /** + * Validation key for not valid + * + */ + const NOT_VALID = 'sitemapPriorityNotValid'; + const INVALID = 'sitemapPriorityInvalid'; + + /** + * Validation failure message template definitions + * + * @var array + */ + protected $messageTemplates = [ + self::NOT_VALID => 'The input is not a valid sitemap priority', + self::INVALID => 'Invalid type given. Numeric string, integer or float expected', + ]; + + /** + * Validates if a string is valid as a sitemap priority + * + * @link http://www.sitemaps.org/protocol.php#prioritydef + * + * @param string $value value to validate + * @return bool + */ + public function isValid($value) + { + if (! is_numeric($value)) { + $this->error(self::INVALID); + return false; + } + + $this->setValue($value); + $value = (float) $value; + if ($value < 0 || $value > 1) { + $this->error(self::NOT_VALID); + return false; + } + + return true; + } +} diff --git a/lib/laminas/laminas-validator/src/StaticValidator.php b/lib/laminas/laminas-validator/src/StaticValidator.php new file mode 100644 index 000000000..bbb58d232 --- /dev/null +++ b/lib/laminas/laminas-validator/src/StaticValidator.php @@ -0,0 +1,74 @@ +configure(['shared_by_default' => false]); + } else { + $plugins->setShareByDefault(false); + } + } + static::$plugins = $plugins; + } + + /** + * Get plugin manager for locating validators + * + * @return ValidatorPluginManager + */ + public static function getPluginManager() + { + if (null === static::$plugins) { + static::setPluginManager(new ValidatorPluginManager(new ServiceManager)); + } + return static::$plugins; + } + + /** + * @param mixed $value + * @param string $classBaseName + * @param array $options OPTIONAL associative array of options to pass as + * the sole argument to the validator constructor. + * @return bool + * @throws Exception\InvalidArgumentException for an invalid $options argument. + */ + public static function execute($value, $classBaseName, array $options = []) + { + if ($options && array_values($options) === $options) { + throw new Exception\InvalidArgumentException( + 'Invalid options provided via $options argument; must be an associative array' + ); + } + + $plugins = static::getPluginManager(); + + $validator = $plugins->get($classBaseName, $options); + return $validator->isValid($value); + } +} diff --git a/lib/laminas/laminas-validator/src/Step.php b/lib/laminas/laminas-validator/src/Step.php new file mode 100644 index 000000000..fd1559cc0 --- /dev/null +++ b/lib/laminas/laminas-validator/src/Step.php @@ -0,0 +1,177 @@ + 'Invalid value given. Scalar expected', + self::NOT_STEP => 'The input is not a valid step', + ]; + + /** + * @var mixed + */ + protected $baseValue = 0; + + /** + * @var mixed + */ + protected $step = 1; + + /** + * Set default options for this instance + * + * @param array $options + */ + public function __construct($options = []) + { + if ($options instanceof Traversable) { + $options = iterator_to_array($options); + } elseif (! is_array($options)) { + $options = func_get_args(); + $temp['baseValue'] = array_shift($options); + if (! empty($options)) { + $temp['step'] = array_shift($options); + } + + $options = $temp; + } + + if (isset($options['baseValue'])) { + $this->setBaseValue($options['baseValue']); + } + if (isset($options['step'])) { + $this->setStep($options['step']); + } + + parent::__construct($options); + } + + /** + * Sets the base value from which the step should be computed + * + * @param mixed $baseValue + * @return $this + */ + public function setBaseValue($baseValue) + { + $this->baseValue = $baseValue; + return $this; + } + + /** + * Returns the base value from which the step should be computed + * + * @return string + */ + public function getBaseValue() + { + return $this->baseValue; + } + + /** + * Sets the step value + * + * @param mixed $step + * @return $this + */ + public function setStep($step) + { + $this->step = (float) $step; + return $this; + } + + /** + * Returns the step value + * + * @return string + */ + public function getStep() + { + return $this->step; + } + + /** + * Returns true if $value is a scalar and a valid step value + * + * @param mixed $value + * @return bool + */ + public function isValid($value) + { + if (! is_numeric($value)) { + $this->error(self::INVALID); + return false; + } + + $this->setValue($value); + + $substract = $this->sub($value, $this->baseValue); + + $fmod = $this->fmod($substract, $this->step); + + if ($fmod !== 0.0 && $fmod !== $this->step) { + $this->error(self::NOT_STEP); + return false; + } + + return true; + } + + /** + * replaces the internal fmod function which give wrong results on many cases + * + * @param float $x + * @param float $y + * @return float + */ + protected function fmod($x, $y) + { + if ($y == 0.0) { + return 1.0; + } + + //find the maximum precision from both input params to give accurate results + $precision = $this->getPrecision($x) + $this->getPrecision($y); + + return round($x - $y * floor($x / $y), $precision); + } + + /** + * replaces the internal substraction operation which give wrong results on some cases + * + * @param float $x + * @param float $y + * @return float + */ + private function sub($x, $y) + { + $precision = $this->getPrecision($x) + $this->getPrecision($y); + return round($x - $y, $precision); + } + + /** + * @param float $float + * @return int + */ + private function getPrecision($float) + { + $segment = substr($float, strpos($float, '.') + 1); + return $segment ? strlen($segment) : 0; + } +} diff --git a/lib/laminas/laminas-validator/src/StringLength.php b/lib/laminas/laminas-validator/src/StringLength.php new file mode 100644 index 000000000..f9d4bcd68 --- /dev/null +++ b/lib/laminas/laminas-validator/src/StringLength.php @@ -0,0 +1,234 @@ + 'Invalid type given. String expected', + self::TOO_SHORT => 'The input is less than %min% characters long', + self::TOO_LONG => 'The input is more than %max% characters long', + ]; + + /** + * @var array + */ + protected $messageVariables = [ + 'min' => ['options' => 'min'], + 'max' => ['options' => 'max'], + 'length' => ['options' => 'length'], + ]; + + protected $options = [ + 'min' => 0, // Minimum length + 'max' => null, // Maximum length, null if there is no length limitation + 'encoding' => 'UTF-8', // Encoding to use + 'length' => 0, // Actual length + ]; + + protected $stringWrapper; + + /** + * Sets validator options + * + * @param int|array|\Traversable $options + */ + public function __construct($options = []) + { + if (! is_array($options)) { + $options = func_get_args(); + $temp['min'] = array_shift($options); + if (! empty($options)) { + $temp['max'] = array_shift($options); + } + + if (! empty($options)) { + $temp['encoding'] = array_shift($options); + } + + $options = $temp; + } + + parent::__construct($options); + } + + /** + * Returns the min option + * + * @return int + */ + public function getMin() + { + return $this->options['min']; + } + + /** + * Sets the min option + * + * @param int $min + * @throws Exception\InvalidArgumentException + * @return $this Provides a fluent interface + */ + public function setMin($min) + { + if (null !== $this->getMax() && $min > $this->getMax()) { + throw new Exception\InvalidArgumentException( + "The minimum must be less than or equal to the maximum length, but {$min} > {$this->getMax()}" + ); + } + + $this->options['min'] = max(0, (int) $min); + return $this; + } + + /** + * Returns the max option + * + * @return int|null + */ + public function getMax() + { + return $this->options['max']; + } + + /** + * Sets the max option + * + * @param int|null $max + * @throws Exception\InvalidArgumentException + * @return $this Provides a fluent interface + */ + public function setMax($max) + { + if (null === $max) { + $this->options['max'] = null; + } elseif ($max < $this->getMin()) { + throw new Exception\InvalidArgumentException( + "The maximum must be greater than or equal to the minimum length, but {$max} < {$this->getMin()}" + ); + } else { + $this->options['max'] = (int) $max; + } + + return $this; + } + + /** + * Get the string wrapper to detect the string length + * + * @return StringWrapper + */ + public function getStringWrapper() + { + if (! $this->stringWrapper) { + $this->stringWrapper = StringUtils::getWrapper($this->getEncoding()); + } + return $this->stringWrapper; + } + + /** + * Set the string wrapper to detect the string length + * + * @param StringWrapper $stringWrapper + * @return StringLength + */ + public function setStringWrapper(StringWrapper $stringWrapper) + { + $stringWrapper->setEncoding($this->getEncoding()); + $this->stringWrapper = $stringWrapper; + } + + /** + * Returns the actual encoding + * + * @return string + */ + public function getEncoding() + { + return $this->options['encoding']; + } + + /** + * Sets a new encoding to use + * + * @param string $encoding + * @return $this + * @throws Exception\InvalidArgumentException + */ + public function setEncoding($encoding) + { + $this->stringWrapper = StringUtils::getWrapper($encoding); + $this->options['encoding'] = $encoding; + return $this; + } + + /** + * Returns the length option + * + * @return int + */ + private function getLength() + { + return $this->options['length']; + } + + /** + * Sets the length option + * + * @param int $length + * @return $this Provides a fluent interface + */ + private function setLength($length) + { + $this->options['length'] = (int) $length; + return $this; + } + + /** + * Returns true if and only if the string length of $value is at least the min option and + * no greater than the max option (when the max option is not null). + * + * @param string $value + * @return bool + */ + public function isValid($value) + { + if (! is_string($value)) { + $this->error(self::INVALID); + return false; + } + + $this->setValue($value); + + $this->setLength($this->getStringWrapper()->strlen($value)); + if ($this->getLength() < $this->getMin()) { + $this->error(self::TOO_SHORT); + } + + if (null !== $this->getMax() && $this->getMax() < $this->getLength()) { + $this->error(self::TOO_LONG); + } + + if ($this->getMessages()) { + return false; + } + + return true; + } +} diff --git a/lib/laminas/laminas-validator/src/Timezone.php b/lib/laminas/laminas-validator/src/Timezone.php new file mode 100644 index 000000000..72068e0d2 --- /dev/null +++ b/lib/laminas/laminas-validator/src/Timezone.php @@ -0,0 +1,173 @@ + 'location', + self::ABBREVIATION => 'abbreviation', + ]; + + /** + * Default value for types; value = 3 + * + * @var array + */ + protected $defaultType = [ + self::LOCATION, + self::ABBREVIATION, + ]; + + /** + * @var array + */ + protected $messageTemplates = [ + self::INVALID => 'Invalid timezone given.', + self::INVALID_TIMEZONE_LOCATION => 'Invalid timezone location given.', + self::INVALID_TIMEZONE_ABBREVIATION => 'Invalid timezone abbreviation given.', + ]; + + /** + * Options for this validator + * + * @var array + */ + protected $options = []; + + /** + * Constructor + * + * @param array|int $options OPTIONAL + */ + public function __construct($options = []) + { + $opts['type'] = $this->defaultType; + + if (is_array($options)) { + if (array_key_exists('type', $options)) { + $opts['type'] = $options['type']; + } + } elseif (! empty($options)) { + $opts['type'] = $options; + } + + // setType called by parent constructor then setOptions method + parent::__construct($opts); + } + + /** + * Set the types + * + * @param int|array $type + * + * @throws Exception\InvalidArgumentException + */ + public function setType($type = null) + { + $type = $this->calculateTypeValue($type); + + if (! is_int($type) || ($type < 1) || ($type > self::ALL)) { + throw new Exception\InvalidArgumentException(sprintf( + 'Unknown type "%s" provided', + is_string($type) || is_int($type) + ? $type + : (is_object($type) ? get_class($type) : gettype($type)) + )); + } + + $this->options['type'] = $type; + } + + /** + * Returns true if timezone location or timezone abbreviations is correct. + * + * @param mixed $value + * @return bool + */ + public function isValid($value) + { + if ($value !== null && ! is_string($value)) { + $this->error(self::INVALID); + return false; + } + + $type = $this->options['type']; + $this->setValue($value); + + switch (true) { + // Check in locations and abbreviations + case (($type & self::LOCATION) && ($type & self::ABBREVIATION)): + $abbrs = DateTimeZone::listAbbreviations(); + $locations = DateTimeZone::listIdentifiers(); + + if (! array_key_exists($value, $abbrs) && ! in_array($value, $locations)) { + $this->error(self::INVALID); + return false; + } + break; + + // Check only in locations + case ($type & self::LOCATION): + $locations = DateTimeZone::listIdentifiers(); + + if (! in_array($value, $locations)) { + $this->error(self::INVALID_TIMEZONE_LOCATION); + return false; + } + break; + + // Check only in abbreviations + case ($type & self::ABBREVIATION): + $abbrs = DateTimeZone::listAbbreviations(); + + if (! array_key_exists($value, $abbrs)) { + $this->error(self::INVALID_TIMEZONE_ABBREVIATION); + return false; + } + break; + } + + return true; + } + + /** + * @param array|int|string $type + * + * @return int + */ + protected function calculateTypeValue($type) + { + $types = (array) $type; + $detected = 0; + + foreach ($types as $value) { + if (is_int($value)) { + $detected |= $value; + } elseif (false !== ($position = array_search($value, $this->constants))) { + $detected |= array_search($value, $this->constants); + } + } + + return $detected; + } +} diff --git a/lib/laminas/laminas-validator/src/Translator/TranslatorAwareInterface.php b/lib/laminas/laminas-validator/src/Translator/TranslatorAwareInterface.php new file mode 100644 index 000000000..84734d835 --- /dev/null +++ b/lib/laminas/laminas-validator/src/Translator/TranslatorAwareInterface.php @@ -0,0 +1,68 @@ + + 'The provided password was found in previous breaches, please create another password', + self::NOT_A_STRING => 'The provided password is not a string, please provide a correct password', + ]; + + /** @var ClientInterface */ + private $httpClient; + + /** @var RequestFactoryInterface */ + private $makeHttpRequest; + + public function __construct(ClientInterface $httpClient, RequestFactoryInterface $makeHttpRequest) + { + parent::__construct(); + + $this->httpClient = $httpClient; + $this->makeHttpRequest = $makeHttpRequest; + } + + /** + * @inheritDoc + */ + public function isValid($value) : bool + { + if (! is_string($value)) { + $this->error(self::NOT_A_STRING); + return false; + } + + if ($this->isPwnedPassword($value)) { + $this->error(self::PASSWORD_BREACHED); + return false; + } + + return true; + } + + private function isPwnedPassword(string $password) : bool + { + $sha1Hash = $this->hashPassword($password); + $rangeHash = $this->getRangeHash($sha1Hash); + $hashList = $this->retrieveHashList($rangeHash); + + return $this->hashInResponse($sha1Hash, $hashList); + } + + /** + * We use a SHA1 hashed password for checking it against + * the breached data set of HIBP. + */ + private function hashPassword(string $password) : string + { + $hashedPassword = sha1($password); + + return strtoupper($hashedPassword); + } + + /** + * Creates a hash range that will be send to HIBP API + * applying K-Anonymity + * + * @see https://www.troyhunt.com/enhancing-pwned-passwords-privacy-by-exclusively-supporting-anonymity/ + */ + private function getRangeHash(string $passwordHash) : string + { + return substr($passwordHash, self::HIBP_K_ANONYMITY_HASH_RANGE_BASE, self::HIBP_K_ANONYMITY_HASH_RANGE_LENGTH); + } + + /** + * Making a connection to the HIBP API to retrieve a + * list of hashes that all have the same range as we + * provided. + * + * @throws ClientExceptionInterface + */ + private function retrieveHashList(string $passwordRange) : string + { + $request = $this->makeHttpRequest->createRequest( + 'GET', + self::HIBP_API_URI . '/range/' . $passwordRange + ); + + $response = $this->httpClient->sendRequest($request); + return (string) $response->getBody(); + } + + /** + * Checks if the password is in the response from HIBP + */ + private function hashInResponse(string $sha1Hash, string $resultStream) : bool + { + $data = explode("\r\n", $resultStream); + $hashes = array_filter($data, static function ($value) use ($sha1Hash) { + [$hash, $count] = explode(':', $value); + + return strcmp($hash, substr($sha1Hash, self::HIBP_K_ANONYMITY_HASH_RANGE_LENGTH)) === 0; + }); + + return $hashes !== []; + } +} diff --git a/lib/laminas/laminas-validator/src/Uri.php b/lib/laminas/laminas-validator/src/Uri.php new file mode 100644 index 000000000..a667f853b --- /dev/null +++ b/lib/laminas/laminas-validator/src/Uri.php @@ -0,0 +1,189 @@ + 'Invalid type given. String expected', + self::NOT_URI => 'The input does not appear to be a valid Uri', + ]; + + /** + * @var UriHandler + */ + protected $uriHandler; + + /** + * @var bool + */ + protected $allowRelative = true; + + /** + * @var bool + */ + protected $allowAbsolute = true; + + /** + * Sets default option values for this instance + * + * @param array|Traversable $options + */ + public function __construct($options = []) + { + if ($options instanceof Traversable) { + $options = iterator_to_array($options); + } elseif (! is_array($options)) { + $options = func_get_args(); + $temp['uriHandler'] = array_shift($options); + if (! empty($options)) { + $temp['allowRelative'] = array_shift($options); + } + if (! empty($options)) { + $temp['allowAbsolute'] = array_shift($options); + } + + $options = $temp; + } + + if (isset($options['uriHandler'])) { + $this->setUriHandler($options['uriHandler']); + } + if (isset($options['allowRelative'])) { + $this->setAllowRelative($options['allowRelative']); + } + if (isset($options['allowAbsolute'])) { + $this->setAllowAbsolute($options['allowAbsolute']); + } + + parent::__construct($options); + } + + /** + * @throws InvalidArgumentException + * @return UriHandler + */ + public function getUriHandler() + { + if (null === $this->uriHandler) { + // Lazy load the base Uri handler + $this->uriHandler = new UriHandler(); + } elseif (is_string($this->uriHandler) && class_exists($this->uriHandler)) { + // Instantiate string Uri handler that references a class + $this->uriHandler = new $this->uriHandler; + } + return $this->uriHandler; + } + + /** + * @param UriHandler|string $uriHandler + * @throws InvalidArgumentException + * @return $this + */ + public function setUriHandler($uriHandler) + { + if (! is_a($uriHandler, UriHandler::class, true)) { + throw new InvalidArgumentException(sprintf( + 'Expecting a subclass name or instance of %s as $uriHandler', + UriHandler::class + )); + } + + $this->uriHandler = $uriHandler; + return $this; + } + + /** + * Returns the allowAbsolute option + * + * @return bool + */ + public function getAllowAbsolute() + { + return $this->allowAbsolute; + } + + /** + * Sets the allowAbsolute option + * + * @param bool $allowAbsolute + * @return $this + */ + public function setAllowAbsolute($allowAbsolute) + { + $this->allowAbsolute = (bool) $allowAbsolute; + return $this; + } + + /** + * Returns the allowRelative option + * + * @return bool + */ + public function getAllowRelative() + { + return $this->allowRelative; + } + + /** + * Sets the allowRelative option + * + * @param bool $allowRelative + * @return $this + */ + public function setAllowRelative($allowRelative) + { + $this->allowRelative = (bool) $allowRelative; + return $this; + } + + /** + * Returns true if and only if $value validates as a Uri + * + * @param string $value + * @return bool + */ + public function isValid($value) + { + if (! is_string($value)) { + $this->error(self::INVALID); + return false; + } + + $uriHandler = $this->getUriHandler(); + try { + $uriHandler->parse($value); + if ($uriHandler->isValid()) { + // It will either be a valid absolute or relative URI + if (($this->allowRelative && $this->allowAbsolute) + || ($this->allowAbsolute && $uriHandler->isAbsolute()) + || ($this->allowRelative && $uriHandler->isValidRelative()) + ) { + return true; + } + } + } catch (UriException $ex) { + // Error parsing URI, it must be invalid + } + + $this->error(self::NOT_URI); + return false; + } +} diff --git a/lib/laminas/laminas-validator/src/Uuid.php b/lib/laminas/laminas-validator/src/Uuid.php new file mode 100644 index 000000000..e6f3a3d14 --- /dev/null +++ b/lib/laminas/laminas-validator/src/Uuid.php @@ -0,0 +1,64 @@ + 'Invalid type given; string expected', + self::INVALID => 'Invalid UUID format', + ]; + + /** + * Returns true if and only if $value meets the validation requirements. + * + * If $value fails validation, then this method returns false, and + * getMessages() will return an array of messages that explain why the + * validation failed. + * + * @param mixed $value + * + * @return bool + * + * @throws Exception\RuntimeException If validation of $value is impossible + */ + public function isValid($value) + { + if (! is_string($value)) { + $this->error(self::NOT_STRING); + return false; + } + + $this->setValue($value); + + if (empty($value) + || $value !== '00000000-0000-0000-0000-000000000000' + && ! preg_match(self::REGEX_UUID, $value) + ) { + $this->error(self::INVALID); + return false; + } + + return true; + } +} diff --git a/lib/laminas/laminas-validator/src/ValidatorChain.php b/lib/laminas/laminas-validator/src/ValidatorChain.php new file mode 100644 index 000000000..6bc9dca03 --- /dev/null +++ b/lib/laminas/laminas-validator/src/ValidatorChain.php @@ -0,0 +1,326 @@ +validators = new PriorityQueue(); + } + + /** + * Return the count of attached validators + * + * @return int + */ + public function count() + { + return count($this->validators); + } + + /** + * Get plugin manager instance + * + * @return ValidatorPluginManager + */ + public function getPluginManager() + { + if (! $this->plugins) { + $this->setPluginManager(new ValidatorPluginManager(new ServiceManager)); + } + return $this->plugins; + } + + /** + * Set plugin manager instance + * + * @param ValidatorPluginManager $plugins Plugin manager + * @return $this + */ + public function setPluginManager(ValidatorPluginManager $plugins) + { + $this->plugins = $plugins; + return $this; + } + + /** + * Retrieve a validator by name + * + * @param string $name Name of validator to return + * @param null|array $options Options to pass to validator constructor (if not already instantiated) + * @return ValidatorInterface + */ + public function plugin($name, array $options = null) + { + $plugins = $this->getPluginManager(); + return $plugins->get($name, $options); + } + + /** + * Attach a validator to the end of the chain + * + * If $breakChainOnFailure is true, then if the validator fails, the next validator in the chain, + * if one exists, will not be executed. + * + * @param ValidatorInterface $validator + * @param bool $breakChainOnFailure + * @param int $priority Priority at which to enqueue validator; defaults to + * 1 (higher executes earlier) + * + * @throws Exception\InvalidArgumentException + * + * @return $this + */ + public function attach( + ValidatorInterface $validator, + $breakChainOnFailure = false, + $priority = self::DEFAULT_PRIORITY + ) { + $this->validators->insert( + [ + 'instance' => $validator, + 'breakChainOnFailure' => (bool) $breakChainOnFailure, + ], + $priority + ); + + return $this; + } + + /** + * Proxy to attach() to keep BC + * + * @deprecated Please use attach() + * @param ValidatorInterface $validator + * @param bool $breakChainOnFailure + * @param int $priority + * @return ValidatorChain Provides a fluent interface + */ + public function addValidator( + ValidatorInterface $validator, + $breakChainOnFailure = false, + $priority = self::DEFAULT_PRIORITY + ) { + return $this->attach($validator, $breakChainOnFailure, $priority); + } + + /** + * Adds a validator to the beginning of the chain + * + * If $breakChainOnFailure is true, then if the validator fails, the next validator in the chain, + * if one exists, will not be executed. + * + * @param ValidatorInterface $validator + * @param bool $breakChainOnFailure + * @return $this Provides a fluent interface + */ + public function prependValidator(ValidatorInterface $validator, $breakChainOnFailure = false) + { + $priority = self::DEFAULT_PRIORITY; + + if (! $this->validators->isEmpty()) { + $extractedNodes = $this->validators->toArray(PriorityQueue::EXTR_PRIORITY); + rsort($extractedNodes, SORT_NUMERIC); + $priority = $extractedNodes[0] + 1; + } + + $this->validators->insert( + [ + 'instance' => $validator, + 'breakChainOnFailure' => (bool) $breakChainOnFailure, + ], + $priority + ); + return $this; + } + + /** + * Use the plugin manager to add a validator by name + * + * @param string $name + * @param array $options + * @param bool $breakChainOnFailure + * @param int $priority + * @return $this + */ + public function attachByName($name, $options = [], $breakChainOnFailure = false, $priority = self::DEFAULT_PRIORITY) + { + if (isset($options['break_chain_on_failure'])) { + $breakChainOnFailure = (bool) $options['break_chain_on_failure']; + } + + if (isset($options['breakchainonfailure'])) { + $breakChainOnFailure = (bool) $options['breakchainonfailure']; + } + + $this->attach($this->plugin($name, $options), $breakChainOnFailure, $priority); + + return $this; + } + + /** + * Proxy to attachByName() to keep BC + * + * @deprecated Please use attachByName() + * @param string $name + * @param array $options + * @param bool $breakChainOnFailure + * @return ValidatorChain + */ + public function addByName($name, $options = [], $breakChainOnFailure = false) + { + return $this->attachByName($name, $options, $breakChainOnFailure); + } + + /** + * Use the plugin manager to prepend a validator by name + * + * @param string $name + * @param array $options + * @param bool $breakChainOnFailure + * @return $this + */ + public function prependByName($name, $options = [], $breakChainOnFailure = false) + { + $validator = $this->plugin($name, $options); + $this->prependValidator($validator, $breakChainOnFailure); + return $this; + } + + /** + * Returns true if and only if $value passes all validations in the chain + * + * Validators are run in the order in which they were added to the chain (FIFO). + * + * @param mixed $value + * @param mixed $context Extra "context" to provide the validator + * @return bool + */ + public function isValid($value, $context = null) + { + $this->messages = []; + $result = true; + foreach ($this->validators as $element) { + $validator = $element['instance']; + if ($validator->isValid($value, $context)) { + continue; + } + $result = false; + $messages = $validator->getMessages(); + $this->messages = array_replace_recursive($this->messages, $messages); + if ($element['breakChainOnFailure']) { + break; + } + } + return $result; + } + + /** + * Merge the validator chain with the one given in parameter + * + * @param ValidatorChain $validatorChain + * @return $this + */ + public function merge(ValidatorChain $validatorChain) + { + foreach ($validatorChain->validators->toArray(PriorityQueue::EXTR_BOTH) as $item) { + $this->attach($item['data']['instance'], $item['data']['breakChainOnFailure'], $item['priority']); + } + + return $this; + } + + /** + * Returns array of validation failure messages + * + * @return array + */ + public function getMessages() + { + return $this->messages; + } + + /** + * Get all the validators + * + * @return array + */ + public function getValidators() + { + return $this->validators->toArray(PriorityQueue::EXTR_DATA); + } + + /** + * Invoke chain as command + * + * @param mixed $value + * @return bool + */ + public function __invoke($value) + { + return $this->isValid($value); + } + + /** + * Deep clone handling + */ + public function __clone() + { + $this->validators = clone $this->validators; + } + + /** + * Prepare validator chain for serialization + * + * Plugin manager (property 'plugins') cannot + * be serialized. On wakeup the property remains unset + * and next invocation to getPluginManager() sets + * the default plugin manager instance (ValidatorPluginManager). + * + * @return array + */ + public function __sleep() + { + return ['validators', 'messages']; + } +} diff --git a/lib/laminas/laminas-validator/src/ValidatorInterface.php b/lib/laminas/laminas-validator/src/ValidatorInterface.php new file mode 100644 index 000000000..a6f4c847f --- /dev/null +++ b/lib/laminas/laminas-validator/src/ValidatorInterface.php @@ -0,0 +1,37 @@ + I18nValidator\Alnum::class, + 'Alnum' => I18nValidator\Alnum::class, + 'alpha' => I18nValidator\Alpha::class, + 'Alpha' => I18nValidator\Alpha::class, + 'barcode' => Barcode::class, + 'Barcode' => Barcode::class, + 'between' => Between::class, + 'Between' => Between::class, + 'bitwise' => Bitwise::class, + 'Bitwise' => Bitwise::class, + 'callback' => Callback::class, + 'Callback' => Callback::class, + 'creditcard' => CreditCard::class, + 'creditCard' => CreditCard::class, + 'CreditCard' => CreditCard::class, + 'csrf' => Csrf::class, + 'Csrf' => Csrf::class, + 'date' => Date::class, + 'Date' => Date::class, + 'datestep' => DateStep::class, + 'dateStep' => DateStep::class, + 'DateStep' => DateStep::class, + 'datetime' => I18nValidator\DateTime::class, + 'dateTime' => I18nValidator\DateTime::class, + 'DateTime' => I18nValidator\DateTime::class, + 'dbnorecordexists' => Db\NoRecordExists::class, + 'dbNoRecordExists' => Db\NoRecordExists::class, + 'DbNoRecordExists' => Db\NoRecordExists::class, + 'dbrecordexists' => Db\RecordExists::class, + 'dbRecordExists' => Db\RecordExists::class, + 'DbRecordExists' => Db\RecordExists::class, + 'digits' => Digits::class, + 'Digits' => Digits::class, + 'emailaddress' => EmailAddress::class, + 'emailAddress' => EmailAddress::class, + 'EmailAddress' => EmailAddress::class, + 'explode' => Explode::class, + 'Explode' => Explode::class, + 'filecount' => File\Count::class, + 'fileCount' => File\Count::class, + 'FileCount' => File\Count::class, + 'filecrc32' => File\Crc32::class, + 'fileCrc32' => File\Crc32::class, + 'FileCrc32' => File\Crc32::class, + 'fileexcludeextension' => File\ExcludeExtension::class, + 'fileExcludeExtension' => File\ExcludeExtension::class, + 'FileExcludeExtension' => File\ExcludeExtension::class, + 'fileexcludemimetype' => File\ExcludeMimeType::class, + 'fileExcludeMimeType' => File\ExcludeMimeType::class, + 'FileExcludeMimeType' => File\ExcludeMimeType::class, + 'fileexists' => File\Exists::class, + 'fileExists' => File\Exists::class, + 'FileExists' => File\Exists::class, + 'fileextension' => File\Extension::class, + 'fileExtension' => File\Extension::class, + 'FileExtension' => File\Extension::class, + 'filefilessize' => File\FilesSize::class, + 'fileFilesSize' => File\FilesSize::class, + 'FileFilesSize' => File\FilesSize::class, + 'filehash' => File\Hash::class, + 'fileHash' => File\Hash::class, + 'FileHash' => File\Hash::class, + 'fileimagesize' => File\ImageSize::class, + 'fileImageSize' => File\ImageSize::class, + 'FileImageSize' => File\ImageSize::class, + 'fileiscompressed' => File\IsCompressed::class, + 'fileIsCompressed' => File\IsCompressed::class, + 'FileIsCompressed' => File\IsCompressed::class, + 'fileisimage' => File\IsImage::class, + 'fileIsImage' => File\IsImage::class, + 'FileIsImage' => File\IsImage::class, + 'filemd5' => File\Md5::class, + 'fileMd5' => File\Md5::class, + 'FileMd5' => File\Md5::class, + 'filemimetype' => File\MimeType::class, + 'fileMimeType' => File\MimeType::class, + 'FileMimeType' => File\MimeType::class, + 'filenotexists' => File\NotExists::class, + 'fileNotExists' => File\NotExists::class, + 'FileNotExists' => File\NotExists::class, + 'filesha1' => File\Sha1::class, + 'fileSha1' => File\Sha1::class, + 'FileSha1' => File\Sha1::class, + 'filesize' => File\Size::class, + 'fileSize' => File\Size::class, + 'FileSize' => File\Size::class, + 'fileupload' => File\Upload::class, + 'fileUpload' => File\Upload::class, + 'FileUpload' => File\Upload::class, + 'fileuploadfile' => File\UploadFile::class, + 'fileUploadFile' => File\UploadFile::class, + 'FileUploadFile' => File\UploadFile::class, + 'filewordcount' => File\WordCount::class, + 'fileWordCount' => File\WordCount::class, + 'FileWordCount' => File\WordCount::class, + 'float' => I18nValidator\IsFloat::class, + 'Float' => I18nValidator\IsFloat::class, + 'gpspoint' => GpsPoint::class, + 'gpsPoint' => GpsPoint::class, + 'GpsPoint' => GpsPoint::class, + 'greaterthan' => GreaterThan::class, + 'greaterThan' => GreaterThan::class, + 'GreaterThan' => GreaterThan::class, + 'hex' => Hex::class, + 'Hex' => Hex::class, + 'hostname' => Hostname::class, + 'Hostname' => Hostname::class, + 'iban' => Iban::class, + 'Iban' => Iban::class, + 'identical' => Identical::class, + 'Identical' => Identical::class, + 'inarray' => InArray::class, + 'inArray' => InArray::class, + 'InArray' => InArray::class, + 'int' => I18nValidator\IsInt::class, + 'Int' => I18nValidator\IsInt::class, + 'ip' => Ip::class, + 'Ip' => Ip::class, + 'isbn' => Isbn::class, + 'Isbn' => Isbn::class, + 'isfloat' => I18nValidator\IsFloat::class, + 'isFloat' => I18nValidator\IsFloat::class, + 'IsFloat' => I18nValidator\IsFloat::class, + 'isinstanceof' => IsInstanceOf::class, + 'isInstanceOf' => IsInstanceOf::class, + 'IsInstanceOf' => IsInstanceOf::class, + 'isint' => I18nValidator\IsInt::class, + 'isInt' => I18nValidator\IsInt::class, + 'IsInt' => I18nValidator\IsInt::class, + 'lessthan' => LessThan::class, + 'lessThan' => LessThan::class, + 'LessThan' => LessThan::class, + 'notempty' => NotEmpty::class, + 'notEmpty' => NotEmpty::class, + 'NotEmpty' => NotEmpty::class, + 'phonenumber' => I18nValidator\PhoneNumber::class, + 'phoneNumber' => I18nValidator\PhoneNumber::class, + 'PhoneNumber' => I18nValidator\PhoneNumber::class, + 'postcode' => I18nValidator\PostCode::class, + 'postCode' => I18nValidator\PostCode::class, + 'PostCode' => I18nValidator\PostCode::class, + 'regex' => Regex::class, + 'Regex' => Regex::class, + 'sitemapchangefreq' => Sitemap\Changefreq::class, + 'sitemapChangefreq' => Sitemap\Changefreq::class, + 'SitemapChangefreq' => Sitemap\Changefreq::class, + 'sitemaplastmod' => Sitemap\Lastmod::class, + 'sitemapLastmod' => Sitemap\Lastmod::class, + 'SitemapLastmod' => Sitemap\Lastmod::class, + 'sitemaploc' => Sitemap\Loc::class, + 'sitemapLoc' => Sitemap\Loc::class, + 'SitemapLoc' => Sitemap\Loc::class, + 'sitemappriority' => Sitemap\Priority::class, + 'sitemapPriority' => Sitemap\Priority::class, + 'SitemapPriority' => Sitemap\Priority::class, + 'stringlength' => StringLength::class, + 'stringLength' => StringLength::class, + 'StringLength' => StringLength::class, + 'step' => Step::class, + 'Step' => Step::class, + 'timezone' => Timezone::class, + 'Timezone' => Timezone::class, + 'uri' => Uri::class, + 'Uri' => Uri::class, + 'uuid' => Uuid::class, + 'Uuid' => Uuid::class, + + // Legacy Zend Framework aliases + \Zend\I18n\Validator\Alnum::class => I18nValidator\Alnum::class, + \Zend\I18n\Validator\Alpha::class => I18nValidator\Alpha::class, + \Zend\Validator\Barcode::class => Barcode::class, + \Zend\Validator\Between::class => Between::class, + \Zend\Validator\Bitwise::class => Bitwise::class, + \Zend\Validator\Callback::class => Callback::class, + \Zend\Validator\CreditCard::class => CreditCard::class, + \Zend\Validator\Csrf::class => Csrf::class, + \Zend\Validator\DateStep::class => DateStep::class, + \Zend\Validator\Date::class => Date::class, + \Zend\I18n\Validator\DateTime::class => I18nValidator\DateTime::class, + \Zend\Validator\Db\NoRecordExists::class => Db\NoRecordExists::class, + \Zend\Validator\Db\RecordExists::class => Db\RecordExists::class, + \Zend\Validator\Digits::class => Digits::class, + \Zend\Validator\EmailAddress::class => EmailAddress::class, + \Zend\Validator\Explode::class => Explode::class, + \Zend\Validator\File\Count::class => File\Count::class, + \Zend\Validator\File\Crc32::class => File\Crc32::class, + \Zend\Validator\File\ExcludeExtension::class => File\ExcludeExtension::class, + \Zend\Validator\File\ExcludeMimeType::class => File\ExcludeMimeType::class, + \Zend\Validator\File\Exists::class => File\Exists::class, + \Zend\Validator\File\Extension::class => File\Extension::class, + \Zend\Validator\File\FilesSize::class => File\FilesSize::class, + \Zend\Validator\File\Hash::class => File\Hash::class, + \Zend\Validator\File\ImageSize::class => File\ImageSize::class, + \Zend\Validator\File\IsCompressed::class => File\IsCompressed::class, + \Zend\Validator\File\IsImage::class => File\IsImage::class, + \Zend\Validator\File\Md5::class => File\Md5::class, + \Zend\Validator\File\MimeType::class => File\MimeType::class, + \Zend\Validator\File\NotExists::class => File\NotExists::class, + \Zend\Validator\File\Sha1::class => File\Sha1::class, + \Zend\Validator\File\Size::class => File\Size::class, + \Zend\Validator\File\Upload::class => File\Upload::class, + \Zend\Validator\File\UploadFile::class => File\UploadFile::class, + \Zend\Validator\File\WordCount::class => File\WordCount::class, + \Zend\I18n\Validator\IsFloat::class => I18nValidator\IsFloat::class, + \Zend\Validator\GpsPoint::class => GpsPoint::class, + \Zend\Validator\GreaterThan::class => GreaterThan::class, + \Zend\Validator\Hex::class => Hex::class, + \Zend\Validator\Hostname::class => Hostname::class, + \Zend\Validator\Iban::class => Iban::class, + \Zend\Validator\Identical::class => Identical::class, + \Zend\Validator\InArray::class => InArray::class, + \Zend\I18n\Validator\IsInt::class => I18nValidator\IsInt::class, + \Zend\Validator\Ip::class => Ip::class, + \Zend\Validator\Isbn::class => Isbn::class, + \Zend\Validator\IsInstanceOf::class => IsInstanceOf::class, + \Zend\Validator\LessThan::class => LessThan::class, + \Zend\Validator\NotEmpty::class => NotEmpty::class, + \Zend\I18n\Validator\PhoneNumber::class => I18nValidator\PhoneNumber::class, + \Zend\I18n\Validator\PostCode::class => I18nValidator\PostCode::class, + \Zend\Validator\Regex::class => Regex::class, + \Zend\Validator\Sitemap\Changefreq::class => Sitemap\Changefreq::class, + \Zend\Validator\Sitemap\Lastmod::class => Sitemap\Lastmod::class, + \Zend\Validator\Sitemap\Loc::class => Sitemap\Loc::class, + \Zend\Validator\Sitemap\Priority::class => Sitemap\Priority::class, + \Zend\Validator\StringLength::class => StringLength::class, + \Zend\Validator\Step::class => Step::class, + \Zend\Validator\Timezone::class => Timezone::class, + \Zend\Validator\Uri::class => Uri::class, + \Zend\Validator\Uuid::class => Uuid::class, + + // v2 normalized FQCNs + 'zendvalidatorbarcode' => Barcode::class, + 'zendvalidatorbetween' => Between::class, + 'zendvalidatorbitwise' => Bitwise::class, + 'zendvalidatorcallback' => Callback::class, + 'zendvalidatorcreditcard' => CreditCard::class, + 'zendvalidatorcsrf' => Csrf::class, + 'zendvalidatordatestep' => DateStep::class, + 'zendvalidatordate' => Date::class, + 'zendvalidatordbnorecordexists' => Db\NoRecordExists::class, + 'zendvalidatordbrecordexists' => Db\RecordExists::class, + 'zendvalidatordigits' => Digits::class, + 'zendvalidatoremailaddress' => EmailAddress::class, + 'zendvalidatorexplode' => Explode::class, + 'zendvalidatorfilecount' => File\Count::class, + 'zendvalidatorfilecrc32' => File\Crc32::class, + 'zendvalidatorfileexcludeextension' => File\ExcludeExtension::class, + 'zendvalidatorfileexcludemimetype' => File\ExcludeMimeType::class, + 'zendvalidatorfileexists' => File\Exists::class, + 'zendvalidatorfileextension' => File\Extension::class, + 'zendvalidatorfilefilessize' => File\FilesSize::class, + 'zendvalidatorfilehash' => File\Hash::class, + 'zendvalidatorfileimagesize' => File\ImageSize::class, + 'zendvalidatorfileiscompressed' => File\IsCompressed::class, + 'zendvalidatorfileisimage' => File\IsImage::class, + 'zendvalidatorfilemd5' => File\Md5::class, + 'zendvalidatorfilemimetype' => File\MimeType::class, + 'zendvalidatorfilenotexists' => File\NotExists::class, + 'zendvalidatorfilesha1' => File\Sha1::class, + 'zendvalidatorfilesize' => File\Size::class, + 'zendvalidatorfileupload' => File\Upload::class, + 'zendvalidatorfileuploadfile' => File\UploadFile::class, + 'zendvalidatorfilewordcount' => File\WordCount::class, + 'zendvalidatorgpspoint' => GpsPoint::class, + 'zendvalidatorgreaterthan' => GreaterThan::class, + 'zendvalidatorhex' => Hex::class, + 'zendvalidatorhostname' => Hostname::class, + 'zendi18nvalidatoralnum' => I18nValidator\Alnum::class, + 'zendi18nvalidatoralpha' => I18nValidator\Alpha::class, + 'zendi18nvalidatordatetime' => I18nValidator\DateTime::class, + 'zendi18nvalidatorisfloat' => I18nValidator\IsFloat::class, + 'zendi18nvalidatorisint' => I18nValidator\IsInt::class, + 'zendi18nvalidatorphonenumber' => I18nValidator\PhoneNumber::class, + 'zendi18nvalidatorpostcode' => I18nValidator\PostCode::class, + 'zendvalidatoriban' => Iban::class, + 'zendvalidatoridentical' => Identical::class, + 'zendvalidatorinarray' => InArray::class, + 'zendvalidatorip' => Ip::class, + 'zendvalidatorisbn' => Isbn::class, + 'zendvalidatorisinstanceof' => IsInstanceOf::class, + 'zendvalidatorlessthan' => LessThan::class, + 'zendvalidatornotempty' => NotEmpty::class, + 'zendvalidatorregex' => Regex::class, + 'zendvalidatorsitemapchangefreq' => Sitemap\Changefreq::class, + 'zendvalidatorsitemaplastmod' => Sitemap\Lastmod::class, + 'zendvalidatorsitemaploc' => Sitemap\Loc::class, + 'zendvalidatorsitemappriority' => Sitemap\Priority::class, + 'zendvalidatorstringlength' => StringLength::class, + 'zendvalidatorstep' => Step::class, + 'zendvalidatortimezone' => Timezone::class, + 'zendvalidatoruri' => Uri::class, + 'zendvalidatoruuid' => Uuid::class, + ]; + + /** + * Default set of factories + * + * @var array + */ + protected $factories = [ + I18nValidator\Alnum::class => InvokableFactory::class, + I18nValidator\Alpha::class => InvokableFactory::class, + Barcode::class => InvokableFactory::class, + Between::class => InvokableFactory::class, + Bitwise::class => InvokableFactory::class, + Callback::class => InvokableFactory::class, + CreditCard::class => InvokableFactory::class, + Csrf::class => InvokableFactory::class, + DateStep::class => InvokableFactory::class, + Date::class => InvokableFactory::class, + I18nValidator\DateTime::class => InvokableFactory::class, + Db\NoRecordExists::class => InvokableFactory::class, + Db\RecordExists::class => InvokableFactory::class, + Digits::class => InvokableFactory::class, + EmailAddress::class => InvokableFactory::class, + Explode::class => InvokableFactory::class, + File\Count::class => InvokableFactory::class, + File\Crc32::class => InvokableFactory::class, + File\ExcludeExtension::class => InvokableFactory::class, + File\ExcludeMimeType::class => InvokableFactory::class, + File\Exists::class => InvokableFactory::class, + File\Extension::class => InvokableFactory::class, + File\FilesSize::class => InvokableFactory::class, + File\Hash::class => InvokableFactory::class, + File\ImageSize::class => InvokableFactory::class, + File\IsCompressed::class => InvokableFactory::class, + File\IsImage::class => InvokableFactory::class, + File\Md5::class => InvokableFactory::class, + File\MimeType::class => InvokableFactory::class, + File\NotExists::class => InvokableFactory::class, + File\Sha1::class => InvokableFactory::class, + File\Size::class => InvokableFactory::class, + File\Upload::class => InvokableFactory::class, + File\UploadFile::class => InvokableFactory::class, + File\WordCount::class => InvokableFactory::class, + I18nValidator\IsFloat::class => InvokableFactory::class, + GpsPoint::class => InvokableFactory::class, + GreaterThan::class => InvokableFactory::class, + Hex::class => InvokableFactory::class, + Hostname::class => InvokableFactory::class, + Iban::class => InvokableFactory::class, + Identical::class => InvokableFactory::class, + InArray::class => InvokableFactory::class, + I18nValidator\IsInt::class => InvokableFactory::class, + Ip::class => InvokableFactory::class, + Isbn::class => InvokableFactory::class, + IsInstanceOf::class => InvokableFactory::class, + LessThan::class => InvokableFactory::class, + NotEmpty::class => InvokableFactory::class, + I18nValidator\PhoneNumber::class => InvokableFactory::class, + I18nValidator\PostCode::class => InvokableFactory::class, + Regex::class => InvokableFactory::class, + Sitemap\Changefreq::class => InvokableFactory::class, + Sitemap\Lastmod::class => InvokableFactory::class, + Sitemap\Loc::class => InvokableFactory::class, + Sitemap\Priority::class => InvokableFactory::class, + StringLength::class => InvokableFactory::class, + Step::class => InvokableFactory::class, + Timezone::class => InvokableFactory::class, + Uri::class => InvokableFactory::class, + Uuid::class => InvokableFactory::class, + + // v2 canonical FQCNs + + 'laminasvalidatorbarcodecode25interleaved' => InvokableFactory::class, + 'laminasvalidatorbarcodecode25' => InvokableFactory::class, + 'laminasvalidatorbarcodecode39ext' => InvokableFactory::class, + 'laminasvalidatorbarcodecode39' => InvokableFactory::class, + 'laminasvalidatorbarcodecode93ext' => InvokableFactory::class, + 'laminasvalidatorbarcodecode93' => InvokableFactory::class, + 'laminasvalidatorbarcodeean12' => InvokableFactory::class, + 'laminasvalidatorbarcodeean13' => InvokableFactory::class, + 'laminasvalidatorbarcodeean14' => InvokableFactory::class, + 'laminasvalidatorbarcodeean18' => InvokableFactory::class, + 'laminasvalidatorbarcodeean2' => InvokableFactory::class, + 'laminasvalidatorbarcodeean5' => InvokableFactory::class, + 'laminasvalidatorbarcodeean8' => InvokableFactory::class, + 'laminasvalidatorbarcodegtin12' => InvokableFactory::class, + 'laminasvalidatorbarcodegtin13' => InvokableFactory::class, + 'laminasvalidatorbarcodegtin14' => InvokableFactory::class, + 'laminasvalidatorbarcodeidentcode' => InvokableFactory::class, + 'laminasvalidatorbarcodeintelligentmail' => InvokableFactory::class, + 'laminasvalidatorbarcodeissn' => InvokableFactory::class, + 'laminasvalidatorbarcodeitf14' => InvokableFactory::class, + 'laminasvalidatorbarcodeleitcode' => InvokableFactory::class, + 'laminasvalidatorbarcodeplanet' => InvokableFactory::class, + 'laminasvalidatorbarcodepostnet' => InvokableFactory::class, + 'laminasvalidatorbarcoderoyalmail' => InvokableFactory::class, + 'laminasvalidatorbarcodesscc' => InvokableFactory::class, + 'laminasvalidatorbarcodeupca' => InvokableFactory::class, + 'laminasvalidatorbarcodeupce' => InvokableFactory::class, + 'laminasvalidatorbarcode' => InvokableFactory::class, + 'laminasvalidatorbetween' => InvokableFactory::class, + 'laminasvalidatorbitwise' => InvokableFactory::class, + 'laminasvalidatorcallback' => InvokableFactory::class, + 'laminasvalidatorcreditcard' => InvokableFactory::class, + 'laminasvalidatorcsrf' => InvokableFactory::class, + 'laminasvalidatordatestep' => InvokableFactory::class, + 'laminasvalidatordate' => InvokableFactory::class, + 'laminasvalidatordbnorecordexists' => InvokableFactory::class, + 'laminasvalidatordbrecordexists' => InvokableFactory::class, + 'laminasvalidatordigits' => InvokableFactory::class, + 'laminasvalidatoremailaddress' => InvokableFactory::class, + 'laminasvalidatorexplode' => InvokableFactory::class, + 'laminasvalidatorfilecount' => InvokableFactory::class, + 'laminasvalidatorfilecrc32' => InvokableFactory::class, + 'laminasvalidatorfileexcludeextension' => InvokableFactory::class, + 'laminasvalidatorfileexcludemimetype' => InvokableFactory::class, + 'laminasvalidatorfileexists' => InvokableFactory::class, + 'laminasvalidatorfileextension' => InvokableFactory::class, + 'laminasvalidatorfilefilessize' => InvokableFactory::class, + 'laminasvalidatorfilehash' => InvokableFactory::class, + 'laminasvalidatorfileimagesize' => InvokableFactory::class, + 'laminasvalidatorfileiscompressed' => InvokableFactory::class, + 'laminasvalidatorfileisimage' => InvokableFactory::class, + 'laminasvalidatorfilemd5' => InvokableFactory::class, + 'laminasvalidatorfilemimetype' => InvokableFactory::class, + 'laminasvalidatorfilenotexists' => InvokableFactory::class, + 'laminasvalidatorfilesha1' => InvokableFactory::class, + 'laminasvalidatorfilesize' => InvokableFactory::class, + 'laminasvalidatorfileupload' => InvokableFactory::class, + 'laminasvalidatorfileuploadfile' => InvokableFactory::class, + 'laminasvalidatorfilewordcount' => InvokableFactory::class, + 'laminasvalidatorgpspoint' => InvokableFactory::class, + 'laminasvalidatorgreaterthan' => InvokableFactory::class, + 'laminasvalidatorhex' => InvokableFactory::class, + 'laminasvalidatorhostname' => InvokableFactory::class, + 'laminasi18nvalidatoralnum' => InvokableFactory::class, + 'laminasi18nvalidatoralpha' => InvokableFactory::class, + 'laminasi18nvalidatordatetime' => InvokableFactory::class, + 'laminasi18nvalidatorisfloat' => InvokableFactory::class, + 'laminasi18nvalidatorisint' => InvokableFactory::class, + 'laminasi18nvalidatorphonenumber' => InvokableFactory::class, + 'laminasi18nvalidatorpostcode' => InvokableFactory::class, + 'laminasvalidatoriban' => InvokableFactory::class, + 'laminasvalidatoridentical' => InvokableFactory::class, + 'laminasvalidatorinarray' => InvokableFactory::class, + 'laminasvalidatorip' => InvokableFactory::class, + 'laminasvalidatorisbn' => InvokableFactory::class, + 'laminasvalidatorisinstanceof' => InvokableFactory::class, + 'laminasvalidatorlessthan' => InvokableFactory::class, + 'laminasvalidatornotempty' => InvokableFactory::class, + 'laminasvalidatorregex' => InvokableFactory::class, + 'laminasvalidatorsitemapchangefreq' => InvokableFactory::class, + 'laminasvalidatorsitemaplastmod' => InvokableFactory::class, + 'laminasvalidatorsitemaploc' => InvokableFactory::class, + 'laminasvalidatorsitemappriority' => InvokableFactory::class, + 'laminasvalidatorstringlength' => InvokableFactory::class, + 'laminasvalidatorstep' => InvokableFactory::class, + 'laminasvalidatortimezone' => InvokableFactory::class, + 'laminasvalidatoruri' => InvokableFactory::class, + 'laminasvalidatoruuid' => InvokableFactory::class, + ]; + + /** + * Whether or not to share by default; default to false (v2) + * + * @var bool + */ + protected $shareByDefault = false; + + /** + * Whether or not to share by default; default to false (v3) + * + * @var bool + */ + protected $sharedByDefault = false; + + /** + * Default instance type + * + * @var string + */ + protected $instanceOf = ValidatorInterface::class; + + /** + * Constructor + * + * After invoking parent constructor, add an initializer to inject the + * attached translator, if any, to the currently requested helper. + * + * {@inheritDoc} + */ + public function __construct($configOrContainerInstance = null, array $v3config = []) + { + parent::__construct($configOrContainerInstance, $v3config); + + $this->addInitializer([$this, 'injectTranslator']); + $this->addInitializer([$this, 'injectValidatorPluginManager']); + } + + /** + * Validate plugin instance + * + * {@inheritDoc} + */ + public function validate($plugin) + { + if (! $plugin instanceof $this->instanceOf) { + throw new InvalidServiceException(sprintf( + '%s expects only to create instances of %s; %s is invalid', + get_class($this), + $this->instanceOf, + is_object($plugin) ? get_class($plugin) : gettype($plugin) + )); + } + } + + /** + * For v2 compatibility: validate plugin instance. + * + * Proxies to `validate()`. + * + * @param mixed $plugin + * @throws Exception\RuntimeException + */ + public function validatePlugin($plugin) + { + try { + $this->validate($plugin); + } catch (InvalidServiceException $e) { + throw new Exception\RuntimeException(sprintf( + 'Plugin of type %s is invalid; must implement %s', + is_object($plugin) ? get_class($plugin) : gettype($plugin), + ValidatorInterface::class + ), $e->getCode(), $e); + } + } + + /** + * Inject a validator instance with the registered translator + * + * @param ContainerInterface|object $first + * @param ContainerInterface|object $second + * @return void + */ + public function injectTranslator($first, $second) + { + if ($first instanceof ContainerInterface) { + $container = $first; + $validator = $second; + } else { + $container = $second; + $validator = $first; + } + + // V2 means we pull it from the parent container + if ($container === $this && method_exists($container, 'getServiceLocator') && $container->getServiceLocator()) { + $container = $container->getServiceLocator(); + } + + if ($validator instanceof Translator\TranslatorAwareInterface) { + if ($container && $container->has('MvcTranslator')) { + $validator->setTranslator($container->get('MvcTranslator')); + } + } + } + + /** + * Inject a validator plugin manager + * + * @param ContainerInterface|object $first + * @param ContainerInterface|object $second + * @return void + */ + public function injectValidatorPluginManager($first, $second) + { + if ($first instanceof ContainerInterface) { + $container = $first; + $validator = $second; + } else { + $container = $second; + $validator = $first; + } + if ($validator instanceof ValidatorPluginManagerAwareInterface) { + $validator->setValidatorPluginManager($this); + } + } +} diff --git a/lib/laminas/laminas-validator/src/ValidatorPluginManagerAwareInterface.php b/lib/laminas/laminas-validator/src/ValidatorPluginManagerAwareInterface.php new file mode 100644 index 000000000..48144127e --- /dev/null +++ b/lib/laminas/laminas-validator/src/ValidatorPluginManagerAwareInterface.php @@ -0,0 +1,26 @@ +has('ServiceListener')) { + return $pluginManager; + } + + // If we do not have a config service, nothing more to do + if (! $container->has('config')) { + return $pluginManager; + } + + $config = $container->get('config'); + + // If we do not have validators configuration, nothing more to do + if (! isset($config['validators']) || ! is_array($config['validators'])) { + return $pluginManager; + } + + // Wire service configuration for validators + (new Config($config['validators']))->configureServiceManager($pluginManager); + + return $pluginManager; + } + + /** + * {@inheritDoc} + * + * @return ValidatorPluginManager + */ + public function createService(ServiceLocatorInterface $container, $name = null, $requestedName = null) + { + return $this($container, $requestedName ?: ValidatorPluginManager::class, $this->creationOptions); + } + + /** + * laminas-servicemanager v2 support for invocation options. + * + * @param array $options + * @return void + */ + public function setCreationOptions(array $options) + { + $this->creationOptions = $options; + } +} diff --git a/lib/laminas/laminas-validator/src/ValidatorProviderInterface.php b/lib/laminas/laminas-validator/src/ValidatorProviderInterface.php new file mode 100644 index 000000000..4640dfa66 --- /dev/null +++ b/lib/laminas/laminas-validator/src/ValidatorProviderInterface.php @@ -0,0 +1,30 @@ + laminas-project.flf. + +## 0.3.5 - 2019-11-06 + +### Added + +- Nothing. + +### Changed + +- Nothing. + +### Deprecated + +- Nothing. + +### Removed + +- Nothing. + +### Fixed + +- [#25](https://github.com/laminas/laminas-zendframework-bridge/pull/25) adds entries for ZendHttp and ZendModule, which are file name segments in files from the zend-feed and zend-config-aggregator-module packages, respectively. + +## 0.3.4 - 2019-11-06 + +### Added + +- Nothing. + +### Changed + +- Nothing. + +### Deprecated + +- Nothing. + +### Removed + +- Nothing. + +### Fixed + +- [#24](https://github.com/laminas/laminas-zendframework-bridge/pull/24) adds a rule to never rewrite the string `Doctrine\Zend`. + +- [#23](https://github.com/laminas/laminas-zendframework-bridge/pull/23) adds a missing map for each of ZendAcl and ZendRbac, which occur in the zend-expressive-authorization-acl and zend-expressive-authorization-rbac packages, respectively. + +## 0.3.3 - 2019-11-06 + +### Added + +- [#22](https://github.com/laminas/laminas-zendframework-bridge/pull/22) adds configuration post-processing features, exposed both as a laminas-config-aggregator post processor (for use with Expressive applications) and as a laminas-modulemanager `EVENT_MERGE_CONFIG` listener (for use with MVC applications). When registered, it will post-process the configuration, replacing known Zend Framework-specific strings with their Laminas replacements. A ruleset is provided that ensures dependency configuration is rewritten in a safe manner, routing configuration is skipped, and certain top-level configuration keys are matched exactly (instead of potentially as substrings or word stems). A later release of laminas-migration will auto-register these tools in applications when possible. + +### Changed + +- [#22](https://github.com/laminas/laminas-zendframework-bridge/pull/22) removes support for PHP versions prior to PHP 5.6. We have decided to only support supported PHP versions, whether that support is via php.net or commercial. The lowest supported PHP version we have found is 5.6. Users wishing to migrate to Laminas must at least update to PHP 5.6 before doing so. + +### Deprecated + +- Nothing. + +### Removed + +- Nothing. + +### Fixed + +- Nothing. + +## 0.3.2 - 2019-10-30 + +### Added + +- Nothing. + +### Changed + +- Nothing. + +### Deprecated + +- Nothing. + +### Removed + +- [#21](https://github.com/laminas/laminas-zendframework-bridge/pull/21) removes rewriting of the Amazon library, as it is not moving to Laminas. + +- [#21](https://github.com/laminas/laminas-zendframework-bridge/pull/21) removes rewriting of the GCM and APNS libraries, as they are not moving to Laminas. + +### Fixed + +- [#21](https://github.com/laminas/laminas-zendframework-bridge/pull/21) fixes how the recaptcha and twitter library package and namespaces are rewritten. + +## 0.3.1 - 2019-04-25 + +### Added + +- [#20](https://github.com/laminas/laminas-zendframework-bridge/pull/20) provides an additional autoloader that is _prepended_ to the autoloader + stack. This new autoloader will create class aliases for interfaces, classes, + and traits referenced in type hints and class declarations, ensuring PHP is + able to resolve them correctly during class_alias operations. + +### Changed + +- Nothing. + +### Deprecated + +- Nothing. + +### Removed + +- Nothing. + +### Fixed + +- Nothing. + +## 0.3.0 - 2019-04-12 + +### Added + +- Nothing. + +### Changed + +- Nothing. + +### Deprecated + +- Nothing. + +### Removed + +- [#16](https://github.com/laminas/laminas-zendframework-bridge/pull/16) removes the `RewriteRules::classRewrite()` method, as it is no longer + needed due to internal refactoring. + +### Fixed + +- [#16](https://github.com/laminas/laminas-zendframework-bridge/pull/16) fixes how the rewrite rules detect the word `Zend` in subnamespaces and + class names to be both more robust and simpler. + +## 0.2.5 - 2019-04-11 + +### Added + +- [#12](https://github.com/laminas/laminas-zendframework-bridge/pull/12) adds functionality for ensuring we alias namespaces and classes that + include the word `Zend` in them; e.g., `Zend\Expressive\ZendView\ZendViewRendererFactory` + will now alias to `Expressive\LaminasView\LaminasViewRendererFactory`. + +### Changed + +- Nothing. + +### Deprecated + +- Nothing. + +### Removed + +- Nothing. + +### Fixed + +- Nothing. + +## 0.2.4 - 2019-04-11 + +### Added + +- [#11](https://github.com/laminas/laminas-zendframework-bridge/pull/11) adds maps for the Expressive router adapter packages. + +- [#10](https://github.com/laminas/laminas-zendframework-bridge/pull/10) adds a map for the Psr7Bridge package, as it used `Zend` within a subnamespace. + +### Changed + +- Nothing. + +### Deprecated + +- Nothing. + +### Removed + +- Nothing. + +### Fixed + +- Nothing. + +## 0.2.3 - 2019-04-10 + +### Added + +- Nothing. + +### Changed + +- Nothing. + +### Deprecated + +- Nothing. + +### Removed + +- Nothing. + +### Fixed + +- [#9](https://github.com/laminas/laminas-zendframework-bridge/pull/9) fixes the mapping for the Problem Details package. + +## 0.2.2 - 2019-04-10 + +### Added + +- Nothing. + +### Changed + +- Nothing. + +### Deprecated + +- Nothing. + +### Removed + +- Nothing. + +### Fixed + +- Added a check that the discovered alias exists as a class, interface, or trait + before attempting to call `class_alias()`. + +## 0.2.1 - 2019-04-10 + +### Added + +- Nothing. + +### Changed + +- Nothing. + +### Deprecated + +- Nothing. + +### Removed + +- Nothing. + +### Fixed + +- [#8](https://github.com/laminas/laminas-zendframework-bridge/pull/8) fixes mappings for each of zend-expressive-authentication-zendauthentication, + zend-expressive-zendrouter, and zend-expressive-zendviewrenderer. + +## 0.2.0 - 2019-04-01 + +### Added + +- Nothing. + +### Changed + +- [#4](https://github.com/laminas/laminas-zendframework-bridge/pull/4) rewrites the autoloader to be class-based, via the class + `Laminas\ZendFrameworkBridge\Autoloader`. Additionally, the new approach + provides a performance boost by using a balanced tree algorithm, ensuring + matches occur faster. + +### Deprecated + +- Nothing. + +### Removed + +- [#4](https://github.com/laminas/laminas-zendframework-bridge/pull/4) removes function aliasing. Function aliasing will move to the packages that + provide functions. + +### Fixed + +- Nothing. + +## 0.1.0 - 2019-03-27 + +### Added + +- Adds an autoloader file that registers with `spl_autoload_register` a routine + for aliasing legacy ZF class/interface/trait names to Laminas Project + equivalents. + +- Adds autoloader files for aliasing legacy ZF package functions to Laminas + Project equivalents. + +### Changed + +- Nothing. + +### Deprecated + +- Nothing. + +### Removed + +- Nothing. + +### Fixed + +- Nothing. diff --git a/lib/laminas/laminas-zendframework-bridge/COPYRIGHT.md b/lib/laminas/laminas-zendframework-bridge/COPYRIGHT.md new file mode 100644 index 000000000..0a8cccc06 --- /dev/null +++ b/lib/laminas/laminas-zendframework-bridge/COPYRIGHT.md @@ -0,0 +1 @@ +Copyright (c) 2020 Laminas Project a Series of LF Projects, LLC. (https://getlaminas.org/) diff --git a/lib/laminas/laminas-zendframework-bridge/LICENSE.md b/lib/laminas/laminas-zendframework-bridge/LICENSE.md new file mode 100644 index 000000000..10b40f142 --- /dev/null +++ b/lib/laminas/laminas-zendframework-bridge/LICENSE.md @@ -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. diff --git a/lib/laminas/laminas-zendframework-bridge/README.md b/lib/laminas/laminas-zendframework-bridge/README.md new file mode 100644 index 000000000..fd7953823 --- /dev/null +++ b/lib/laminas/laminas-zendframework-bridge/README.md @@ -0,0 +1,24 @@ +# laminas-zendframework-bridge + +[![Build Status](https://travis-ci.com/laminas/laminas-zendframework-bridge.svg?branch=master)](https://travis-ci.com/laminas/laminas-zendframework-bridge) +[![Coverage Status](https://coveralls.io/repos/github/laminas/laminas-zendframework-bridge/badge.svg?branch=master)](https://coveralls.io/github/laminas/laminas-zendframework-bridge?branch=master) + +This library provides a custom autoloader that aliases legacy Zend Framework, +Apigility, and Expressive classes to their replacements under the Laminas +Project. + +This package should be installed only if you are also using the composer plugin +that installs Laminas packages to replace ZF/Apigility/Expressive packages. + +## Installation + +Run the following to install this library: + +```bash +$ composer require laminas/laminas-zendframework-bridge +``` + +## Support + +* [Issues](https://github.com/laminas/laminas-zendframework-bridge/issues/) +* [Forum](https://discourse.laminas.dev/) diff --git a/lib/laminas/laminas-zendframework-bridge/composer.json b/lib/laminas/laminas-zendframework-bridge/composer.json new file mode 100644 index 000000000..34af15a43 --- /dev/null +++ b/lib/laminas/laminas-zendframework-bridge/composer.json @@ -0,0 +1,58 @@ +{ + "name": "laminas/laminas-zendframework-bridge", + "description": "Alias legacy ZF class names to Laminas Project equivalents.", + "license": "BSD-3-Clause", + "keywords": [ + "autoloading", + "laminas", + "zf", + "zendframework" + ], + "support": { + "issues": "https://github.com/laminas/laminas-zendframework-bridge/issues", + "source": "https://github.com/laminas/laminas-zendframework-bridge", + "rss": "https://github.com/laminas/laminas-zendframework-bridge/releases.atom", + "forum": "https://discourse.laminas.dev/" + }, + "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" + }, + "autoload": { + "files": [ + "src/autoload.php" + ], + "psr-4": { + "Laminas\\ZendFrameworkBridge\\": "src//" + } + }, + "autoload-dev": { + "files": [ + "test/classes.php" + ], + "psr-4": { + "LaminasTest\\ZendFrameworkBridge\\": "test/", + "LaminasTest\\ZendFrameworkBridge\\TestAsset\\": "test/TestAsset/classes/", + "Laminas\\ApiTools\\": "test/TestAsset/LaminasApiTools/", + "Mezzio\\": "test/TestAsset/Mezzio/", + "Laminas\\": "test/TestAsset/Laminas/" + } + }, + "extra": { + "laminas": { + "module": "Laminas\\ZendFrameworkBridge" + } + }, + "config": { + "sort-packages": true + }, + "scripts": { + "cs-check": "phpcs", + "cs-fix": "phpcbf", + "test": "phpunit --colors=always", + "test-coverage": "phpunit --colors=always --coverage-clover clover.xml" + } +} diff --git a/lib/laminas/laminas-zendframework-bridge/config/replacements.php b/lib/laminas/laminas-zendframework-bridge/config/replacements.php new file mode 100644 index 000000000..f5344355f --- /dev/null +++ b/lib/laminas/laminas-zendframework-bridge/config/replacements.php @@ -0,0 +1,372 @@ + 'zendframework/zendframework', + 'zend-developer-tools/toolbar/bjy' => 'zend-developer-tools/toolbar/bjy', + 'zend-developer-tools/toolbar/doctrine' => 'zend-developer-tools/toolbar/doctrine', + + // NAMESPACES + // Zend Framework components + 'Zend\\AuraDi\\Config' => 'Laminas\\AuraDi\\Config', + 'Zend\\Authentication' => 'Laminas\\Authentication', + 'Zend\\Barcode' => 'Laminas\\Barcode', + 'Zend\\Cache' => 'Laminas\\Cache', + 'Zend\\Captcha' => 'Laminas\\Captcha', + 'Zend\\Code' => 'Laminas\\Code', + 'ZendCodingStandard\\Sniffs' => 'LaminasCodingStandard\\Sniffs', + 'ZendCodingStandard\\Utils' => 'LaminasCodingStandard\\Utils', + 'Zend\\ComponentInstaller' => 'Laminas\\ComponentInstaller', + 'Zend\\Config' => 'Laminas\\Config', + 'Zend\\ConfigAggregator' => 'Laminas\\ConfigAggregator', + 'Zend\\ConfigAggregatorModuleManager' => 'Laminas\\ConfigAggregatorModuleManager', + 'Zend\\ConfigAggregatorParameters' => 'Laminas\\ConfigAggregatorParameters', + 'Zend\\Console' => 'Laminas\\Console', + 'Zend\\ContainerConfigTest' => 'Laminas\\ContainerConfigTest', + 'Zend\\Crypt' => 'Laminas\\Crypt', + 'Zend\\Db' => 'Laminas\\Db', + 'ZendDeveloperTools' => 'Laminas\\DeveloperTools', + 'Zend\\Di' => 'Laminas\\Di', + 'Zend\\Diactoros' => 'Laminas\\Diactoros', + 'ZendDiagnostics\\Check' => 'Laminas\\Diagnostics\\Check', + 'ZendDiagnostics\\Result' => 'Laminas\\Diagnostics\\Result', + 'ZendDiagnostics\\Runner' => 'Laminas\\Diagnostics\\Runner', + 'Zend\\Dom' => 'Laminas\\Dom', + 'Zend\\Escaper' => 'Laminas\\Escaper', + 'Zend\\EventManager' => 'Laminas\\EventManager', + 'Zend\\Feed' => 'Laminas\\Feed', + 'Zend\\File' => 'Laminas\\File', + 'Zend\\Filter' => 'Laminas\\Filter', + 'Zend\\Form' => 'Laminas\\Form', + 'Zend\\Http' => 'Laminas\\Http', + 'Zend\\HttpHandlerRunner' => 'Laminas\\HttpHandlerRunner', + 'Zend\\Hydrator' => 'Laminas\\Hydrator', + 'Zend\\I18n' => 'Laminas\\I18n', + 'Zend\\InputFilter' => 'Laminas\\InputFilter', + 'Zend\\Json' => 'Laminas\\Json', + 'Zend\\Ldap' => 'Laminas\\Ldap', + 'Zend\\Loader' => 'Laminas\\Loader', + 'Zend\\Log' => 'Laminas\\Log', + 'Zend\\Mail' => 'Laminas\\Mail', + 'Zend\\Math' => 'Laminas\\Math', + 'Zend\\Memory' => 'Laminas\\Memory', + 'Zend\\Mime' => 'Laminas\\Mime', + 'Zend\\ModuleManager' => 'Laminas\\ModuleManager', + 'Zend\\Mvc' => 'Laminas\\Mvc', + 'Zend\\Navigation' => 'Laminas\\Navigation', + 'Zend\\Paginator' => 'Laminas\\Paginator', + 'Zend\\Permissions' => 'Laminas\\Permissions', + 'Zend\\Pimple\\Config' => 'Laminas\\Pimple\\Config', + 'Zend\\ProblemDetails' => 'Mezzio\\ProblemDetails', + 'Zend\\ProgressBar' => 'Laminas\\ProgressBar', + 'Zend\\Psr7Bridge' => 'Laminas\\Psr7Bridge', + 'Zend\\Router' => 'Laminas\\Router', + 'Zend\\Serializer' => 'Laminas\\Serializer', + 'Zend\\Server' => 'Laminas\\Server', + 'Zend\\ServiceManager' => 'Laminas\\ServiceManager', + 'ZendService\\ReCaptcha' => 'Laminas\\ReCaptcha', + 'ZendService\\Twitter' => 'Laminas\\Twitter', + 'Zend\\Session' => 'Laminas\\Session', + 'Zend\\SkeletonInstaller' => 'Laminas\\SkeletonInstaller', + 'Zend\\Soap' => 'Laminas\\Soap', + 'Zend\\Stdlib' => 'Laminas\\Stdlib', + 'Zend\\Stratigility' => 'Laminas\\Stratigility', + 'Zend\\Tag' => 'Laminas\\Tag', + 'Zend\\Test' => 'Laminas\\Test', + 'Zend\\Text' => 'Laminas\\Text', + 'Zend\\Uri' => 'Laminas\\Uri', + 'Zend\\Validator' => 'Laminas\\Validator', + 'Zend\\View' => 'Laminas\\View', + 'ZendXml' => 'Laminas\\Xml', + 'Zend\\Xml2Json' => 'Laminas\\Xml2Json', + 'Zend\\XmlRpc' => 'Laminas\\XmlRpc', + 'ZendOAuth' => 'Laminas\\OAuth', + + // class ZendAcl in zend-expressive-authorization-acl + 'ZendAcl' => 'LaminasAcl', + 'Zend\\Expressive\\Authorization\\Acl\\ZendAcl' => 'Mezzio\\Authorization\\Acl\\LaminasAcl', + // class ZendHttpClientDecorator in zend-feed + 'ZendHttp' => 'LaminasHttp', + // class ZendModuleProvider in zend-config-aggregator-modulemanager + 'ZendModule' => 'LaminasModule', + // class ZendRbac in zend-expressive-authorization-rbac + 'ZendRbac' => 'LaminasRbac', + 'Zend\\Expressive\\Authorization\\Rbac\\ZendRbac' => 'Mezzio\\Authorization\\Rbac\\LaminasRbac', + // class ZendRouter in zend-expressive-router-zendrouter + 'ZendRouter' => 'LaminasRouter', + 'Zend\\Expressive\\Router\\ZendRouter' => 'Mezzio\\Router\\LaminasRouter', + // class ZendViewRenderer in zend-expressive-zendviewrenderer + 'ZendViewRenderer' => 'LaminasViewRenderer', + 'Zend\\Expressive\\ZendView\\ZendViewRenderer' => 'Mezzio\\LaminasView\\LaminasViewRenderer', + 'a\\Zend' => 'a\\Zend', + 'b\\Zend' => 'b\\Zend', + 'c\\Zend' => 'c\\Zend', + 'd\\Zend' => 'd\\Zend', + 'e\\Zend' => 'e\\Zend', + 'f\\Zend' => 'f\\Zend', + 'g\\Zend' => 'g\\Zend', + 'h\\Zend' => 'h\\Zend', + 'i\\Zend' => 'i\\Zend', + 'j\\Zend' => 'j\\Zend', + 'k\\Zend' => 'k\\Zend', + 'l\\Zend' => 'l\\Zend', + 'm\\Zend' => 'm\\Zend', + 'n\\Zend' => 'n\\Zend', + 'o\\Zend' => 'o\\Zend', + 'p\\Zend' => 'p\\Zend', + 'q\\Zend' => 'q\\Zend', + 'r\\Zend' => 'r\\Zend', + 's\\Zend' => 's\\Zend', + 't\\Zend' => 't\\Zend', + 'u\\Zend' => 'u\\Zend', + 'v\\Zend' => 'v\\Zend', + 'w\\Zend' => 'w\\Zend', + 'x\\Zend' => 'x\\Zend', + 'y\\Zend' => 'y\\Zend', + 'z\\Zend' => 'z\\Zend', + + // Expressive + 'Zend\\Expressive' => 'Mezzio', + 'ZendAuthentication' => 'LaminasAuthentication', + 'ZendAcl' => 'LaminasAcl', + 'ZendRbac' => 'LaminasRbac', + 'ZendRouter' => 'LaminasRouter', + 'ExpressiveUrlGenerator' => 'MezzioUrlGenerator', + 'ExpressiveInstaller' => 'MezzioInstaller', + + // Apigility + 'ZF\\Apigility' => 'Laminas\\ApiTools', + 'ZF\\ApiProblem' => 'Laminas\\ApiTools\\ApiProblem', + 'ZF\\AssetManager' => 'Laminas\\ApiTools\\AssetManager', + 'ZF\\ComposerAutoloading' => 'Laminas\\ComposerAutoloading', + 'ZF\\Configuration' => 'Laminas\\ApiTools\\Configuration', + 'ZF\\ContentNegotiation' => 'Laminas\\ApiTools\\ContentNegotiation', + 'ZF\\ContentValidation' => 'Laminas\\ApiTools\\ContentValidation', + 'ZF\\DevelopmentMode' => 'Laminas\\DevelopmentMode', + 'ZF\\Doctrine\\QueryBuilder' => 'Laminas\\ApiTools\\Doctrine\\QueryBuilder', + 'ZF\\Hal' => 'Laminas\\ApiTools\\Hal', + 'ZF\\HttpCache' => 'Laminas\\ApiTools\\HttpCache', + 'ZF\\MvcAuth' => 'Laminas\\ApiTools\\MvcAuth', + 'ZF\\OAuth2' => 'Laminas\\ApiTools\\OAuth2', + 'ZF\\Rest' => 'Laminas\\ApiTools\\Rest', + 'ZF\\Rpc' => 'Laminas\\ApiTools\\Rpc', + 'ZF\\Versioning' => 'Laminas\\ApiTools\\Versioning', + 'a\\ZF' => 'a\\ZF', + 'b\\ZF' => 'b\\ZF', + 'c\\ZF' => 'c\\ZF', + 'd\\ZF' => 'd\\ZF', + 'e\\ZF' => 'e\\ZF', + 'f\\ZF' => 'f\\ZF', + 'g\\ZF' => 'g\\ZF', + 'h\\ZF' => 'h\\ZF', + 'i\\ZF' => 'i\\ZF', + 'j\\ZF' => 'j\\ZF', + 'k\\ZF' => 'k\\ZF', + 'l\\ZF' => 'l\\ZF', + 'm\\ZF' => 'm\\ZF', + 'n\\ZF' => 'n\\ZF', + 'o\\ZF' => 'o\\ZF', + 'p\\ZF' => 'p\\ZF', + 'q\\ZF' => 'q\\ZF', + 'r\\ZF' => 'r\\ZF', + 's\\ZF' => 's\\ZF', + 't\\ZF' => 't\\ZF', + 'u\\ZF' => 'u\\ZF', + 'v\\ZF' => 'v\\ZF', + 'w\\ZF' => 'w\\ZF', + 'x\\ZF' => 'x\\ZF', + 'y\\ZF' => 'y\\ZF', + 'z\\ZF' => 'z\\ZF', + + 'ApigilityModuleInterface' => 'ApiToolsModuleInterface', + 'ApigilityProviderInterface' => 'ApiToolsProviderInterface', + 'ApigilityVersionController' => 'ApiToolsVersionController', + + // PACKAGES + // ZF components, MVC + 'zendframework/skeleton-application' => 'laminas/skeleton-application', + 'zendframework/zend-auradi-config' => 'laminas/laminas-auradi-config', + 'zendframework/zend-authentication' => 'laminas/laminas-authentication', + 'zendframework/zend-barcode' => 'laminas/laminas-barcode', + 'zendframework/zend-cache' => 'laminas/laminas-cache', + 'zendframework/zend-captcha' => 'laminas/laminas-captcha', + 'zendframework/zend-code' => 'laminas/laminas-code', + 'zendframework/zend-coding-standard' => 'laminas/laminas-coding-standard', + 'zendframework/zend-component-installer' => 'laminas/laminas-component-installer', + 'zendframework/zend-composer-autoloading' => 'laminas/laminas-composer-autoloading', + 'zendframework/zend-config-aggregator' => 'laminas/laminas-config-aggregator', + 'zendframework/zend-config' => 'laminas/laminas-config', + 'zendframework/zend-console' => 'laminas/laminas-console', + 'zendframework/zend-container-config-test' => 'laminas/laminas-container-config-test', + 'zendframework/zend-crypt' => 'laminas/laminas-crypt', + 'zendframework/zend-db' => 'laminas/laminas-db', + 'zendframework/zend-developer-tools' => 'laminas/laminas-developer-tools', + 'zendframework/zend-diactoros' => 'laminas/laminas-diactoros', + 'zendframework/zenddiagnostics' => 'laminas/laminas-diagnostics', + 'zendframework/zend-di' => 'laminas/laminas-di', + 'zendframework/zend-dom' => 'laminas/laminas-dom', + 'zendframework/zend-escaper' => 'laminas/laminas-escaper', + 'zendframework/zend-eventmanager' => 'laminas/laminas-eventmanager', + 'zendframework/zend-feed' => 'laminas/laminas-feed', + 'zendframework/zend-file' => 'laminas/laminas-file', + 'zendframework/zend-filter' => 'laminas/laminas-filter', + 'zendframework/zend-form' => 'laminas/laminas-form', + 'zendframework/zend-httphandlerrunner' => 'laminas/laminas-httphandlerrunner', + 'zendframework/zend-http' => 'laminas/laminas-http', + 'zendframework/zend-hydrator' => 'laminas/laminas-hydrator', + 'zendframework/zend-i18n' => 'laminas/laminas-i18n', + 'zendframework/zend-i18n-resources' => 'laminas/laminas-i18n-resources', + 'zendframework/zend-inputfilter' => 'laminas/laminas-inputfilter', + 'zendframework/zend-json' => 'laminas/laminas-json', + 'zendframework/zend-json-server' => 'laminas/laminas-json-server', + 'zendframework/zend-ldap' => 'laminas/laminas-ldap', + 'zendframework/zend-loader' => 'laminas/laminas-loader', + 'zendframework/zend-log' => 'laminas/laminas-log', + 'zendframework/zend-mail' => 'laminas/laminas-mail', + 'zendframework/zend-math' => 'laminas/laminas-math', + 'zendframework/zend-memory' => 'laminas/laminas-memory', + 'zendframework/zend-mime' => 'laminas/laminas-mime', + 'zendframework/zend-modulemanager' => 'laminas/laminas-modulemanager', + 'zendframework/zend-mvc' => 'laminas/laminas-mvc', + 'zendframework/zend-navigation' => 'laminas/laminas-navigation', + 'zendframework/zend-oauth' => 'laminas/laminas-oauth', + 'zendframework/zend-paginator' => 'laminas/laminas-paginator', + 'zendframework/zend-permissions-acl' => 'laminas/laminas-permissions-acl', + 'zendframework/zend-permissions-rbac' => 'laminas/laminas-permissions-rbac', + 'zendframework/zend-pimple-config' => 'laminas/laminas-pimple-config', + 'zendframework/zend-progressbar' => 'laminas/laminas-progressbar', + 'zendframework/zend-psr7bridge' => 'laminas/laminas-psr7bridge', + 'zendframework/zend-recaptcha' => 'laminas/laminas-recaptcha', + 'zendframework/zend-router' => 'laminas/laminas-router', + 'zendframework/zend-serializer' => 'laminas/laminas-serializer', + 'zendframework/zend-server' => 'laminas/laminas-server', + 'zendframework/zend-servicemanager' => 'laminas/laminas-servicemanager', + 'zendframework/zendservice-recaptcha' => 'laminas/laminas-recaptcha', + 'zendframework/zendservice-twitter' => 'laminas/laminas-twitter', + 'zendframework/zend-session' => 'laminas/laminas-session', + 'zendframework/zend-skeleton-installer' => 'laminas/laminas-skeleton-installer', + 'zendframework/zend-soap' => 'laminas/laminas-soap', + 'zendframework/zend-stdlib' => 'laminas/laminas-stdlib', + 'zendframework/zend-stratigility' => 'laminas/laminas-stratigility', + 'zendframework/zend-tag' => 'laminas/laminas-tag', + 'zendframework/zend-test' => 'laminas/laminas-test', + 'zendframework/zend-text' => 'laminas/laminas-text', + 'zendframework/zend-uri' => 'laminas/laminas-uri', + 'zendframework/zend-validator' => 'laminas/laminas-validator', + 'zendframework/zend-view' => 'laminas/laminas-view', + 'zendframework/zend-xml2json' => 'laminas/laminas-xml2json', + 'zendframework/zend-xml' => 'laminas/laminas-xml', + 'zendframework/zend-xmlrpc' => 'laminas/laminas-xmlrpc', + + // Expressive packages + 'zendframework/zend-expressive' => 'mezzio/mezzio', + 'zendframework/zend-expressive-zendrouter' => 'mezzio/mezzio-laminasrouter', + 'zendframework/zend-problem-details' => 'mezzio/mezzio-problem-details', + 'zendframework/zend-expressive-zendviewrenderer' => 'mezzio/mezzio-laminasviewrenderer', + + // Apigility packages + 'zfcampus/apigility-documentation' => 'laminas-api-tools/documentation', + 'zfcampus/statuslib-example' => 'laminas-api-tools/statuslib-example', + 'zfcampus/zf-apigility' => 'laminas-api-tools/api-tools', + 'zfcampus/zf-api-problem' => 'laminas-api-tools/api-tools-api-problem', + 'zfcampus/zf-asset-manager' => 'laminas-api-tools/api-tools-asset-manager', + 'zfcampus/zf-configuration' => 'laminas-api-tools/api-tools-configuration', + 'zfcampus/zf-content-negotiation' => 'laminas-api-tools/api-tools-content-negotiation', + 'zfcampus/zf-content-validation' => 'laminas-api-tools/api-tools-content-validation', + 'zfcampus/zf-development-mode' => 'laminas/laminas-development-mode', + 'zfcampus/zf-doctrine-querybuilder' => 'laminas-api-tools/api-tools-doctrine-querybuilder', + 'zfcampus/zf-hal' => 'laminas-api-tools/api-tools-hal', + 'zfcampus/zf-http-cache' => 'laminas-api-tools/api-tools-http-cache', + 'zfcampus/zf-mvc-auth' => 'laminas-api-tools/api-tools-mvc-auth', + 'zfcampus/zf-oauth2' => 'laminas-api-tools/api-tools-oauth2', + 'zfcampus/zf-rest' => 'laminas-api-tools/api-tools-rest', + 'zfcampus/zf-rpc' => 'laminas-api-tools/api-tools-rpc', + 'zfcampus/zf-versioning' => 'laminas-api-tools/api-tools-versioning', + + // CONFIG KEYS, SCRIPT NAMES, ETC + // ZF components + '::fromZend' => '::fromLaminas', // psr7bridge + '::toZend' => '::toLaminas', // psr7bridge + 'use_zend_loader' => 'use_laminas_loader', // zend-modulemanager + 'zend-config' => 'laminas-config', + 'zend-developer-tools/' => 'laminas-developer-tools/', + 'zend-tag-cloud' => 'laminas-tag-cloud', + 'zenddevelopertools' => 'laminas-developer-tools', + 'zendbarcode' => 'laminasbarcode', + 'ZendBarcode' => 'LaminasBarcode', + 'zendcache' => 'laminascache', + 'ZendCache' => 'LaminasCache', + 'zendconfig' => 'laminasconfig', + 'ZendConfig' => 'LaminasConfig', + 'zendfeed' => 'laminasfeed', + 'ZendFeed' => 'LaminasFeed', + 'zendfilter' => 'laminasfilter', + 'ZendFilter' => 'LaminasFilter', + 'zendform' => 'laminasform', + 'ZendForm' => 'LaminasForm', + 'zendi18n' => 'laminasi18n', + 'ZendI18n' => 'LaminasI18n', + 'zendinputfilter' => 'laminasinputfilter', + 'ZendInputFilter' => 'LaminasInputFilter', + 'zendlog' => 'laminaslog', + 'ZendLog' => 'LaminasLog', + 'zendmail' => 'laminasmail', + 'ZendMail' => 'LaminasMail', + 'zendmvc' => 'laminasmvc', + 'ZendMvc' => 'LaminasMvc', + 'zendpaginator' => 'laminaspaginator', + 'ZendPaginator' => 'LaminasPaginator', + 'zendserializer' => 'laminasserializer', + 'ZendSerializer' => 'LaminasSerializer', + 'zendtag' => 'laminastag', + 'ZendTag' => 'LaminasTag', + 'zendtext' => 'laminastext', + 'ZendText' => 'LaminasText', + 'zendvalidator' => 'laminasvalidator', + 'ZendValidator' => 'LaminasValidator', + 'zendview' => 'laminasview', + 'ZendView' => 'LaminasView', + 'zend-framework.flf' => 'laminas-project.flf', + + // Expressive-related + "'zend-expressive'" => "'mezzio'", + '"zend-expressive"' => '"mezzio"', + 'zend-expressive.' => 'mezzio.', + 'zend-expressive-authorization' => 'mezzio-authorization', + 'zend-expressive-hal' => 'mezzio-hal', + 'zend-expressive-session' => 'mezzio-session', + 'zend-expressive-swoole' => 'mezzio-swoole', + 'zend-expressive-tooling' => 'mezzio-tooling', + + // Apigility-related + "'zf-apigility'" => "'api-tools'", + '"zf-apigility"' => '"api-tools"', + 'zf-apigility/' => 'api-tools/', + 'zf-apigility-admin' => 'api-tools-admin', + 'zf-content-negotiation' => 'api-tools-content-negotiation', + 'zf-hal' => 'api-tools-hal', + 'zf-rest' => 'api-tools-rest', + 'zf-rpc' => 'api-tools-rpc', + 'zf-content-validation' => 'api-tools-content-validation', + 'zf-apigility-ui' => 'api-tools-ui', + 'zf-apigility-documentation-blueprint' => 'api-tools-documentation-blueprint', + 'zf-apigility-documentation-swagger' => 'api-tools-documentation-swagger', + 'zf-apigility-welcome' => 'api-tools-welcome', + 'zf-api-problem' => 'api-tools-api-problem', + 'zf-configuration' => 'api-tools-configuration', + 'zf-http-cache' => 'api-tools-http-cache', + 'zf-mvc-auth' => 'api-tools-mvc-auth', + 'zf-oauth2' => 'api-tools-oauth2', + 'zf-versioning' => 'api-tools-versioning', + 'ZfApigilityDoctrineQueryProviderManager' => 'LaminasApiToolsDoctrineQueryProviderManager', + 'ZfApigilityDoctrineQueryCreateFilterManager' => 'LaminasApiToolsDoctrineQueryCreateFilterManager', + 'zf-apigility-doctrine' => 'api-tools-doctrine', + 'zf-development-mode' => 'laminas-development-mode', + 'zf-doctrine-querybuilder' => 'api-tools-doctrine-querybuilder', + + // 3rd party Apigility packages + 'api-skeletons/zf-' => 'api-skeletons/zf-', // api-skeletons packages + 'zf-oauth2-' => 'zf-oauth2-', // api-skeletons OAuth2-related packages + 'ZF\\OAuth2\\Client' => 'ZF\\OAuth2\\Client', // api-skeletons/zf-oauth2-client + 'ZF\\OAuth2\\Doctrine' => 'ZF\\OAuth2\\Doctrine', // api-skeletons/zf-oauth2-doctrine +]; diff --git a/lib/laminas/laminas-zendframework-bridge/src/Autoloader.php b/lib/laminas/laminas-zendframework-bridge/src/Autoloader.php new file mode 100644 index 000000000..6048766a2 --- /dev/null +++ b/lib/laminas/laminas-zendframework-bridge/src/Autoloader.php @@ -0,0 +1,172 @@ +loadClass($class)) { + $legacy = $namespaces[$check] + . strtr(substr($class, strlen($check)), [ + 'ApiTools' => 'Apigility', + 'Mezzio' => 'Expressive', + 'Laminas' => 'Zend', + ]); + class_alias($class, $legacy); + } + }; + } + + /** + * @return callable + */ + private static function createAppendAutoloader(array $namespaces, ArrayObject $loaded) + { + /** + * @param string $class Class name to autoload + * @return void + */ + return static function ($class) use ($namespaces, $loaded) { + $segments = explode('\\', $class); + + if ($segments[0] === 'ZendService' && isset($segments[1])) { + $segments[0] .= '\\' . $segments[1]; + unset($segments[1]); + $segments = array_values($segments); + } + + $i = 0; + $check = ''; + + // We are checking segments of the namespace to match quicker + while (isset($segments[$i + 1], $namespaces[$check . $segments[$i] . '\\'])) { + $check .= $segments[$i] . '\\'; + ++$i; + } + + if ($check === '') { + return; + } + + $alias = $namespaces[$check] + . strtr(substr($class, strlen($check)), [ + 'Apigility' => 'ApiTools', + 'Expressive' => 'Mezzio', + 'Zend' => 'Laminas', + 'AbstractZendServer' => 'AbstractZendServer', + 'ZendServerDisk' => 'ZendServerDisk', + 'ZendServerShm' => 'ZendServerShm', + 'ZendMonitor' => 'ZendMonitor', + ]); + + $loaded[$alias] = true; + if (class_exists($alias) || interface_exists($alias) || trait_exists($alias)) { + class_alias($alias, $class); + } + }; + } +} diff --git a/lib/laminas/laminas-zendframework-bridge/src/ConfigPostProcessor.php b/lib/laminas/laminas-zendframework-bridge/src/ConfigPostProcessor.php new file mode 100644 index 000000000..bac7b9747 --- /dev/null +++ b/lib/laminas/laminas-zendframework-bridge/src/ConfigPostProcessor.php @@ -0,0 +1,434 @@ + true, + 'factories' => true, + 'invokables' => true, + 'services' => true, + ]; + + /** @var array String keys => string values */ + private $exactReplacements = [ + 'zend-expressive' => 'mezzio', + 'zf-apigility' => 'api-tools', + ]; + + /** @var Replacements */ + private $replacements; + + /** @var callable[] */ + private $rulesets; + + public function __construct() + { + $this->replacements = new Replacements(); + + /* Define the rulesets for replacements. + * + * Each ruleset has the following signature: + * + * @param mixed $value + * @param string[] $keys Full nested key hierarchy leading to the value + * @return null|callable + * + * If no match is made, a null is returned, allowing it to fallback to + * the next ruleset in the list. If a match is made, a callback is returned, + * and that will be used to perform the replacement on the value. + * + * The callback should have the following signature: + * + * @param mixed $value + * @param string[] $keys + * @return mixed The transformed value + */ + $this->rulesets = [ + // Exact values + function ($value) { + return is_string($value) && isset($this->exactReplacements[$value]) + ? [$this, 'replaceExactValue'] + : null; + }, + + // Router (MVC applications) + // We do not want to rewrite these. + function ($value, array $keys) { + $key = array_pop($keys); + // Only worried about a top-level "router" key. + return $key === 'router' && count($keys) === 0 && is_array($value) + ? [$this, 'noopReplacement'] + : null; + }, + + // service- and pluginmanager handling + function ($value) { + return is_array($value) && array_intersect_key(self::SERVICE_MANAGER_KEYS_OF_INTEREST, $value) !== [] + ? [$this, 'replaceDependencyConfiguration'] + : null; + }, + + // Array values + function ($value, array $keys) { + return 0 !== count($keys) && is_array($value) + ? [$this, '__invoke'] + : null; + }, + ]; + } + + /** + * @param string[] $keys Hierarchy of keys, for determining location in + * nested configuration. + * @return array + */ + public function __invoke(array $config, array $keys = []) + { + $rewritten = []; + + foreach ($config as $key => $value) { + // Determine new key from replacements + $newKey = is_string($key) ? $this->replace($key, $keys) : $key; + + // Keep original values with original key, if the key has changed, but only at the top-level. + if (empty($keys) && $newKey !== $key) { + $rewritten[$key] = $value; + } + + // Perform value replacements, if any + $newValue = $this->replace($value, $keys, $newKey); + + // Key does not already exist and/or is not an array value + if (! array_key_exists($newKey, $rewritten) || ! is_array($rewritten[$newKey])) { + // Do not overwrite existing values with null values + $rewritten[$newKey] = array_key_exists($newKey, $rewritten) && null === $newValue + ? $rewritten[$newKey] + : $newValue; + continue; + } + + // New value is null; nothing to do. + if (null === $newValue) { + continue; + } + + // Key already exists as an array value, but $value is not an array + if (! is_array($newValue)) { + $rewritten[$newKey][] = $newValue; + continue; + } + + // Key already exists as an array value, and $value is also an array + $rewritten[$newKey] = static::merge($rewritten[$newKey], $newValue); + } + + return $rewritten; + } + + /** + * Perform substitutions as needed on an individual value. + * + * The $key is provided to allow fine-grained selection of rewrite rules. + * + * @param mixed $value + * @param string[] $keys Key hierarchy + * @param null|int|string $key + * @return mixed + */ + private function replace($value, array $keys, $key = null) + { + // Add new key to the list of keys. + // We do not need to remove it later, as we are working on a copy of the array. + array_push($keys, $key); + + // Identify rewrite strategy and perform replacements + $rewriteRule = $this->replacementRuleMatch($value, $keys); + return $rewriteRule($value, $keys); + } + + /** + * Merge two arrays together. + * + * If an integer key exists in both arrays, the value from the second array + * will be appended to the first array. If both values are arrays, they are + * merged together, else the value of the second array overwrites the one + * of the first array. + * + * Based on zend-stdlib Zend\Stdlib\ArrayUtils::merge + * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) + * + * @return array + */ + public static function merge(array $a, array $b) + { + foreach ($b as $key => $value) { + if (! isset($a[$key]) && ! array_key_exists($key, $a)) { + $a[$key] = $value; + continue; + } + + if (null === $value && array_key_exists($key, $a)) { + // Leave as-is if value from $b is null + continue; + } + + if (is_int($key)) { + $a[] = $value; + continue; + } + + if (is_array($value) && is_array($a[$key])) { + $a[$key] = static::merge($a[$key], $value); + continue; + } + + $a[$key] = $value; + } + + return $a; + } + + /** + * @param mixed $value + * @param null|int|string $key + * @return callable Callable to invoke with value + */ + private function replacementRuleMatch($value, $key = null) + { + foreach ($this->rulesets as $ruleset) { + $result = $ruleset($value, $key); + if (is_callable($result)) { + return $result; + } + } + return [$this, 'fallbackReplacement']; + } + + /** + * Replace a value using the translation table, if the value is a string. + * + * @param mixed $value + * @return mixed + */ + private function fallbackReplacement($value) + { + return is_string($value) + ? $this->replacements->replace($value) + : $value; + } + + /** + * Replace a value matched exactly. + * + * @param mixed $value + * @return mixed + */ + private function replaceExactValue($value) + { + return $this->exactReplacements[$value]; + } + + private function replaceDependencyConfiguration(array $config) + { + $aliases = isset($config['aliases']) && is_array($config['aliases']) + ? $this->replaceDependencyAliases($config['aliases']) + : []; + + if ($aliases) { + $config['aliases'] = $aliases; + } + + $config = $this->replaceDependencyInvokables($config); + $config = $this->replaceDependencyFactories($config); + $config = $this->replaceDependencyServices($config); + + $keys = self::SERVICE_MANAGER_KEYS_OF_INTEREST; + foreach ($config as $key => $data) { + if (isset($keys[$key])) { + continue; + } + + $config[$key] = is_array($data) ? $this->__invoke($data, [$key]) : $data; + } + + return $config; + } + + /** + * Rewrite dependency aliases array + * + * In this case, we want to keep the alias as-is, but rewrite the target. + * + * We need also provide an additional alias if the alias key is a legacy class. + * + * @return array + */ + private function replaceDependencyAliases(array $aliases) + { + foreach ($aliases as $alias => $target) { + if (! is_string($alias) || ! is_string($target)) { + continue; + } + + $newTarget = $this->replacements->replace($target); + $newAlias = $this->replacements->replace($alias); + + $notIn = [$newTarget]; + $name = $newTarget; + while (isset($aliases[$name])) { + $notIn[] = $aliases[$name]; + $name = $aliases[$name]; + } + + if ($newAlias === $alias && ! in_array($alias, $notIn, true)) { + $aliases[$alias] = $newTarget; + continue; + } + + if (isset($aliases[$newAlias])) { + continue; + } + + if (! in_array($newAlias, $notIn, true)) { + $aliases[$alias] = $newAlias; + $aliases[$newAlias] = $newTarget; + } + } + + return $aliases; + } + + /** + * Rewrite dependency invokables array + * + * In this case, we want to keep the alias as-is, but rewrite the target. + * + * We need also provide an additional alias if invokable is defined with + * an alias which is a legacy class. + * + * @return array + */ + private function replaceDependencyInvokables(array $config) + { + if (empty($config['invokables']) || ! is_array($config['invokables'])) { + return $config; + } + + foreach ($config['invokables'] as $alias => $target) { + if (! is_string($alias)) { + continue; + } + + $newTarget = $this->replacements->replace($target); + $newAlias = $this->replacements->replace($alias); + + if ($alias === $target || isset($config['aliases'][$newAlias])) { + $config['invokables'][$alias] = $newTarget; + continue; + } + + $config['invokables'][$newAlias] = $newTarget; + + if ($newAlias === $alias) { + continue; + } + + $config['aliases'][$alias] = $newAlias; + + unset($config['invokables'][$alias]); + } + + return $config; + } + + /** + * @param mixed $value + * @return mixed Returns $value verbatim. + */ + private function noopReplacement($value) + { + return $value; + } + + private function replaceDependencyFactories(array $config) + { + if (empty($config['factories']) || ! is_array($config['factories'])) { + return $config; + } + + foreach ($config['factories'] as $service => $factory) { + if (! is_string($service)) { + continue; + } + + $replacedService = $this->replacements->replace($service); + $factory = is_string($factory) ? $this->replacements->replace($factory) : $factory; + $config['factories'][$replacedService] = $factory; + + if ($replacedService === $service) { + continue; + } + + unset($config['factories'][$service]); + if (isset($config['aliases'][$service])) { + continue; + } + + $config['aliases'][$service] = $replacedService; + } + + return $config; + } + + private function replaceDependencyServices(array $config) + { + if (empty($config['services']) || ! is_array($config['services'])) { + return $config; + } + + foreach ($config['services'] as $service => $serviceInstance) { + if (! is_string($service)) { + continue; + } + + $replacedService = $this->replacements->replace($service); + $serviceInstance = is_array($serviceInstance) ? $this->__invoke($serviceInstance) : $serviceInstance; + + $config['services'][$replacedService] = $serviceInstance; + + if ($service === $replacedService) { + continue; + } + + unset($config['services'][$service]); + + if (isset($config['aliases'][$service])) { + continue; + } + + $config['aliases'][$service] = $replacedService; + } + + return $config; + } +} diff --git a/lib/laminas/laminas-zendframework-bridge/src/Module.php b/lib/laminas/laminas-zendframework-bridge/src/Module.php new file mode 100644 index 000000000..d10cb43dd --- /dev/null +++ b/lib/laminas/laminas-zendframework-bridge/src/Module.php @@ -0,0 +1,54 @@ +getEventManager() + ->attach('mergeConfig', [$this, 'onMergeConfig']); + } + + /** + * Perform substitutions in the merged configuration. + * + * Rewrites keys and values matching known ZF classes, namespaces, and + * configuration keys to their Laminas equivalents. + * + * Type-hinting deliberately omitted to allow unit testing + * without dependencies on packages that do not exist yet. + * + * @param ModuleEvent $event + */ + public function onMergeConfig($event) + { + /** @var ConfigMergerInterface */ + $configMerger = $event->getConfigListener(); + $processor = new ConfigPostProcessor(); + $configMerger->setMergedConfig( + $processor( + $configMerger->getMergedConfig($returnAsObject = false) + ) + ); + } +} diff --git a/lib/laminas/laminas-zendframework-bridge/src/Replacements.php b/lib/laminas/laminas-zendframework-bridge/src/Replacements.php new file mode 100644 index 000000000..ca445c01f --- /dev/null +++ b/lib/laminas/laminas-zendframework-bridge/src/Replacements.php @@ -0,0 +1,46 @@ +replacements = array_merge( + require __DIR__ . '/../config/replacements.php', + $additionalReplacements + ); + + // Provide multiple variants of strings containing namespace separators + foreach ($this->replacements as $original => $replacement) { + if (false === strpos($original, '\\')) { + continue; + } + $this->replacements[str_replace('\\', '\\\\', $original)] = str_replace('\\', '\\\\', $replacement); + $this->replacements[str_replace('\\', '\\\\\\\\', $original)] = str_replace('\\', '\\\\\\\\', $replacement); + } + } + + /** + * @param string $value + * @return string + */ + public function replace($value) + { + return strtr($value, $this->replacements); + } +} diff --git a/lib/laminas/laminas-zendframework-bridge/src/RewriteRules.php b/lib/laminas/laminas-zendframework-bridge/src/RewriteRules.php new file mode 100644 index 000000000..8dc999f45 --- /dev/null +++ b/lib/laminas/laminas-zendframework-bridge/src/RewriteRules.php @@ -0,0 +1,79 @@ + 'Mezzio\\ProblemDetails\\', + 'Zend\\Expressive\\' => 'Mezzio\\', + + // Laminas + 'Zend\\' => 'Laminas\\', + 'ZF\\ComposerAutoloading\\' => 'Laminas\\ComposerAutoloading\\', + 'ZF\\DevelopmentMode\\' => 'Laminas\\DevelopmentMode\\', + + // Apigility + 'ZF\\Apigility\\' => 'Laminas\\ApiTools\\', + 'ZF\\' => 'Laminas\\ApiTools\\', + + // ZendXml, API wrappers, zend-http OAuth support, zend-diagnostics, ZendDeveloperTools + 'ZendXml\\' => 'Laminas\\Xml\\', + 'ZendOAuth\\' => 'Laminas\\OAuth\\', + 'ZendDiagnostics\\' => 'Laminas\\Diagnostics\\', + 'ZendService\\ReCaptcha\\' => 'Laminas\\ReCaptcha\\', + 'ZendService\\Twitter\\' => 'Laminas\\Twitter\\', + 'ZendDeveloperTools\\' => 'Laminas\\DeveloperTools\\', + ]; + } + + /** + * @return array + */ + public static function namespaceReverse() + { + return [ + // ZendXml, ZendOAuth, ZendDiagnostics, ZendDeveloperTools + 'Laminas\\Xml\\' => 'ZendXml\\', + 'Laminas\\OAuth\\' => 'ZendOAuth\\', + 'Laminas\\Diagnostics\\' => 'ZendDiagnostics\\', + 'Laminas\\DeveloperTools\\' => 'ZendDeveloperTools\\', + + // Zend Service + 'Laminas\\ReCaptcha\\' => 'ZendService\\ReCaptcha\\', + 'Laminas\\Twitter\\' => 'ZendService\\Twitter\\', + + // Zend + 'Laminas\\' => 'Zend\\', + + // Expressive + 'Mezzio\\ProblemDetails\\' => 'Zend\\ProblemDetails\\', + 'Mezzio\\' => 'Zend\\Expressive\\', + + // Laminas to ZfCampus + 'Laminas\\ComposerAutoloading\\' => 'ZF\\ComposerAutoloading\\', + 'Laminas\\DevelopmentMode\\' => 'ZF\\DevelopmentMode\\', + + // Apigility + 'Laminas\\ApiTools\\Admin\\' => 'ZF\\Apigility\\Admin\\', + 'Laminas\\ApiTools\\Doctrine\\' => 'ZF\\Apigility\\Doctrine\\', + 'Laminas\\ApiTools\\Documentation\\' => 'ZF\\Apigility\\Documentation\\', + 'Laminas\\ApiTools\\Example\\' => 'ZF\\Apigility\\Example\\', + 'Laminas\\ApiTools\\Provider\\' => 'ZF\\Apigility\\Provider\\', + 'Laminas\\ApiTools\\Welcome\\' => 'ZF\\Apiglity\\Welcome\\', + 'Laminas\\ApiTools\\' => 'ZF\\', + ]; + } +} diff --git a/lib/laminas/laminas-zendframework-bridge/src/autoload.php b/lib/laminas/laminas-zendframework-bridge/src/autoload.php new file mode 100644 index 000000000..9f2f2adf8 --- /dev/null +++ b/lib/laminas/laminas-zendframework-bridge/src/autoload.php @@ -0,0 +1,9 @@ +setRules(array( - '@Symfony' => true, - '@Symfony:risky' => true, - 'array_syntax' => array('syntax' => 'long'), - 'no_unreachable_default_argument_value' => false, - 'braces' => array('allow_single_line_closure' => true), - 'heredoc_to_nowdoc' => false, - 'phpdoc_annotation_without_dot' => false, - )) - ->setRiskyAllowed(true) - ->setFinder(PhpCsFixer\Finder::create()->in(__DIR__)) -; diff --git a/lib/swiftmailer/swiftmailer/.travis.yml b/lib/swiftmailer/swiftmailer/.travis.yml deleted file mode 100644 index fc24d05e8..000000000 --- a/lib/swiftmailer/swiftmailer/.travis.yml +++ /dev/null @@ -1,31 +0,0 @@ -language: php - -sudo: false - -before_script: - - cp tests/acceptance.conf.php.default tests/acceptance.conf.php - - cp tests/smoke.conf.php.default tests/smoke.conf.php - - composer self-update - - composer update --no-interaction --prefer-source - - gem install mime-types -v 2.99.1 - - gem install mailcatcher - - mailcatcher --smtp-port 4456 - -script: ./vendor/bin/simple-phpunit - -matrix: - include: - - php: 5.3 - - php: 5.4 - - php: 5.5 - - php: 5.6 - - php: 7.0 - - php: 7.1 - - php: hhvm - allow_failures: - - php: hhvm - fast_finish: true - -cache: - directories: - - .phpunit diff --git a/lib/swiftmailer/swiftmailer/CHANGES b/lib/swiftmailer/swiftmailer/CHANGES deleted file mode 100644 index 3532ec2dc..000000000 --- a/lib/swiftmailer/swiftmailer/CHANGES +++ /dev/null @@ -1,287 +0,0 @@ -Changelog -========= - -5.4.12 (2018-07-31) -------------------- - - * fixed typo - -5.4.11 (2018-07-31) -------------------- - - * fixed startTLS support for PHP 5.6- - -5.4.10 (2018-07-27) -------------------- - - * fixed startTLS only allowed tls1.0, now allowed: tls1.0, tls1.1, tls1.2 - -5.4.9 (2018-01-23) ------------------- - - * no changes, last version of the 5.x series - -5.4.8 (2017-05-01) ------------------- - - * fixed encoding inheritance in addPart() - * fixed sorting MIME children when their types are equal - -5.4.7 (2017-04-20) ------------------- - - * fixed NTLMAuthenticator clobbering bcmath scale - -5.4.6 (2017-02-13) ------------------- - - * removed exceptions thrown in destructors as they lead to fatal errors - * switched to use sha256 by default in DKIM as per the RFC - * fixed an 'Undefined variable: pipes' PHP notice - * fixed long To headers when using the mail transport - * fixed NTLMAuthenticator when no domain is passed with the username - * prevented fatal error during unserialization of a message - * fixed a PHP warning when sending a message that has a length of a multiple of 8192 - -5.4.5 (2016-12-29) ------------------- - - * SECURITY FIX: fixed CVE-2016-10074 by disallowing potentially unsafe shell characters - - Prior to 5.4.5, the mail transport (Swift_Transport_MailTransport) was vulnerable to passing - arbitrary shell arguments if the "From", "ReturnPath" or "Sender" header came - from a non-trusted source, potentially allowing Remote Code Execution - * deprecated the mail transport - -5.4.4 (2016-11-23) ------------------- - - * reverted escaping command-line args to mail (PHP mail() function already does it) - -5.4.3 (2016-07-08) ------------------- - - * fixed SimpleHeaderSet::has()/get() when the 0 index is removed - * removed the need to have mcrypt installed - * fixed broken MIME header encoding with quotes/colons and non-ascii chars - * allowed mail transport send for messages without To header - * fixed PHP 7 support - -5.4.2 (2016-05-01) ------------------- - - * fixed support for IPv6 sockets - * added auto-retry when sending messages from the memory spool - * fixed consecutive read calls in Swift_ByteStream_FileByteStream - * added support for iso-8859-15 encoding - * fixed PHP mail extra params on missing reversePath - * added methods to set custom stream context options - * fixed charset changes in QpContentEncoderProxy - * added return-path header to the ignoredHeaders list of DKIMSigner - * fixed crlf for subject using mail - * fixed add soft line break only when necessary - * fixed escaping command-line args to mail - -5.4.1 (2015-06-06) ------------------- - - * made Swiftmailer exceptions confirm to PHP base exception constructor signature - * fixed MAIL FROM & RCPT TO headers to be RFC compliant - -5.4.0 (2015-03-14) ------------------- - - * added the possibility to add extra certs to PKCS#7 signature - * fix base64 encoding with streams - * added a new RESULT_SPOOLED status for SpoolTransport - * fixed getBody() on attachments when called more than once - * removed dots from generated filenames in filespool - -5.3.1 (2014-12-05) ------------------- - - * fixed cloning of messages with attachments - -5.3.0 (2014-10-04) ------------------- - - * fixed cloning when using signers - * reverted removal of Swift_Encoding - * drop support for PHP 5.2.x - -5.2.2 (2014-09-20) ------------------- - - * fixed Japanese support - * fixed the memory spool when the message changes when in the pool - * added support for cloning messages - * fixed PHP warning in the redirect plugin - * changed the way to and cc-ed email are sent to only use one transaction - -5.2.1 (2014-06-13) ------------------- - - * SECURITY FIX: fixed CLI escaping when using sendmail as a transport - - Prior to 5.2.1, the sendmail transport (Swift_Transport_SendmailTransport) - was vulnerable to an arbitrary shell execution if the "From" header came - from a non-trusted source and no "Return-Path" is configured. - - * fixed parameter in DKIMSigner - * fixed compatibility with PHP < 5.4 - -5.2.0 (2014-05-08) ------------------- - - * fixed Swift_ByteStream_FileByteStream::read() to match to the specification - * fixed from-charset and to-charset arguments in mbstring_convert_encoding() usages - * fixed infinite loop in StreamBuffer - * fixed NullTransport to return the number of ignored emails instead of 0 - * Use phpunit and mockery for unit testing (realityking) - -5.1.0 (2014-03-18) ------------------- - - * fixed data writing to stream when sending large messages - * added support for libopendkim (https://github.com/xdecock/php-opendkim) - * merged SignedMessage and Message - * added Gmail XOAuth2 authentication - * updated the list of known mime types - * added NTLM authentication - -5.0.3 (2013-12-03) ------------------- - - * fixed double-dot bug - * fixed DKIM signer - -5.0.2 (2013-08-30) ------------------- - - * handled correct exception type while reading IoBuffer output - -5.0.1 (2013-06-17) ------------------- - - * changed the spool to only start the transport when a mail has to be sent - * fixed compatibility with PHP 5.2 - * fixed LICENSE file - -5.0.0 (2013-04-30) ------------------- - - * changed the license from LGPL to MIT - -4.3.1 (2013-04-11) ------------------- - - * removed usage of the native QP encoder when the charset is not UTF-8 - * fixed usage of uniqid to avoid collisions - * made a performance improvement when tokenizing large headers - * fixed usage of the PHP native QP encoder on PHP 5.4.7+ - -4.3.0 (2013-01-08) ------------------- - - * made the temporary directory configurable via the TMPDIR env variable - * added S/MIME signer and encryption support - -4.2.2 (2012-10-25) ------------------- - - * added the possibility to throttle messages per second in ThrottlerPlugin (mostly for Amazon SES) - * switched mime.qpcontentencoder to automatically use the PHP native encoder on PHP 5.4.7+ - * allowed specifying a whitelist with regular expressions in RedirectingPlugin - -4.2.1 (2012-07-13) ------------------- - - * changed the coding standards to PSR-1/2 - * fixed issue with autoloading - * added NativeQpContentEncoder to enhance performance (for PHP 5.3+) - -4.2.0 (2012-06-29) ------------------- - - * added documentation about how to use the Japanese support introduced in 4.1.8 - * added a way to override the default configuration in a lazy way - * changed the PEAR init script to lazy-load the initialization - * fixed a bug when calling Swift_Preferences before anything else (regression introduced in 4.1.8) - -4.1.8 (2012-06-17) ------------------- - - * added Japanese iso-2022-jp support - * changed the init script to lazy-load the initialization - * fixed docblocks (@id) which caused some problems with libraries parsing the dobclocks - * fixed Swift_Mime_Headers_IdentificationHeader::setId() when passed an array of ids - * fixed encoding of email addresses in headers - * added replacements setter to the Decorator plugin - -4.1.7 (2012-04-26) ------------------- - - * fixed QpEncoder safeMapShareId property - -4.1.6 (2012-03-23) ------------------- - - * reduced the size of serialized Messages - -4.1.5 (2012-01-04) ------------------- - - * enforced Swift_Spool::queueMessage() to return a Boolean - * made an optimization to the memory spool: start the transport only when required - * prevented stream_socket_client() from generating an error and throw a Swift_TransportException instead - * fixed a PHP warning when calling to mail() when safe_mode is off - * many doc tweaks - -4.1.4 (2011-12-16) ------------------- - - * added a memory spool (Swift_MemorySpool) - * fixed too many opened files when sending emails with attachments - -4.1.3 (2011-10-27) ------------------- - - * added STARTTLS support - * added missing @return tags on fluent methods - * added a MessageLogger plugin that logs all sent messages - * added composer.json - -4.1.2 (2011-09-13) ------------------- - - * fixed wrong detection of magic_quotes_runtime - * fixed fatal errors when no To or Subject header has been set - * fixed charset on parameter header continuations - * added documentation about how to install Swiftmailer from the PEAR channel - * fixed various typos and markup problem in the documentation - * fixed warning when cache directory does not exist - * fixed "slashes are escaped" bug - * changed require_once() to require() in autoload - -4.1.1 (2011-07-04) ------------------- - - * added missing file in PEAR package - -4.1.0 (2011-06-30) ------------------- - - * documentation has been converted to ReST - -4.1.0 RC1 (2011-06-17) ----------------------- - -New features: - - * changed the Decorator Plugin to allow replacements in all headers - * added Swift_Mime_Grammar and Swift_Validate to validate an email address - * modified the autoloader to lazy-initialize Swiftmailer - * removed Swift_Mailer::batchSend() - * added NullTransport - * added new plugins: RedirectingPlugin and ImpersonatePlugin - * added a way to send messages asynchronously (Spool) diff --git a/lib/swiftmailer/swiftmailer/LICENSE b/lib/swiftmailer/swiftmailer/LICENSE deleted file mode 100644 index 485f1d6d6..000000000 --- a/lib/swiftmailer/swiftmailer/LICENSE +++ /dev/null @@ -1,19 +0,0 @@ -Copyright (c) 2013-2016 Fabien Potencier - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is furnished -to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. diff --git a/lib/swiftmailer/swiftmailer/README b/lib/swiftmailer/swiftmailer/README deleted file mode 100644 index 52c075758..000000000 --- a/lib/swiftmailer/swiftmailer/README +++ /dev/null @@ -1,15 +0,0 @@ -Swift Mailer ------------- - -Swift Mailer is a component based mailing solution for PHP 5. -It is released under the MIT license. - -Homepage: https://swiftmailer.symfony.com/ -Documentation: https://swiftmailer.symfony.com/docs/introduction.html -Bugs: https://github.com/swiftmailer/swiftmailer/issues -Repository: https://github.com/swiftmailer/swiftmailer - -Swift Mailer is highly object-oriented by design and lends itself -to use in complex web application with a great deal of flexibility. - -For full details on usage, see the documentation. diff --git a/lib/swiftmailer/swiftmailer/VERSION b/lib/swiftmailer/swiftmailer/VERSION deleted file mode 100644 index 82a2d1d04..000000000 --- a/lib/swiftmailer/swiftmailer/VERSION +++ /dev/null @@ -1 +0,0 @@ -Swift-5.4.12 diff --git a/lib/swiftmailer/swiftmailer/composer.json b/lib/swiftmailer/swiftmailer/composer.json deleted file mode 100644 index 44a1050fa..000000000 --- a/lib/swiftmailer/swiftmailer/composer.json +++ /dev/null @@ -1,37 +0,0 @@ -{ - "name": "swiftmailer/swiftmailer", - "type": "library", - "description": "Swiftmailer, free feature-rich PHP mailer", - "keywords": ["mail","mailer","email"], - "homepage": "https://swiftmailer.symfony.com", - "license": "MIT", - "authors": [ - { - "name": "Chris Corbyn" - }, - { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - } - ], - "require": { - "php": ">=5.3.3" - }, - "require-dev": { - "mockery/mockery": "~0.9.1", - "symfony/phpunit-bridge": "~3.2" - }, - "autoload": { - "files": ["lib/swift_required.php"] - }, - "autoload-dev": { - "psr-0": { - "Swift_": "tests/unit" - } - }, - "extra": { - "branch-alias": { - "dev-master": "5.4-dev" - } - } -} diff --git a/lib/swiftmailer/swiftmailer/lib/classes/Swift.php b/lib/swiftmailer/swiftmailer/lib/classes/Swift.php deleted file mode 100644 index 82c381b73..000000000 --- a/lib/swiftmailer/swiftmailer/lib/classes/Swift.php +++ /dev/null @@ -1,80 +0,0 @@ -createDependenciesFor('mime.attachment') - ); - - $this->setBody($data); - $this->setFilename($filename); - if ($contentType) { - $this->setContentType($contentType); - } - } - - /** - * Create a new Attachment. - * - * @param string|Swift_OutputByteStream $data - * @param string $filename - * @param string $contentType - * - * @return Swift_Mime_Attachment - */ - public static function newInstance($data = null, $filename = null, $contentType = null) - { - return new self($data, $filename, $contentType); - } - - /** - * Create a new Attachment from a filesystem path. - * - * @param string $path - * @param string $contentType optional - * - * @return Swift_Mime_Attachment - */ - public static function fromPath($path, $contentType = null) - { - return self::newInstance()->setFile( - new Swift_ByteStream_FileByteStream($path), - $contentType - ); - } -} diff --git a/lib/swiftmailer/swiftmailer/lib/classes/Swift/ByteStream/AbstractFilterableInputStream.php b/lib/swiftmailer/swiftmailer/lib/classes/Swift/ByteStream/AbstractFilterableInputStream.php deleted file mode 100644 index a7b0e3a62..000000000 --- a/lib/swiftmailer/swiftmailer/lib/classes/Swift/ByteStream/AbstractFilterableInputStream.php +++ /dev/null @@ -1,181 +0,0 @@ -_filters[$key] = $filter; - } - - /** - * Remove an already present StreamFilter based on its $key. - * - * @param string $key - */ - public function removeFilter($key) - { - unset($this->_filters[$key]); - } - - /** - * Writes $bytes to the end of the stream. - * - * @param string $bytes - * - * @throws Swift_IoException - * - * @return int - */ - public function write($bytes) - { - $this->_writeBuffer .= $bytes; - foreach ($this->_filters as $filter) { - if ($filter->shouldBuffer($this->_writeBuffer)) { - return; - } - } - $this->_doWrite($this->_writeBuffer); - - return ++$this->_sequence; - } - - /** - * For any bytes that are currently buffered inside the stream, force them - * off the buffer. - * - * @throws Swift_IoException - */ - public function commit() - { - $this->_doWrite($this->_writeBuffer); - } - - /** - * Attach $is to this stream. - * - * The stream acts as an observer, receiving all data that is written. - * All {@link write()} and {@link flushBuffers()} operations will be mirrored. - * - * @param Swift_InputByteStream $is - */ - public function bind(Swift_InputByteStream $is) - { - $this->_mirrors[] = $is; - } - - /** - * Remove an already bound stream. - * - * If $is is not bound, no errors will be raised. - * If the stream currently has any buffered data it will be written to $is - * before unbinding occurs. - * - * @param Swift_InputByteStream $is - */ - public function unbind(Swift_InputByteStream $is) - { - foreach ($this->_mirrors as $k => $stream) { - if ($is === $stream) { - if ($this->_writeBuffer !== '') { - $stream->write($this->_writeBuffer); - } - unset($this->_mirrors[$k]); - } - } - } - - /** - * Flush the contents of the stream (empty it) and set the internal pointer - * to the beginning. - * - * @throws Swift_IoException - */ - public function flushBuffers() - { - if ($this->_writeBuffer !== '') { - $this->_doWrite($this->_writeBuffer); - } - $this->_flush(); - - foreach ($this->_mirrors as $stream) { - $stream->flushBuffers(); - } - } - - /** Run $bytes through all filters */ - private function _filter($bytes) - { - foreach ($this->_filters as $filter) { - $bytes = $filter->filter($bytes); - } - - return $bytes; - } - - /** Just write the bytes to the stream */ - private function _doWrite($bytes) - { - $this->_commit($this->_filter($bytes)); - - foreach ($this->_mirrors as $stream) { - $stream->write($bytes); - } - - $this->_writeBuffer = ''; - } -} diff --git a/lib/swiftmailer/swiftmailer/lib/classes/Swift/ByteStream/ArrayByteStream.php b/lib/swiftmailer/swiftmailer/lib/classes/Swift/ByteStream/ArrayByteStream.php deleted file mode 100644 index ef05a6d5e..000000000 --- a/lib/swiftmailer/swiftmailer/lib/classes/Swift/ByteStream/ArrayByteStream.php +++ /dev/null @@ -1,182 +0,0 @@ -_array = $stack; - $this->_arraySize = count($stack); - } elseif (is_string($stack)) { - $this->write($stack); - } else { - $this->_array = array(); - } - } - - /** - * Reads $length bytes from the stream into a string and moves the pointer - * through the stream by $length. - * - * If less bytes exist than are requested the - * remaining bytes are given instead. If no bytes are remaining at all, boolean - * false is returned. - * - * @param int $length - * - * @return string - */ - public function read($length) - { - if ($this->_offset == $this->_arraySize) { - return false; - } - - // Don't use array slice - $end = $length + $this->_offset; - $end = $this->_arraySize < $end ? $this->_arraySize : $end; - $ret = ''; - for (; $this->_offset < $end; ++$this->_offset) { - $ret .= $this->_array[$this->_offset]; - } - - return $ret; - } - - /** - * Writes $bytes to the end of the stream. - * - * @param string $bytes - */ - public function write($bytes) - { - $to_add = str_split($bytes); - foreach ($to_add as $value) { - $this->_array[] = $value; - } - $this->_arraySize = count($this->_array); - - foreach ($this->_mirrors as $stream) { - $stream->write($bytes); - } - } - - /** - * Not used. - */ - public function commit() - { - } - - /** - * Attach $is to this stream. - * - * The stream acts as an observer, receiving all data that is written. - * All {@link write()} and {@link flushBuffers()} operations will be mirrored. - * - * @param Swift_InputByteStream $is - */ - public function bind(Swift_InputByteStream $is) - { - $this->_mirrors[] = $is; - } - - /** - * Remove an already bound stream. - * - * If $is is not bound, no errors will be raised. - * If the stream currently has any buffered data it will be written to $is - * before unbinding occurs. - * - * @param Swift_InputByteStream $is - */ - public function unbind(Swift_InputByteStream $is) - { - foreach ($this->_mirrors as $k => $stream) { - if ($is === $stream) { - unset($this->_mirrors[$k]); - } - } - } - - /** - * Move the internal read pointer to $byteOffset in the stream. - * - * @param int $byteOffset - * - * @return bool - */ - public function setReadPointer($byteOffset) - { - if ($byteOffset > $this->_arraySize) { - $byteOffset = $this->_arraySize; - } elseif ($byteOffset < 0) { - $byteOffset = 0; - } - - $this->_offset = $byteOffset; - } - - /** - * Flush the contents of the stream (empty it) and set the internal pointer - * to the beginning. - */ - public function flushBuffers() - { - $this->_offset = 0; - $this->_array = array(); - $this->_arraySize = 0; - - foreach ($this->_mirrors as $stream) { - $stream->flushBuffers(); - } - } -} diff --git a/lib/swiftmailer/swiftmailer/lib/classes/Swift/ByteStream/FileByteStream.php b/lib/swiftmailer/swiftmailer/lib/classes/Swift/ByteStream/FileByteStream.php deleted file mode 100644 index 9ed852310..000000000 --- a/lib/swiftmailer/swiftmailer/lib/classes/Swift/ByteStream/FileByteStream.php +++ /dev/null @@ -1,231 +0,0 @@ -_path = $path; - $this->_mode = $writable ? 'w+b' : 'rb'; - - if (function_exists('get_magic_quotes_runtime') && @get_magic_quotes_runtime() == 1) { - $this->_quotes = true; - } - } - - /** - * Get the complete path to the file. - * - * @return string - */ - public function getPath() - { - return $this->_path; - } - - /** - * Reads $length bytes from the stream into a string and moves the pointer - * through the stream by $length. - * - * If less bytes exist than are requested the - * remaining bytes are given instead. If no bytes are remaining at all, boolean - * false is returned. - * - * @param int $length - * - * @throws Swift_IoException - * - * @return string|bool - */ - public function read($length) - { - $fp = $this->_getReadHandle(); - if (!feof($fp)) { - if ($this->_quotes) { - ini_set('magic_quotes_runtime', 0); - } - $bytes = fread($fp, $length); - if ($this->_quotes) { - ini_set('magic_quotes_runtime', 1); - } - $this->_offset = ftell($fp); - - // If we read one byte after reaching the end of the file - // feof() will return false and an empty string is returned - if ($bytes === '' && feof($fp)) { - $this->_resetReadHandle(); - - return false; - } - - return $bytes; - } - - $this->_resetReadHandle(); - - return false; - } - - /** - * Move the internal read pointer to $byteOffset in the stream. - * - * @param int $byteOffset - * - * @return bool - */ - public function setReadPointer($byteOffset) - { - if (isset($this->_reader)) { - $this->_seekReadStreamToPosition($byteOffset); - } - $this->_offset = $byteOffset; - } - - /** Just write the bytes to the file */ - protected function _commit($bytes) - { - fwrite($this->_getWriteHandle(), $bytes); - $this->_resetReadHandle(); - } - - /** Not used */ - protected function _flush() - { - } - - /** Get the resource for reading */ - private function _getReadHandle() - { - if (!isset($this->_reader)) { - $pointer = @fopen($this->_path, 'rb'); - if (!$pointer) { - throw new Swift_IoException( - 'Unable to open file for reading ['.$this->_path.']' - ); - } - $this->_reader = $pointer; - if ($this->_offset != 0) { - $this->_getReadStreamSeekableStatus(); - $this->_seekReadStreamToPosition($this->_offset); - } - } - - return $this->_reader; - } - - /** Get the resource for writing */ - private function _getWriteHandle() - { - if (!isset($this->_writer)) { - if (!$this->_writer = fopen($this->_path, $this->_mode)) { - throw new Swift_IoException( - 'Unable to open file for writing ['.$this->_path.']' - ); - } - } - - return $this->_writer; - } - - /** Force a reload of the resource for reading */ - private function _resetReadHandle() - { - if (isset($this->_reader)) { - fclose($this->_reader); - $this->_reader = null; - } - } - - /** Check if ReadOnly Stream is seekable */ - private function _getReadStreamSeekableStatus() - { - $metas = stream_get_meta_data($this->_reader); - $this->_seekable = $metas['seekable']; - } - - /** Streams in a readOnly stream ensuring copy if needed */ - private function _seekReadStreamToPosition($offset) - { - if ($this->_seekable === null) { - $this->_getReadStreamSeekableStatus(); - } - if ($this->_seekable === false) { - $currentPos = ftell($this->_reader); - if ($currentPos < $offset) { - $toDiscard = $offset - $currentPos; - fread($this->_reader, $toDiscard); - - return; - } - $this->_copyReadStream(); - } - fseek($this->_reader, $offset, SEEK_SET); - } - - /** Copy a readOnly Stream to ensure seekability */ - private function _copyReadStream() - { - if ($tmpFile = fopen('php://temp/maxmemory:4096', 'w+b')) { - /* We have opened a php:// Stream Should work without problem */ - } elseif (function_exists('sys_get_temp_dir') && is_writable(sys_get_temp_dir()) && ($tmpFile = tmpfile())) { - /* We have opened a tmpfile */ - } else { - throw new Swift_IoException('Unable to copy the file to make it seekable, sys_temp_dir is not writable, php://memory not available'); - } - $currentPos = ftell($this->_reader); - fclose($this->_reader); - $source = fopen($this->_path, 'rb'); - if (!$source) { - throw new Swift_IoException('Unable to open file for copying ['.$this->_path.']'); - } - fseek($tmpFile, 0, SEEK_SET); - while (!feof($source)) { - fwrite($tmpFile, fread($source, 4096)); - } - fseek($tmpFile, $currentPos, SEEK_SET); - fclose($source); - $this->_reader = $tmpFile; - } -} diff --git a/lib/swiftmailer/swiftmailer/lib/classes/Swift/ByteStream/TemporaryFileByteStream.php b/lib/swiftmailer/swiftmailer/lib/classes/Swift/ByteStream/TemporaryFileByteStream.php deleted file mode 100644 index 1c9a80c03..000000000 --- a/lib/swiftmailer/swiftmailer/lib/classes/Swift/ByteStream/TemporaryFileByteStream.php +++ /dev/null @@ -1,42 +0,0 @@ -getPath())) === false) { - throw new Swift_IoException('Failed to get temporary file content.'); - } - - return $content; - } - - public function __destruct() - { - if (file_exists($this->getPath())) { - @unlink($this->getPath()); - } - } -} diff --git a/lib/swiftmailer/swiftmailer/lib/classes/Swift/CharacterReader.php b/lib/swiftmailer/swiftmailer/lib/classes/Swift/CharacterReader.php deleted file mode 100644 index 4267adbc5..000000000 --- a/lib/swiftmailer/swiftmailer/lib/classes/Swift/CharacterReader.php +++ /dev/null @@ -1,67 +0,0 @@ - - */ -interface Swift_CharacterReader -{ - const MAP_TYPE_INVALID = 0x01; - const MAP_TYPE_FIXED_LEN = 0x02; - const MAP_TYPE_POSITIONS = 0x03; - - /** - * Returns the complete character map. - * - * @param string $string - * @param int $startOffset - * @param array $currentMap - * @param mixed $ignoredChars - * - * @return int - */ - public function getCharPositions($string, $startOffset, &$currentMap, &$ignoredChars); - - /** - * Returns the mapType, see constants. - * - * @return int - */ - public function getMapType(); - - /** - * Returns an integer which specifies how many more bytes to read. - * - * A positive integer indicates the number of more bytes to fetch before invoking - * this method again. - * - * A value of zero means this is already a valid character. - * A value of -1 means this cannot possibly be a valid character. - * - * @param int[] $bytes - * @param int $size - * - * @return int - */ - public function validateByteSequence($bytes, $size); - - /** - * Returns the number of bytes which should be read to start each character. - * - * For fixed width character sets this should be the number of octets-per-character. - * For multibyte character sets this will probably be 1. - * - * @return int - */ - public function getInitialByteSize(); -} diff --git a/lib/swiftmailer/swiftmailer/lib/classes/Swift/CharacterReader/GenericFixedWidthReader.php b/lib/swiftmailer/swiftmailer/lib/classes/Swift/CharacterReader/GenericFixedWidthReader.php deleted file mode 100644 index 6a18e1dd1..000000000 --- a/lib/swiftmailer/swiftmailer/lib/classes/Swift/CharacterReader/GenericFixedWidthReader.php +++ /dev/null @@ -1,97 +0,0 @@ - - */ -class Swift_CharacterReader_GenericFixedWidthReader implements Swift_CharacterReader -{ - /** - * The number of bytes in a single character. - * - * @var int - */ - private $_width; - - /** - * Creates a new GenericFixedWidthReader using $width bytes per character. - * - * @param int $width - */ - public function __construct($width) - { - $this->_width = $width; - } - - /** - * Returns the complete character map. - * - * @param string $string - * @param int $startOffset - * @param array $currentMap - * @param mixed $ignoredChars - * - * @return int - */ - public function getCharPositions($string, $startOffset, &$currentMap, &$ignoredChars) - { - $strlen = strlen($string); - // % and / are CPU intensive, so, maybe find a better way - $ignored = $strlen % $this->_width; - $ignoredChars = $ignored ? substr($string, -$ignored) : ''; - $currentMap = $this->_width; - - return ($strlen - $ignored) / $this->_width; - } - - /** - * Returns the mapType. - * - * @return int - */ - public function getMapType() - { - return self::MAP_TYPE_FIXED_LEN; - } - - /** - * Returns an integer which specifies how many more bytes to read. - * - * A positive integer indicates the number of more bytes to fetch before invoking - * this method again. - * - * A value of zero means this is already a valid character. - * A value of -1 means this cannot possibly be a valid character. - * - * @param string $bytes - * @param int $size - * - * @return int - */ - public function validateByteSequence($bytes, $size) - { - $needed = $this->_width - $size; - - return $needed > -1 ? $needed : -1; - } - - /** - * Returns the number of bytes which should be read to start each character. - * - * @return int - */ - public function getInitialByteSize() - { - return $this->_width; - } -} diff --git a/lib/swiftmailer/swiftmailer/lib/classes/Swift/CharacterReader/UsAsciiReader.php b/lib/swiftmailer/swiftmailer/lib/classes/Swift/CharacterReader/UsAsciiReader.php deleted file mode 100644 index 67da48f6c..000000000 --- a/lib/swiftmailer/swiftmailer/lib/classes/Swift/CharacterReader/UsAsciiReader.php +++ /dev/null @@ -1,84 +0,0 @@ - "\x07F") { - // Invalid char - $currentMap[$i + $startOffset] = $string[$i]; - } - } - - return $strlen; - } - - /** - * Returns mapType. - * - * @return int mapType - */ - public function getMapType() - { - return self::MAP_TYPE_INVALID; - } - - /** - * Returns an integer which specifies how many more bytes to read. - * - * A positive integer indicates the number of more bytes to fetch before invoking - * this method again. - * A value of zero means this is already a valid character. - * A value of -1 means this cannot possibly be a valid character. - * - * @param string $bytes - * @param int $size - * - * @return int - */ - public function validateByteSequence($bytes, $size) - { - $byte = reset($bytes); - if (1 == count($bytes) && $byte >= 0x00 && $byte <= 0x7F) { - return 0; - } - - return -1; - } - - /** - * Returns the number of bytes which should be read to start each character. - * - * @return int - */ - public function getInitialByteSize() - { - return 1; - } -} diff --git a/lib/swiftmailer/swiftmailer/lib/classes/Swift/CharacterReader/Utf8Reader.php b/lib/swiftmailer/swiftmailer/lib/classes/Swift/CharacterReader/Utf8Reader.php deleted file mode 100644 index 22746bd85..000000000 --- a/lib/swiftmailer/swiftmailer/lib/classes/Swift/CharacterReader/Utf8Reader.php +++ /dev/null @@ -1,176 +0,0 @@ - - */ -class Swift_CharacterReader_Utf8Reader implements Swift_CharacterReader -{ - /** Pre-computed for optimization */ - private static $length_map = array( - // N=0,1,2,3,4,5,6,7,8,9,A,B,C,D,E,F, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0x0N - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0x1N - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0x2N - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0x3N - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0x4N - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0x5N - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0x6N - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0x7N - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 0x8N - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 0x9N - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 0xAN - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 0xBN - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, // 0xCN - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, // 0xDN - 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, // 0xEN - 4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 6, 6, 0, 0, // 0xFN - ); - - private static $s_length_map = array( - "\x00" => 1, "\x01" => 1, "\x02" => 1, "\x03" => 1, "\x04" => 1, "\x05" => 1, "\x06" => 1, "\x07" => 1, - "\x08" => 1, "\x09" => 1, "\x0a" => 1, "\x0b" => 1, "\x0c" => 1, "\x0d" => 1, "\x0e" => 1, "\x0f" => 1, - "\x10" => 1, "\x11" => 1, "\x12" => 1, "\x13" => 1, "\x14" => 1, "\x15" => 1, "\x16" => 1, "\x17" => 1, - "\x18" => 1, "\x19" => 1, "\x1a" => 1, "\x1b" => 1, "\x1c" => 1, "\x1d" => 1, "\x1e" => 1, "\x1f" => 1, - "\x20" => 1, "\x21" => 1, "\x22" => 1, "\x23" => 1, "\x24" => 1, "\x25" => 1, "\x26" => 1, "\x27" => 1, - "\x28" => 1, "\x29" => 1, "\x2a" => 1, "\x2b" => 1, "\x2c" => 1, "\x2d" => 1, "\x2e" => 1, "\x2f" => 1, - "\x30" => 1, "\x31" => 1, "\x32" => 1, "\x33" => 1, "\x34" => 1, "\x35" => 1, "\x36" => 1, "\x37" => 1, - "\x38" => 1, "\x39" => 1, "\x3a" => 1, "\x3b" => 1, "\x3c" => 1, "\x3d" => 1, "\x3e" => 1, "\x3f" => 1, - "\x40" => 1, "\x41" => 1, "\x42" => 1, "\x43" => 1, "\x44" => 1, "\x45" => 1, "\x46" => 1, "\x47" => 1, - "\x48" => 1, "\x49" => 1, "\x4a" => 1, "\x4b" => 1, "\x4c" => 1, "\x4d" => 1, "\x4e" => 1, "\x4f" => 1, - "\x50" => 1, "\x51" => 1, "\x52" => 1, "\x53" => 1, "\x54" => 1, "\x55" => 1, "\x56" => 1, "\x57" => 1, - "\x58" => 1, "\x59" => 1, "\x5a" => 1, "\x5b" => 1, "\x5c" => 1, "\x5d" => 1, "\x5e" => 1, "\x5f" => 1, - "\x60" => 1, "\x61" => 1, "\x62" => 1, "\x63" => 1, "\x64" => 1, "\x65" => 1, "\x66" => 1, "\x67" => 1, - "\x68" => 1, "\x69" => 1, "\x6a" => 1, "\x6b" => 1, "\x6c" => 1, "\x6d" => 1, "\x6e" => 1, "\x6f" => 1, - "\x70" => 1, "\x71" => 1, "\x72" => 1, "\x73" => 1, "\x74" => 1, "\x75" => 1, "\x76" => 1, "\x77" => 1, - "\x78" => 1, "\x79" => 1, "\x7a" => 1, "\x7b" => 1, "\x7c" => 1, "\x7d" => 1, "\x7e" => 1, "\x7f" => 1, - "\x80" => 0, "\x81" => 0, "\x82" => 0, "\x83" => 0, "\x84" => 0, "\x85" => 0, "\x86" => 0, "\x87" => 0, - "\x88" => 0, "\x89" => 0, "\x8a" => 0, "\x8b" => 0, "\x8c" => 0, "\x8d" => 0, "\x8e" => 0, "\x8f" => 0, - "\x90" => 0, "\x91" => 0, "\x92" => 0, "\x93" => 0, "\x94" => 0, "\x95" => 0, "\x96" => 0, "\x97" => 0, - "\x98" => 0, "\x99" => 0, "\x9a" => 0, "\x9b" => 0, "\x9c" => 0, "\x9d" => 0, "\x9e" => 0, "\x9f" => 0, - "\xa0" => 0, "\xa1" => 0, "\xa2" => 0, "\xa3" => 0, "\xa4" => 0, "\xa5" => 0, "\xa6" => 0, "\xa7" => 0, - "\xa8" => 0, "\xa9" => 0, "\xaa" => 0, "\xab" => 0, "\xac" => 0, "\xad" => 0, "\xae" => 0, "\xaf" => 0, - "\xb0" => 0, "\xb1" => 0, "\xb2" => 0, "\xb3" => 0, "\xb4" => 0, "\xb5" => 0, "\xb6" => 0, "\xb7" => 0, - "\xb8" => 0, "\xb9" => 0, "\xba" => 0, "\xbb" => 0, "\xbc" => 0, "\xbd" => 0, "\xbe" => 0, "\xbf" => 0, - "\xc0" => 2, "\xc1" => 2, "\xc2" => 2, "\xc3" => 2, "\xc4" => 2, "\xc5" => 2, "\xc6" => 2, "\xc7" => 2, - "\xc8" => 2, "\xc9" => 2, "\xca" => 2, "\xcb" => 2, "\xcc" => 2, "\xcd" => 2, "\xce" => 2, "\xcf" => 2, - "\xd0" => 2, "\xd1" => 2, "\xd2" => 2, "\xd3" => 2, "\xd4" => 2, "\xd5" => 2, "\xd6" => 2, "\xd7" => 2, - "\xd8" => 2, "\xd9" => 2, "\xda" => 2, "\xdb" => 2, "\xdc" => 2, "\xdd" => 2, "\xde" => 2, "\xdf" => 2, - "\xe0" => 3, "\xe1" => 3, "\xe2" => 3, "\xe3" => 3, "\xe4" => 3, "\xe5" => 3, "\xe6" => 3, "\xe7" => 3, - "\xe8" => 3, "\xe9" => 3, "\xea" => 3, "\xeb" => 3, "\xec" => 3, "\xed" => 3, "\xee" => 3, "\xef" => 3, - "\xf0" => 4, "\xf1" => 4, "\xf2" => 4, "\xf3" => 4, "\xf4" => 4, "\xf5" => 4, "\xf6" => 4, "\xf7" => 4, - "\xf8" => 5, "\xf9" => 5, "\xfa" => 5, "\xfb" => 5, "\xfc" => 6, "\xfd" => 6, "\xfe" => 0, "\xff" => 0, - ); - - /** - * Returns the complete character map. - * - * @param string $string - * @param int $startOffset - * @param array $currentMap - * @param mixed $ignoredChars - * - * @return int - */ - public function getCharPositions($string, $startOffset, &$currentMap, &$ignoredChars) - { - if (!isset($currentMap['i']) || !isset($currentMap['p'])) { - $currentMap['p'] = $currentMap['i'] = array(); - } - - $strlen = strlen($string); - $charPos = count($currentMap['p']); - $foundChars = 0; - $invalid = false; - for ($i = 0; $i < $strlen; ++$i) { - $char = $string[$i]; - $size = self::$s_length_map[$char]; - if ($size == 0) { - /* char is invalid, we must wait for a resync */ - $invalid = true; - continue; - } else { - if ($invalid == true) { - /* We mark the chars as invalid and start a new char */ - $currentMap['p'][$charPos + $foundChars] = $startOffset + $i; - $currentMap['i'][$charPos + $foundChars] = true; - ++$foundChars; - $invalid = false; - } - if (($i + $size) > $strlen) { - $ignoredChars = substr($string, $i); - break; - } - for ($j = 1; $j < $size; ++$j) { - $char = $string[$i + $j]; - if ($char > "\x7F" && $char < "\xC0") { - // Valid - continue parsing - } else { - /* char is invalid, we must wait for a resync */ - $invalid = true; - continue 2; - } - } - /* Ok we got a complete char here */ - $currentMap['p'][$charPos + $foundChars] = $startOffset + $i + $size; - $i += $j - 1; - ++$foundChars; - } - } - - return $foundChars; - } - - /** - * Returns mapType. - * - * @return int mapType - */ - public function getMapType() - { - return self::MAP_TYPE_POSITIONS; - } - - /** - * Returns an integer which specifies how many more bytes to read. - * - * A positive integer indicates the number of more bytes to fetch before invoking - * this method again. - * A value of zero means this is already a valid character. - * A value of -1 means this cannot possibly be a valid character. - * - * @param string $bytes - * @param int $size - * - * @return int - */ - public function validateByteSequence($bytes, $size) - { - if ($size < 1) { - return -1; - } - $needed = self::$length_map[$bytes[0]] - $size; - - return $needed > -1 ? $needed : -1; - } - - /** - * Returns the number of bytes which should be read to start each character. - * - * @return int - */ - public function getInitialByteSize() - { - return 1; - } -} diff --git a/lib/swiftmailer/swiftmailer/lib/classes/Swift/CharacterReaderFactory.php b/lib/swiftmailer/swiftmailer/lib/classes/Swift/CharacterReaderFactory.php deleted file mode 100644 index 15b6c6920..000000000 --- a/lib/swiftmailer/swiftmailer/lib/classes/Swift/CharacterReaderFactory.php +++ /dev/null @@ -1,26 +0,0 @@ -init(); - } - - public function __wakeup() - { - $this->init(); - } - - public function init() - { - if (count(self::$_map) > 0) { - return; - } - - $prefix = 'Swift_CharacterReader_'; - - $singleByte = array( - 'class' => $prefix.'GenericFixedWidthReader', - 'constructor' => array(1), - ); - - $doubleByte = array( - 'class' => $prefix.'GenericFixedWidthReader', - 'constructor' => array(2), - ); - - $fourBytes = array( - 'class' => $prefix.'GenericFixedWidthReader', - 'constructor' => array(4), - ); - - // Utf-8 - self::$_map['utf-?8'] = array( - 'class' => $prefix.'Utf8Reader', - 'constructor' => array(), - ); - - //7-8 bit charsets - self::$_map['(us-)?ascii'] = $singleByte; - self::$_map['(iso|iec)-?8859-?[0-9]+'] = $singleByte; - self::$_map['windows-?125[0-9]'] = $singleByte; - self::$_map['cp-?[0-9]+'] = $singleByte; - self::$_map['ansi'] = $singleByte; - self::$_map['macintosh'] = $singleByte; - self::$_map['koi-?7'] = $singleByte; - self::$_map['koi-?8-?.+'] = $singleByte; - self::$_map['mik'] = $singleByte; - self::$_map['(cork|t1)'] = $singleByte; - self::$_map['v?iscii'] = $singleByte; - - //16 bits - self::$_map['(ucs-?2|utf-?16)'] = $doubleByte; - - //32 bits - self::$_map['(ucs-?4|utf-?32)'] = $fourBytes; - - // Fallback - self::$_map['.*'] = $singleByte; - } - - /** - * Returns a CharacterReader suitable for the charset applied. - * - * @param string $charset - * - * @return Swift_CharacterReader - */ - public function getReaderFor($charset) - { - $charset = trim(strtolower($charset)); - foreach (self::$_map as $pattern => $spec) { - $re = '/^'.$pattern.'$/D'; - if (preg_match($re, $charset)) { - if (!array_key_exists($pattern, self::$_loaded)) { - $reflector = new ReflectionClass($spec['class']); - if ($reflector->getConstructor()) { - $reader = $reflector->newInstanceArgs($spec['constructor']); - } else { - $reader = $reflector->newInstance(); - } - self::$_loaded[$pattern] = $reader; - } - - return self::$_loaded[$pattern]; - } - } - } -} diff --git a/lib/swiftmailer/swiftmailer/lib/classes/Swift/CharacterStream.php b/lib/swiftmailer/swiftmailer/lib/classes/Swift/CharacterStream.php deleted file mode 100644 index 717924f5d..000000000 --- a/lib/swiftmailer/swiftmailer/lib/classes/Swift/CharacterStream.php +++ /dev/null @@ -1,89 +0,0 @@ -setCharacterReaderFactory($factory); - $this->setCharacterSet($charset); - } - - /** - * Set the character set used in this CharacterStream. - * - * @param string $charset - */ - public function setCharacterSet($charset) - { - $this->_charset = $charset; - $this->_charReader = null; - } - - /** - * Set the CharacterReaderFactory for multi charset support. - * - * @param Swift_CharacterReaderFactory $factory - */ - public function setCharacterReaderFactory(Swift_CharacterReaderFactory $factory) - { - $this->_charReaderFactory = $factory; - } - - /** - * Overwrite this character stream using the byte sequence in the byte stream. - * - * @param Swift_OutputByteStream $os output stream to read from - */ - public function importByteStream(Swift_OutputByteStream $os) - { - if (!isset($this->_charReader)) { - $this->_charReader = $this->_charReaderFactory - ->getReaderFor($this->_charset); - } - - $startLength = $this->_charReader->getInitialByteSize(); - while (false !== $bytes = $os->read($startLength)) { - $c = array(); - for ($i = 0, $len = strlen($bytes); $i < $len; ++$i) { - $c[] = self::$_byteMap[$bytes[$i]]; - } - $size = count($c); - $need = $this->_charReader - ->validateByteSequence($c, $size); - if ($need > 0 && - false !== $bytes = $os->read($need)) { - for ($i = 0, $len = strlen($bytes); $i < $len; ++$i) { - $c[] = self::$_byteMap[$bytes[$i]]; - } - } - $this->_array[] = $c; - ++$this->_array_size; - } - } - - /** - * Import a string a bytes into this CharacterStream, overwriting any existing - * data in the stream. - * - * @param string $string - */ - public function importString($string) - { - $this->flushContents(); - $this->write($string); - } - - /** - * Read $length characters from the stream and move the internal pointer - * $length further into the stream. - * - * @param int $length - * - * @return string - */ - public function read($length) - { - if ($this->_offset == $this->_array_size) { - return false; - } - - // Don't use array slice - $arrays = array(); - $end = $length + $this->_offset; - for ($i = $this->_offset; $i < $end; ++$i) { - if (!isset($this->_array[$i])) { - break; - } - $arrays[] = $this->_array[$i]; - } - $this->_offset += $i - $this->_offset; // Limit function calls - $chars = false; - foreach ($arrays as $array) { - $chars .= implode('', array_map('chr', $array)); - } - - return $chars; - } - - /** - * Read $length characters from the stream and return a 1-dimensional array - * containing there octet values. - * - * @param int $length - * - * @return int[] - */ - public function readBytes($length) - { - if ($this->_offset == $this->_array_size) { - return false; - } - $arrays = array(); - $end = $length + $this->_offset; - for ($i = $this->_offset; $i < $end; ++$i) { - if (!isset($this->_array[$i])) { - break; - } - $arrays[] = $this->_array[$i]; - } - $this->_offset += ($i - $this->_offset); // Limit function calls - - return call_user_func_array('array_merge', $arrays); - } - - /** - * Write $chars to the end of the stream. - * - * @param string $chars - */ - public function write($chars) - { - if (!isset($this->_charReader)) { - $this->_charReader = $this->_charReaderFactory->getReaderFor( - $this->_charset); - } - - $startLength = $this->_charReader->getInitialByteSize(); - - $fp = fopen('php://memory', 'w+b'); - fwrite($fp, $chars); - unset($chars); - fseek($fp, 0, SEEK_SET); - - $buffer = array(0); - $buf_pos = 1; - $buf_len = 1; - $has_datas = true; - do { - $bytes = array(); - // Buffer Filing - if ($buf_len - $buf_pos < $startLength) { - $buf = array_splice($buffer, $buf_pos); - $new = $this->_reloadBuffer($fp, 100); - if ($new) { - $buffer = array_merge($buf, $new); - $buf_len = count($buffer); - $buf_pos = 0; - } else { - $has_datas = false; - } - } - if ($buf_len - $buf_pos > 0) { - $size = 0; - for ($i = 0; $i < $startLength && isset($buffer[$buf_pos]); ++$i) { - ++$size; - $bytes[] = $buffer[$buf_pos++]; - } - $need = $this->_charReader->validateByteSequence( - $bytes, $size); - if ($need > 0) { - if ($buf_len - $buf_pos < $need) { - $new = $this->_reloadBuffer($fp, $need); - - if ($new) { - $buffer = array_merge($buffer, $new); - $buf_len = count($buffer); - } - } - for ($i = 0; $i < $need && isset($buffer[$buf_pos]); ++$i) { - $bytes[] = $buffer[$buf_pos++]; - } - } - $this->_array[] = $bytes; - ++$this->_array_size; - } - } while ($has_datas); - - fclose($fp); - } - - /** - * Move the internal pointer to $charOffset in the stream. - * - * @param int $charOffset - */ - public function setPointer($charOffset) - { - if ($charOffset > $this->_array_size) { - $charOffset = $this->_array_size; - } elseif ($charOffset < 0) { - $charOffset = 0; - } - $this->_offset = $charOffset; - } - - /** - * Empty the stream and reset the internal pointer. - */ - public function flushContents() - { - $this->_offset = 0; - $this->_array = array(); - $this->_array_size = 0; - } - - private function _reloadBuffer($fp, $len) - { - if (!feof($fp) && ($bytes = fread($fp, $len)) !== false) { - $buf = array(); - for ($i = 0, $len = strlen($bytes); $i < $len; ++$i) { - $buf[] = self::$_byteMap[$bytes[$i]]; - } - - return $buf; - } - - return false; - } - - private static function _initializeMaps() - { - if (!isset(self::$_charMap)) { - self::$_charMap = array(); - for ($byte = 0; $byte < 256; ++$byte) { - self::$_charMap[$byte] = chr($byte); - } - self::$_byteMap = array_flip(self::$_charMap); - } - } -} diff --git a/lib/swiftmailer/swiftmailer/lib/classes/Swift/CharacterStream/NgCharacterStream.php b/lib/swiftmailer/swiftmailer/lib/classes/Swift/CharacterStream/NgCharacterStream.php deleted file mode 100644 index 58bd140fd..000000000 --- a/lib/swiftmailer/swiftmailer/lib/classes/Swift/CharacterStream/NgCharacterStream.php +++ /dev/null @@ -1,267 +0,0 @@ - - */ -class Swift_CharacterStream_NgCharacterStream implements Swift_CharacterStream -{ - /** - * The char reader (lazy-loaded) for the current charset. - * - * @var Swift_CharacterReader - */ - private $_charReader; - - /** - * A factory for creating CharacterReader instances. - * - * @var Swift_CharacterReaderFactory - */ - private $_charReaderFactory; - - /** - * The character set this stream is using. - * - * @var string - */ - private $_charset; - - /** - * The data's stored as-is. - * - * @var string - */ - private $_datas = ''; - - /** - * Number of bytes in the stream. - * - * @var int - */ - private $_datasSize = 0; - - /** - * Map. - * - * @var mixed - */ - private $_map; - - /** - * Map Type. - * - * @var int - */ - private $_mapType = 0; - - /** - * Number of characters in the stream. - * - * @var int - */ - private $_charCount = 0; - - /** - * Position in the stream. - * - * @var int - */ - private $_currentPos = 0; - - /** - * Constructor. - * - * @param Swift_CharacterReaderFactory $factory - * @param string $charset - */ - public function __construct(Swift_CharacterReaderFactory $factory, $charset) - { - $this->setCharacterReaderFactory($factory); - $this->setCharacterSet($charset); - } - - /* -- Changing parameters of the stream -- */ - - /** - * Set the character set used in this CharacterStream. - * - * @param string $charset - */ - public function setCharacterSet($charset) - { - $this->_charset = $charset; - $this->_charReader = null; - $this->_mapType = 0; - } - - /** - * Set the CharacterReaderFactory for multi charset support. - * - * @param Swift_CharacterReaderFactory $factory - */ - public function setCharacterReaderFactory(Swift_CharacterReaderFactory $factory) - { - $this->_charReaderFactory = $factory; - } - - /** - * @see Swift_CharacterStream::flushContents() - */ - public function flushContents() - { - $this->_datas = null; - $this->_map = null; - $this->_charCount = 0; - $this->_currentPos = 0; - $this->_datasSize = 0; - } - - /** - * @see Swift_CharacterStream::importByteStream() - * - * @param Swift_OutputByteStream $os - */ - public function importByteStream(Swift_OutputByteStream $os) - { - $this->flushContents(); - $blocks = 512; - $os->setReadPointer(0); - while (false !== ($read = $os->read($blocks))) { - $this->write($read); - } - } - - /** - * @see Swift_CharacterStream::importString() - * - * @param string $string - */ - public function importString($string) - { - $this->flushContents(); - $this->write($string); - } - - /** - * @see Swift_CharacterStream::read() - * - * @param int $length - * - * @return string - */ - public function read($length) - { - if ($this->_currentPos >= $this->_charCount) { - return false; - } - $ret = false; - $length = $this->_currentPos + $length > $this->_charCount ? $this->_charCount - $this->_currentPos : $length; - switch ($this->_mapType) { - case Swift_CharacterReader::MAP_TYPE_FIXED_LEN: - $len = $length * $this->_map; - $ret = substr($this->_datas, - $this->_currentPos * $this->_map, - $len); - $this->_currentPos += $length; - break; - - case Swift_CharacterReader::MAP_TYPE_INVALID: - $ret = ''; - for (; $this->_currentPos < $length; ++$this->_currentPos) { - if (isset($this->_map[$this->_currentPos])) { - $ret .= '?'; - } else { - $ret .= $this->_datas[$this->_currentPos]; - } - } - break; - - case Swift_CharacterReader::MAP_TYPE_POSITIONS: - $end = $this->_currentPos + $length; - $end = $end > $this->_charCount ? $this->_charCount : $end; - $ret = ''; - $start = 0; - if ($this->_currentPos > 0) { - $start = $this->_map['p'][$this->_currentPos - 1]; - } - $to = $start; - for (; $this->_currentPos < $end; ++$this->_currentPos) { - if (isset($this->_map['i'][$this->_currentPos])) { - $ret .= substr($this->_datas, $start, $to - $start).'?'; - $start = $this->_map['p'][$this->_currentPos]; - } else { - $to = $this->_map['p'][$this->_currentPos]; - } - } - $ret .= substr($this->_datas, $start, $to - $start); - break; - } - - return $ret; - } - - /** - * @see Swift_CharacterStream::readBytes() - * - * @param int $length - * - * @return int[] - */ - public function readBytes($length) - { - $read = $this->read($length); - if ($read !== false) { - $ret = array_map('ord', str_split($read, 1)); - - return $ret; - } - - return false; - } - - /** - * @see Swift_CharacterStream::setPointer() - * - * @param int $charOffset - */ - public function setPointer($charOffset) - { - if ($this->_charCount < $charOffset) { - $charOffset = $this->_charCount; - } - $this->_currentPos = $charOffset; - } - - /** - * @see Swift_CharacterStream::write() - * - * @param string $chars - */ - public function write($chars) - { - if (!isset($this->_charReader)) { - $this->_charReader = $this->_charReaderFactory->getReaderFor( - $this->_charset); - $this->_map = array(); - $this->_mapType = $this->_charReader->getMapType(); - } - $ignored = ''; - $this->_datas .= $chars; - $this->_charCount += $this->_charReader->getCharPositions(substr($this->_datas, $this->_datasSize), $this->_datasSize, $this->_map, $ignored); - if ($ignored !== false) { - $this->_datasSize = strlen($this->_datas) - strlen($ignored); - } else { - $this->_datasSize = strlen($this->_datas); - } - } -} diff --git a/lib/swiftmailer/swiftmailer/lib/classes/Swift/ConfigurableSpool.php b/lib/swiftmailer/swiftmailer/lib/classes/Swift/ConfigurableSpool.php deleted file mode 100644 index 4ae5bacfc..000000000 --- a/lib/swiftmailer/swiftmailer/lib/classes/Swift/ConfigurableSpool.php +++ /dev/null @@ -1,63 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -/** - * Base class for Spools (implements time and message limits). - * - * @author Fabien Potencier - */ -abstract class Swift_ConfigurableSpool implements Swift_Spool -{ - /** The maximum number of messages to send per flush */ - private $_message_limit; - - /** The time limit per flush */ - private $_time_limit; - - /** - * Sets the maximum number of messages to send per flush. - * - * @param int $limit - */ - public function setMessageLimit($limit) - { - $this->_message_limit = (int) $limit; - } - - /** - * Gets the maximum number of messages to send per flush. - * - * @return int The limit - */ - public function getMessageLimit() - { - return $this->_message_limit; - } - - /** - * Sets the time limit (in seconds) per flush. - * - * @param int $limit The limit - */ - public function setTimeLimit($limit) - { - $this->_time_limit = (int) $limit; - } - - /** - * Gets the time limit (in seconds) per flush. - * - * @return int The limit - */ - public function getTimeLimit() - { - return $this->_time_limit; - } -} diff --git a/lib/swiftmailer/swiftmailer/lib/classes/Swift/DependencyContainer.php b/lib/swiftmailer/swiftmailer/lib/classes/Swift/DependencyContainer.php deleted file mode 100644 index befec9ac0..000000000 --- a/lib/swiftmailer/swiftmailer/lib/classes/Swift/DependencyContainer.php +++ /dev/null @@ -1,373 +0,0 @@ -_store); - } - - /** - * Test if an item is registered in this container with the given name. - * - * @see register() - * - * @param string $itemName - * - * @return bool - */ - public function has($itemName) - { - return array_key_exists($itemName, $this->_store) - && isset($this->_store[$itemName]['lookupType']); - } - - /** - * Lookup the item with the given $itemName. - * - * @see register() - * - * @param string $itemName - * - * @throws Swift_DependencyException If the dependency is not found - * - * @return mixed - */ - public function lookup($itemName) - { - if (!$this->has($itemName)) { - throw new Swift_DependencyException( - 'Cannot lookup dependency "'.$itemName.'" since it is not registered.' - ); - } - - switch ($this->_store[$itemName]['lookupType']) { - case self::TYPE_ALIAS: - return $this->_createAlias($itemName); - case self::TYPE_VALUE: - return $this->_getValue($itemName); - case self::TYPE_INSTANCE: - return $this->_createNewInstance($itemName); - case self::TYPE_SHARED: - return $this->_createSharedInstance($itemName); - } - } - - /** - * Create an array of arguments passed to the constructor of $itemName. - * - * @param string $itemName - * - * @return array - */ - public function createDependenciesFor($itemName) - { - $args = array(); - if (isset($this->_store[$itemName]['args'])) { - $args = $this->_resolveArgs($this->_store[$itemName]['args']); - } - - return $args; - } - - /** - * Register a new dependency with $itemName. - * - * This method returns the current DependencyContainer instance because it - * requires the use of the fluid interface to set the specific details for the - * dependency. - * - * @see asNewInstanceOf(), asSharedInstanceOf(), asValue() - * - * @param string $itemName - * - * @return $this - */ - public function register($itemName) - { - $this->_store[$itemName] = array(); - $this->_endPoint = &$this->_store[$itemName]; - - return $this; - } - - /** - * Specify the previously registered item as a literal value. - * - * {@link register()} must be called before this will work. - * - * @param mixed $value - * - * @return $this - */ - public function asValue($value) - { - $endPoint = &$this->_getEndPoint(); - $endPoint['lookupType'] = self::TYPE_VALUE; - $endPoint['value'] = $value; - - return $this; - } - - /** - * Specify the previously registered item as an alias of another item. - * - * @param string $lookup - * - * @return $this - */ - public function asAliasOf($lookup) - { - $endPoint = &$this->_getEndPoint(); - $endPoint['lookupType'] = self::TYPE_ALIAS; - $endPoint['ref'] = $lookup; - - return $this; - } - - /** - * Specify the previously registered item as a new instance of $className. - * - * {@link register()} must be called before this will work. - * Any arguments can be set with {@link withDependencies()}, - * {@link addConstructorValue()} or {@link addConstructorLookup()}. - * - * @see withDependencies(), addConstructorValue(), addConstructorLookup() - * - * @param string $className - * - * @return $this - */ - public function asNewInstanceOf($className) - { - $endPoint = &$this->_getEndPoint(); - $endPoint['lookupType'] = self::TYPE_INSTANCE; - $endPoint['className'] = $className; - - return $this; - } - - /** - * Specify the previously registered item as a shared instance of $className. - * - * {@link register()} must be called before this will work. - * - * @param string $className - * - * @return $this - */ - public function asSharedInstanceOf($className) - { - $endPoint = &$this->_getEndPoint(); - $endPoint['lookupType'] = self::TYPE_SHARED; - $endPoint['className'] = $className; - - return $this; - } - - /** - * Specify a list of injected dependencies for the previously registered item. - * - * This method takes an array of lookup names. - * - * @see addConstructorValue(), addConstructorLookup() - * - * @param array $lookups - * - * @return $this - */ - public function withDependencies(array $lookups) - { - $endPoint = &$this->_getEndPoint(); - $endPoint['args'] = array(); - foreach ($lookups as $lookup) { - $this->addConstructorLookup($lookup); - } - - return $this; - } - - /** - * Specify a literal (non looked up) value for the constructor of the - * previously registered item. - * - * @see withDependencies(), addConstructorLookup() - * - * @param mixed $value - * - * @return $this - */ - public function addConstructorValue($value) - { - $endPoint = &$this->_getEndPoint(); - if (!isset($endPoint['args'])) { - $endPoint['args'] = array(); - } - $endPoint['args'][] = array('type' => 'value', 'item' => $value); - - return $this; - } - - /** - * Specify a dependency lookup for the constructor of the previously - * registered item. - * - * @see withDependencies(), addConstructorValue() - * - * @param string $lookup - * - * @return $this - */ - public function addConstructorLookup($lookup) - { - $endPoint = &$this->_getEndPoint(); - if (!isset($this->_endPoint['args'])) { - $endPoint['args'] = array(); - } - $endPoint['args'][] = array('type' => 'lookup', 'item' => $lookup); - - return $this; - } - - /** Get the literal value with $itemName */ - private function _getValue($itemName) - { - return $this->_store[$itemName]['value']; - } - - /** Resolve an alias to another item */ - private function _createAlias($itemName) - { - return $this->lookup($this->_store[$itemName]['ref']); - } - - /** Create a fresh instance of $itemName */ - private function _createNewInstance($itemName) - { - $reflector = new ReflectionClass($this->_store[$itemName]['className']); - if ($reflector->getConstructor()) { - return $reflector->newInstanceArgs( - $this->createDependenciesFor($itemName) - ); - } - - return $reflector->newInstance(); - } - - /** Create and register a shared instance of $itemName */ - private function _createSharedInstance($itemName) - { - if (!isset($this->_store[$itemName]['instance'])) { - $this->_store[$itemName]['instance'] = $this->_createNewInstance($itemName); - } - - return $this->_store[$itemName]['instance']; - } - - /** Get the current endpoint in the store */ - private function &_getEndPoint() - { - if (!isset($this->_endPoint)) { - throw new BadMethodCallException( - 'Component must first be registered by calling register()' - ); - } - - return $this->_endPoint; - } - - /** Get an argument list with dependencies resolved */ - private function _resolveArgs(array $args) - { - $resolved = array(); - foreach ($args as $argDefinition) { - switch ($argDefinition['type']) { - case 'lookup': - $resolved[] = $this->_lookupRecursive($argDefinition['item']); - break; - case 'value': - $resolved[] = $argDefinition['item']; - break; - } - } - - return $resolved; - } - - /** Resolve a single dependency with an collections */ - private function _lookupRecursive($item) - { - if (is_array($item)) { - $collection = array(); - foreach ($item as $k => $v) { - $collection[$k] = $this->_lookupRecursive($v); - } - - return $collection; - } - - return $this->lookup($item); - } -} diff --git a/lib/swiftmailer/swiftmailer/lib/classes/Swift/DependencyException.php b/lib/swiftmailer/swiftmailer/lib/classes/Swift/DependencyException.php deleted file mode 100644 index 799d38d83..000000000 --- a/lib/swiftmailer/swiftmailer/lib/classes/Swift/DependencyException.php +++ /dev/null @@ -1,27 +0,0 @@ -createDependenciesFor('mime.embeddedfile') - ); - - $this->setBody($data); - $this->setFilename($filename); - if ($contentType) { - $this->setContentType($contentType); - } - } - - /** - * Create a new EmbeddedFile. - * - * @param string|Swift_OutputByteStream $data - * @param string $filename - * @param string $contentType - * - * @return Swift_Mime_EmbeddedFile - */ - public static function newInstance($data = null, $filename = null, $contentType = null) - { - return new self($data, $filename, $contentType); - } - - /** - * Create a new EmbeddedFile from a filesystem path. - * - * @param string $path - * - * @return Swift_Mime_EmbeddedFile - */ - public static function fromPath($path) - { - return self::newInstance()->setFile( - new Swift_ByteStream_FileByteStream($path) - ); - } -} diff --git a/lib/swiftmailer/swiftmailer/lib/classes/Swift/Encoder.php b/lib/swiftmailer/swiftmailer/lib/classes/Swift/Encoder.php deleted file mode 100644 index 2073abca1..000000000 --- a/lib/swiftmailer/swiftmailer/lib/classes/Swift/Encoder.php +++ /dev/null @@ -1,28 +0,0 @@ -= $maxLineLength || 76 < $maxLineLength) { - $maxLineLength = 76; - } - - $encodedString = base64_encode($string); - $firstLine = ''; - - if (0 != $firstLineOffset) { - $firstLine = substr( - $encodedString, 0, $maxLineLength - $firstLineOffset - )."\r\n"; - $encodedString = substr( - $encodedString, $maxLineLength - $firstLineOffset - ); - } - - return $firstLine.trim(chunk_split($encodedString, $maxLineLength, "\r\n")); - } - - /** - * Does nothing. - */ - public function charsetChanged($charset) - { - } -} diff --git a/lib/swiftmailer/swiftmailer/lib/classes/Swift/Encoder/QpEncoder.php b/lib/swiftmailer/swiftmailer/lib/classes/Swift/Encoder/QpEncoder.php deleted file mode 100644 index edec10c51..000000000 --- a/lib/swiftmailer/swiftmailer/lib/classes/Swift/Encoder/QpEncoder.php +++ /dev/null @@ -1,300 +0,0 @@ - '=00', 1 => '=01', 2 => '=02', 3 => '=03', 4 => '=04', - 5 => '=05', 6 => '=06', 7 => '=07', 8 => '=08', 9 => '=09', - 10 => '=0A', 11 => '=0B', 12 => '=0C', 13 => '=0D', 14 => '=0E', - 15 => '=0F', 16 => '=10', 17 => '=11', 18 => '=12', 19 => '=13', - 20 => '=14', 21 => '=15', 22 => '=16', 23 => '=17', 24 => '=18', - 25 => '=19', 26 => '=1A', 27 => '=1B', 28 => '=1C', 29 => '=1D', - 30 => '=1E', 31 => '=1F', 32 => '=20', 33 => '=21', 34 => '=22', - 35 => '=23', 36 => '=24', 37 => '=25', 38 => '=26', 39 => '=27', - 40 => '=28', 41 => '=29', 42 => '=2A', 43 => '=2B', 44 => '=2C', - 45 => '=2D', 46 => '=2E', 47 => '=2F', 48 => '=30', 49 => '=31', - 50 => '=32', 51 => '=33', 52 => '=34', 53 => '=35', 54 => '=36', - 55 => '=37', 56 => '=38', 57 => '=39', 58 => '=3A', 59 => '=3B', - 60 => '=3C', 61 => '=3D', 62 => '=3E', 63 => '=3F', 64 => '=40', - 65 => '=41', 66 => '=42', 67 => '=43', 68 => '=44', 69 => '=45', - 70 => '=46', 71 => '=47', 72 => '=48', 73 => '=49', 74 => '=4A', - 75 => '=4B', 76 => '=4C', 77 => '=4D', 78 => '=4E', 79 => '=4F', - 80 => '=50', 81 => '=51', 82 => '=52', 83 => '=53', 84 => '=54', - 85 => '=55', 86 => '=56', 87 => '=57', 88 => '=58', 89 => '=59', - 90 => '=5A', 91 => '=5B', 92 => '=5C', 93 => '=5D', 94 => '=5E', - 95 => '=5F', 96 => '=60', 97 => '=61', 98 => '=62', 99 => '=63', - 100 => '=64', 101 => '=65', 102 => '=66', 103 => '=67', 104 => '=68', - 105 => '=69', 106 => '=6A', 107 => '=6B', 108 => '=6C', 109 => '=6D', - 110 => '=6E', 111 => '=6F', 112 => '=70', 113 => '=71', 114 => '=72', - 115 => '=73', 116 => '=74', 117 => '=75', 118 => '=76', 119 => '=77', - 120 => '=78', 121 => '=79', 122 => '=7A', 123 => '=7B', 124 => '=7C', - 125 => '=7D', 126 => '=7E', 127 => '=7F', 128 => '=80', 129 => '=81', - 130 => '=82', 131 => '=83', 132 => '=84', 133 => '=85', 134 => '=86', - 135 => '=87', 136 => '=88', 137 => '=89', 138 => '=8A', 139 => '=8B', - 140 => '=8C', 141 => '=8D', 142 => '=8E', 143 => '=8F', 144 => '=90', - 145 => '=91', 146 => '=92', 147 => '=93', 148 => '=94', 149 => '=95', - 150 => '=96', 151 => '=97', 152 => '=98', 153 => '=99', 154 => '=9A', - 155 => '=9B', 156 => '=9C', 157 => '=9D', 158 => '=9E', 159 => '=9F', - 160 => '=A0', 161 => '=A1', 162 => '=A2', 163 => '=A3', 164 => '=A4', - 165 => '=A5', 166 => '=A6', 167 => '=A7', 168 => '=A8', 169 => '=A9', - 170 => '=AA', 171 => '=AB', 172 => '=AC', 173 => '=AD', 174 => '=AE', - 175 => '=AF', 176 => '=B0', 177 => '=B1', 178 => '=B2', 179 => '=B3', - 180 => '=B4', 181 => '=B5', 182 => '=B6', 183 => '=B7', 184 => '=B8', - 185 => '=B9', 186 => '=BA', 187 => '=BB', 188 => '=BC', 189 => '=BD', - 190 => '=BE', 191 => '=BF', 192 => '=C0', 193 => '=C1', 194 => '=C2', - 195 => '=C3', 196 => '=C4', 197 => '=C5', 198 => '=C6', 199 => '=C7', - 200 => '=C8', 201 => '=C9', 202 => '=CA', 203 => '=CB', 204 => '=CC', - 205 => '=CD', 206 => '=CE', 207 => '=CF', 208 => '=D0', 209 => '=D1', - 210 => '=D2', 211 => '=D3', 212 => '=D4', 213 => '=D5', 214 => '=D6', - 215 => '=D7', 216 => '=D8', 217 => '=D9', 218 => '=DA', 219 => '=DB', - 220 => '=DC', 221 => '=DD', 222 => '=DE', 223 => '=DF', 224 => '=E0', - 225 => '=E1', 226 => '=E2', 227 => '=E3', 228 => '=E4', 229 => '=E5', - 230 => '=E6', 231 => '=E7', 232 => '=E8', 233 => '=E9', 234 => '=EA', - 235 => '=EB', 236 => '=EC', 237 => '=ED', 238 => '=EE', 239 => '=EF', - 240 => '=F0', 241 => '=F1', 242 => '=F2', 243 => '=F3', 244 => '=F4', - 245 => '=F5', 246 => '=F6', 247 => '=F7', 248 => '=F8', 249 => '=F9', - 250 => '=FA', 251 => '=FB', 252 => '=FC', 253 => '=FD', 254 => '=FE', - 255 => '=FF', - ); - - protected static $_safeMapShare = array(); - - /** - * A map of non-encoded ascii characters. - * - * @var string[] - */ - protected $_safeMap = array(); - - /** - * Creates a new QpEncoder for the given CharacterStream. - * - * @param Swift_CharacterStream $charStream to use for reading characters - * @param Swift_StreamFilter $filter if input should be canonicalized - */ - public function __construct(Swift_CharacterStream $charStream, Swift_StreamFilter $filter = null) - { - $this->_charStream = $charStream; - if (!isset(self::$_safeMapShare[$this->getSafeMapShareId()])) { - $this->initSafeMap(); - self::$_safeMapShare[$this->getSafeMapShareId()] = $this->_safeMap; - } else { - $this->_safeMap = self::$_safeMapShare[$this->getSafeMapShareId()]; - } - $this->_filter = $filter; - } - - public function __sleep() - { - return array('_charStream', '_filter'); - } - - public function __wakeup() - { - if (!isset(self::$_safeMapShare[$this->getSafeMapShareId()])) { - $this->initSafeMap(); - self::$_safeMapShare[$this->getSafeMapShareId()] = $this->_safeMap; - } else { - $this->_safeMap = self::$_safeMapShare[$this->getSafeMapShareId()]; - } - } - - protected function getSafeMapShareId() - { - return get_class($this); - } - - protected function initSafeMap() - { - foreach (array_merge( - array(0x09, 0x20), range(0x21, 0x3C), range(0x3E, 0x7E)) as $byte) { - $this->_safeMap[$byte] = chr($byte); - } - } - - /** - * Takes an unencoded string and produces a QP encoded string from it. - * - * QP encoded strings have a maximum line length of 76 characters. - * If the first line needs to be shorter, indicate the difference with - * $firstLineOffset. - * - * @param string $string to encode - * @param int $firstLineOffset, optional - * @param int $maxLineLength, optional 0 indicates the default of 76 chars - * - * @return string - */ - public function encodeString($string, $firstLineOffset = 0, $maxLineLength = 0) - { - if ($maxLineLength > 76 || $maxLineLength <= 0) { - $maxLineLength = 76; - } - - $thisLineLength = $maxLineLength - $firstLineOffset; - - $lines = array(); - $lNo = 0; - $lines[$lNo] = ''; - $currentLine = &$lines[$lNo++]; - $size = $lineLen = 0; - - $this->_charStream->flushContents(); - $this->_charStream->importString($string); - - // Fetching more than 4 chars at one is slower, as is fetching fewer bytes - // Conveniently 4 chars is the UTF-8 safe number since UTF-8 has up to 6 - // bytes per char and (6 * 4 * 3 = 72 chars per line) * =NN is 3 bytes - while (false !== $bytes = $this->_nextSequence()) { - // If we're filtering the input - if (isset($this->_filter)) { - // If we can't filter because we need more bytes - while ($this->_filter->shouldBuffer($bytes)) { - // Then collect bytes into the buffer - if (false === $moreBytes = $this->_nextSequence(1)) { - break; - } - - foreach ($moreBytes as $b) { - $bytes[] = $b; - } - } - // And filter them - $bytes = $this->_filter->filter($bytes); - } - - $enc = $this->_encodeByteSequence($bytes, $size); - - $i = strpos($enc, '=0D=0A'); - $newLineLength = $lineLen + ($i === false ? $size : $i); - - if ($currentLine && $newLineLength >= $thisLineLength) { - $lines[$lNo] = ''; - $currentLine = &$lines[$lNo++]; - $thisLineLength = $maxLineLength; - $lineLen = 0; - } - - $currentLine .= $enc; - - if ($i === false) { - $lineLen += $size; - } else { - // 6 is the length of '=0D=0A'. - $lineLen = $size - strrpos($enc, '=0D=0A') - 6; - } - } - - return $this->_standardize(implode("=\r\n", $lines)); - } - - /** - * Updates the charset used. - * - * @param string $charset - */ - public function charsetChanged($charset) - { - $this->_charStream->setCharacterSet($charset); - } - - /** - * Encode the given byte array into a verbatim QP form. - * - * @param int[] $bytes - * @param int $size - * - * @return string - */ - protected function _encodeByteSequence(array $bytes, &$size) - { - $ret = ''; - $size = 0; - foreach ($bytes as $b) { - if (isset($this->_safeMap[$b])) { - $ret .= $this->_safeMap[$b]; - ++$size; - } else { - $ret .= self::$_qpMap[$b]; - $size += 3; - } - } - - return $ret; - } - - /** - * Get the next sequence of bytes to read from the char stream. - * - * @param int $size number of bytes to read - * - * @return int[] - */ - protected function _nextSequence($size = 4) - { - return $this->_charStream->readBytes($size); - } - - /** - * Make sure CRLF is correct and HT/SPACE are in valid places. - * - * @param string $string - * - * @return string - */ - protected function _standardize($string) - { - $string = str_replace(array("\t=0D=0A", ' =0D=0A', '=0D=0A'), - array("=09\r\n", "=20\r\n", "\r\n"), $string - ); - switch ($end = ord(substr($string, -1))) { - case 0x09: - case 0x20: - $string = substr_replace($string, self::$_qpMap[$end], -1); - } - - return $string; - } - - /** - * Make a deep copy of object. - */ - public function __clone() - { - $this->_charStream = clone $this->_charStream; - } -} diff --git a/lib/swiftmailer/swiftmailer/lib/classes/Swift/Encoder/Rfc2231Encoder.php b/lib/swiftmailer/swiftmailer/lib/classes/Swift/Encoder/Rfc2231Encoder.php deleted file mode 100644 index b0215e883..000000000 --- a/lib/swiftmailer/swiftmailer/lib/classes/Swift/Encoder/Rfc2231Encoder.php +++ /dev/null @@ -1,92 +0,0 @@ -_charStream = $charStream; - } - - /** - * Takes an unencoded string and produces a string encoded according to - * RFC 2231 from it. - * - * @param string $string - * @param int $firstLineOffset - * @param int $maxLineLength optional, 0 indicates the default of 75 bytes - * - * @return string - */ - public function encodeString($string, $firstLineOffset = 0, $maxLineLength = 0) - { - $lines = array(); - $lineCount = 0; - $lines[] = ''; - $currentLine = &$lines[$lineCount++]; - - if (0 >= $maxLineLength) { - $maxLineLength = 75; - } - - $this->_charStream->flushContents(); - $this->_charStream->importString($string); - - $thisLineLength = $maxLineLength - $firstLineOffset; - - while (false !== $char = $this->_charStream->read(4)) { - $encodedChar = rawurlencode($char); - if (0 != strlen($currentLine) - && strlen($currentLine.$encodedChar) > $thisLineLength) { - $lines[] = ''; - $currentLine = &$lines[$lineCount++]; - $thisLineLength = $maxLineLength; - } - $currentLine .= $encodedChar; - } - - return implode("\r\n", $lines); - } - - /** - * Updates the charset used. - * - * @param string $charset - */ - public function charsetChanged($charset) - { - $this->_charStream->setCharacterSet($charset); - } - - /** - * Make a deep copy of object. - */ - public function __clone() - { - $this->_charStream = clone $this->_charStream; - } -} diff --git a/lib/swiftmailer/swiftmailer/lib/classes/Swift/Encoding.php b/lib/swiftmailer/swiftmailer/lib/classes/Swift/Encoding.php deleted file mode 100644 index 245878706..000000000 --- a/lib/swiftmailer/swiftmailer/lib/classes/Swift/Encoding.php +++ /dev/null @@ -1,62 +0,0 @@ -lookup($key); - } -} diff --git a/lib/swiftmailer/swiftmailer/lib/classes/Swift/Events/CommandEvent.php b/lib/swiftmailer/swiftmailer/lib/classes/Swift/Events/CommandEvent.php deleted file mode 100644 index 674e6b5e4..000000000 --- a/lib/swiftmailer/swiftmailer/lib/classes/Swift/Events/CommandEvent.php +++ /dev/null @@ -1,65 +0,0 @@ -_command = $command; - $this->_successCodes = $successCodes; - } - - /** - * Get the command which was sent to the server. - * - * @return string - */ - public function getCommand() - { - return $this->_command; - } - - /** - * Get the numeric response codes which indicate success for this command. - * - * @return int[] - */ - public function getSuccessCodes() - { - return $this->_successCodes; - } -} diff --git a/lib/swiftmailer/swiftmailer/lib/classes/Swift/Events/CommandListener.php b/lib/swiftmailer/swiftmailer/lib/classes/Swift/Events/CommandListener.php deleted file mode 100644 index 7545404e7..000000000 --- a/lib/swiftmailer/swiftmailer/lib/classes/Swift/Events/CommandListener.php +++ /dev/null @@ -1,24 +0,0 @@ -_source = $source; - } - - /** - * Get the source object of this event. - * - * @return object - */ - public function getSource() - { - return $this->_source; - } - - /** - * Prevent this Event from bubbling any further up the stack. - * - * @param bool $cancel, optional - */ - public function cancelBubble($cancel = true) - { - $this->_bubbleCancelled = $cancel; - } - - /** - * Returns true if this Event will not bubble any further up the stack. - * - * @return bool - */ - public function bubbleCancelled() - { - return $this->_bubbleCancelled; - } -} diff --git a/lib/swiftmailer/swiftmailer/lib/classes/Swift/Events/ResponseEvent.php b/lib/swiftmailer/swiftmailer/lib/classes/Swift/Events/ResponseEvent.php deleted file mode 100644 index 2e92ba940..000000000 --- a/lib/swiftmailer/swiftmailer/lib/classes/Swift/Events/ResponseEvent.php +++ /dev/null @@ -1,65 +0,0 @@ -_response = $response; - $this->_valid = $valid; - } - - /** - * Get the response which was received from the server. - * - * @return string - */ - public function getResponse() - { - return $this->_response; - } - - /** - * Get the success status of this Event. - * - * @return bool - */ - public function isValid() - { - return $this->_valid; - } -} diff --git a/lib/swiftmailer/swiftmailer/lib/classes/Swift/Events/ResponseListener.php b/lib/swiftmailer/swiftmailer/lib/classes/Swift/Events/ResponseListener.php deleted file mode 100644 index c40919d21..000000000 --- a/lib/swiftmailer/swiftmailer/lib/classes/Swift/Events/ResponseListener.php +++ /dev/null @@ -1,24 +0,0 @@ -_message = $message; - $this->_result = self::RESULT_PENDING; - } - - /** - * Get the Transport used to send the Message. - * - * @return Swift_Transport - */ - public function getTransport() - { - return $this->getSource(); - } - - /** - * Get the Message being sent. - * - * @return Swift_Mime_Message - */ - public function getMessage() - { - return $this->_message; - } - - /** - * Set the array of addresses that failed in sending. - * - * @param array $recipients - */ - public function setFailedRecipients($recipients) - { - $this->_failedRecipients = $recipients; - } - - /** - * Get an recipient addresses which were not accepted for delivery. - * - * @return string[] - */ - public function getFailedRecipients() - { - return $this->_failedRecipients; - } - - /** - * Set the result of sending. - * - * @param int $result - */ - public function setResult($result) - { - $this->_result = $result; - } - - /** - * Get the result of this Event. - * - * The return value is a bitmask from - * {@see RESULT_PENDING, RESULT_SUCCESS, RESULT_TENTATIVE, RESULT_FAILED} - * - * @return int - */ - public function getResult() - { - return $this->_result; - } -} diff --git a/lib/swiftmailer/swiftmailer/lib/classes/Swift/Events/SendListener.php b/lib/swiftmailer/swiftmailer/lib/classes/Swift/Events/SendListener.php deleted file mode 100644 index d922e1bfa..000000000 --- a/lib/swiftmailer/swiftmailer/lib/classes/Swift/Events/SendListener.php +++ /dev/null @@ -1,31 +0,0 @@ -_eventMap = array( - 'Swift_Events_CommandEvent' => 'Swift_Events_CommandListener', - 'Swift_Events_ResponseEvent' => 'Swift_Events_ResponseListener', - 'Swift_Events_SendEvent' => 'Swift_Events_SendListener', - 'Swift_Events_TransportChangeEvent' => 'Swift_Events_TransportChangeListener', - 'Swift_Events_TransportExceptionEvent' => 'Swift_Events_TransportExceptionListener', - ); - } - - /** - * Create a new SendEvent for $source and $message. - * - * @param Swift_Transport $source - * @param Swift_Mime_Message - * - * @return Swift_Events_SendEvent - */ - public function createSendEvent(Swift_Transport $source, Swift_Mime_Message $message) - { - return new Swift_Events_SendEvent($source, $message); - } - - /** - * Create a new CommandEvent for $source and $command. - * - * @param Swift_Transport $source - * @param string $command That will be executed - * @param array $successCodes That are needed - * - * @return Swift_Events_CommandEvent - */ - public function createCommandEvent(Swift_Transport $source, $command, $successCodes = array()) - { - return new Swift_Events_CommandEvent($source, $command, $successCodes); - } - - /** - * Create a new ResponseEvent for $source and $response. - * - * @param Swift_Transport $source - * @param string $response - * @param bool $valid If the response is valid - * - * @return Swift_Events_ResponseEvent - */ - public function createResponseEvent(Swift_Transport $source, $response, $valid) - { - return new Swift_Events_ResponseEvent($source, $response, $valid); - } - - /** - * Create a new TransportChangeEvent for $source. - * - * @param Swift_Transport $source - * - * @return Swift_Events_TransportChangeEvent - */ - public function createTransportChangeEvent(Swift_Transport $source) - { - return new Swift_Events_TransportChangeEvent($source); - } - - /** - * Create a new TransportExceptionEvent for $source. - * - * @param Swift_Transport $source - * @param Swift_TransportException $ex - * - * @return Swift_Events_TransportExceptionEvent - */ - public function createTransportExceptionEvent(Swift_Transport $source, Swift_TransportException $ex) - { - return new Swift_Events_TransportExceptionEvent($source, $ex); - } - - /** - * Bind an event listener to this dispatcher. - * - * @param Swift_Events_EventListener $listener - */ - public function bindEventListener(Swift_Events_EventListener $listener) - { - foreach ($this->_listeners as $l) { - // Already loaded - if ($l === $listener) { - return; - } - } - $this->_listeners[] = $listener; - } - - /** - * Dispatch the given Event to all suitable listeners. - * - * @param Swift_Events_EventObject $evt - * @param string $target method - */ - public function dispatchEvent(Swift_Events_EventObject $evt, $target) - { - $this->_prepareBubbleQueue($evt); - $this->_bubble($evt, $target); - } - - /** Queue listeners on a stack ready for $evt to be bubbled up it */ - private function _prepareBubbleQueue(Swift_Events_EventObject $evt) - { - $this->_bubbleQueue = array(); - $evtClass = get_class($evt); - foreach ($this->_listeners as $listener) { - if (array_key_exists($evtClass, $this->_eventMap) - && ($listener instanceof $this->_eventMap[$evtClass])) { - $this->_bubbleQueue[] = $listener; - } - } - } - - /** Bubble $evt up the stack calling $target() on each listener */ - private function _bubble(Swift_Events_EventObject $evt, $target) - { - if (!$evt->bubbleCancelled() && $listener = array_shift($this->_bubbleQueue)) { - $listener->$target($evt); - $this->_bubble($evt, $target); - } - } -} diff --git a/lib/swiftmailer/swiftmailer/lib/classes/Swift/Events/TransportChangeEvent.php b/lib/swiftmailer/swiftmailer/lib/classes/Swift/Events/TransportChangeEvent.php deleted file mode 100644 index a8972fda9..000000000 --- a/lib/swiftmailer/swiftmailer/lib/classes/Swift/Events/TransportChangeEvent.php +++ /dev/null @@ -1,27 +0,0 @@ -getSource(); - } -} diff --git a/lib/swiftmailer/swiftmailer/lib/classes/Swift/Events/TransportChangeListener.php b/lib/swiftmailer/swiftmailer/lib/classes/Swift/Events/TransportChangeListener.php deleted file mode 100644 index 253165de8..000000000 --- a/lib/swiftmailer/swiftmailer/lib/classes/Swift/Events/TransportChangeListener.php +++ /dev/null @@ -1,45 +0,0 @@ -_exception = $ex; - } - - /** - * Get the TransportException thrown. - * - * @return Swift_TransportException - */ - public function getException() - { - return $this->_exception; - } -} diff --git a/lib/swiftmailer/swiftmailer/lib/classes/Swift/Events/TransportExceptionListener.php b/lib/swiftmailer/swiftmailer/lib/classes/Swift/Events/TransportExceptionListener.php deleted file mode 100644 index cc3c09937..000000000 --- a/lib/swiftmailer/swiftmailer/lib/classes/Swift/Events/TransportExceptionListener.php +++ /dev/null @@ -1,24 +0,0 @@ -createDependenciesFor('transport.failover') - ); - - $this->setTransports($transports); - } - - /** - * Create a new FailoverTransport instance. - * - * @param Swift_Transport[] $transports - * - * @return self - */ - public static function newInstance($transports = array()) - { - return new self($transports); - } -} diff --git a/lib/swiftmailer/swiftmailer/lib/classes/Swift/FileSpool.php b/lib/swiftmailer/swiftmailer/lib/classes/Swift/FileSpool.php deleted file mode 100644 index c82c5dbf1..000000000 --- a/lib/swiftmailer/swiftmailer/lib/classes/Swift/FileSpool.php +++ /dev/null @@ -1,208 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -/** - * Stores Messages on the filesystem. - * - * @author Fabien Potencier - * @author Xavier De Cock - */ -class Swift_FileSpool extends Swift_ConfigurableSpool -{ - /** The spool directory */ - private $_path; - - /** - * File WriteRetry Limit. - * - * @var int - */ - private $_retryLimit = 10; - - /** - * Create a new FileSpool. - * - * @param string $path - * - * @throws Swift_IoException - */ - public function __construct($path) - { - $this->_path = $path; - - if (!file_exists($this->_path)) { - if (!mkdir($this->_path, 0777, true)) { - throw new Swift_IoException(sprintf('Unable to create path "%s".', $this->_path)); - } - } - } - - /** - * Tests if this Spool mechanism has started. - * - * @return bool - */ - public function isStarted() - { - return true; - } - - /** - * Starts this Spool mechanism. - */ - public function start() - { - } - - /** - * Stops this Spool mechanism. - */ - public function stop() - { - } - - /** - * Allow to manage the enqueuing retry limit. - * - * Default, is ten and allows over 64^20 different fileNames - * - * @param int $limit - */ - public function setRetryLimit($limit) - { - $this->_retryLimit = $limit; - } - - /** - * Queues a message. - * - * @param Swift_Mime_Message $message The message to store - * - * @throws Swift_IoException - * - * @return bool - */ - public function queueMessage(Swift_Mime_Message $message) - { - $ser = serialize($message); - $fileName = $this->_path.'/'.$this->getRandomString(10); - for ($i = 0; $i < $this->_retryLimit; ++$i) { - /* We try an exclusive creation of the file. This is an atomic operation, it avoid locking mechanism */ - $fp = @fopen($fileName.'.message', 'x'); - if (false !== $fp) { - if (false === fwrite($fp, $ser)) { - return false; - } - - return fclose($fp); - } else { - /* The file already exists, we try a longer fileName */ - $fileName .= $this->getRandomString(1); - } - } - - throw new Swift_IoException(sprintf('Unable to create a file for enqueuing Message in "%s".', $this->_path)); - } - - /** - * Execute a recovery if for any reason a process is sending for too long. - * - * @param int $timeout in second Defaults is for very slow smtp responses - */ - public function recover($timeout = 900) - { - foreach (new DirectoryIterator($this->_path) as $file) { - $file = $file->getRealPath(); - - if (substr($file, -16) == '.message.sending') { - $lockedtime = filectime($file); - if ((time() - $lockedtime) > $timeout) { - rename($file, substr($file, 0, -8)); - } - } - } - } - - /** - * Sends messages using the given transport instance. - * - * @param Swift_Transport $transport A transport instance - * @param string[] $failedRecipients An array of failures by-reference - * - * @return int The number of sent e-mail's - */ - public function flushQueue(Swift_Transport $transport, &$failedRecipients = null) - { - $directoryIterator = new DirectoryIterator($this->_path); - - /* Start the transport only if there are queued files to send */ - if (!$transport->isStarted()) { - foreach ($directoryIterator as $file) { - if (substr($file->getRealPath(), -8) == '.message') { - $transport->start(); - break; - } - } - } - - $failedRecipients = (array) $failedRecipients; - $count = 0; - $time = time(); - foreach ($directoryIterator as $file) { - $file = $file->getRealPath(); - - if (substr($file, -8) != '.message') { - continue; - } - - /* We try a rename, it's an atomic operation, and avoid locking the file */ - if (rename($file, $file.'.sending')) { - $message = unserialize(file_get_contents($file.'.sending')); - - $count += $transport->send($message, $failedRecipients); - - unlink($file.'.sending'); - } else { - /* This message has just been catched by another process */ - continue; - } - - if ($this->getMessageLimit() && $count >= $this->getMessageLimit()) { - break; - } - - if ($this->getTimeLimit() && (time() - $time) >= $this->getTimeLimit()) { - break; - } - } - - return $count; - } - - /** - * Returns a random string needed to generate a fileName for the queue. - * - * @param int $count - * - * @return string - */ - protected function getRandomString($count) - { - // This string MUST stay FS safe, avoid special chars - $base = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_-'; - $ret = ''; - $strlen = strlen($base); - for ($i = 0; $i < $count; ++$i) { - $ret .= $base[((int) rand(0, $strlen - 1))]; - } - - return $ret; - } -} diff --git a/lib/swiftmailer/swiftmailer/lib/classes/Swift/FileStream.php b/lib/swiftmailer/swiftmailer/lib/classes/Swift/FileStream.php deleted file mode 100644 index 0b24db1ce..000000000 --- a/lib/swiftmailer/swiftmailer/lib/classes/Swift/FileStream.php +++ /dev/null @@ -1,24 +0,0 @@ -setFile(new Swift_ByteStream_FileByteStream($path)); - } -} diff --git a/lib/swiftmailer/swiftmailer/lib/classes/Swift/InputByteStream.php b/lib/swiftmailer/swiftmailer/lib/classes/Swift/InputByteStream.php deleted file mode 100644 index 56efc7593..000000000 --- a/lib/swiftmailer/swiftmailer/lib/classes/Swift/InputByteStream.php +++ /dev/null @@ -1,75 +0,0 @@ -_stream = $stream; - } - - /** - * Set a string into the cache under $itemKey for the namespace $nsKey. - * - * @see MODE_WRITE, MODE_APPEND - * - * @param string $nsKey - * @param string $itemKey - * @param string $string - * @param int $mode - */ - public function setString($nsKey, $itemKey, $string, $mode) - { - $this->_prepareCache($nsKey); - switch ($mode) { - case self::MODE_WRITE: - $this->_contents[$nsKey][$itemKey] = $string; - break; - case self::MODE_APPEND: - if (!$this->hasKey($nsKey, $itemKey)) { - $this->_contents[$nsKey][$itemKey] = ''; - } - $this->_contents[$nsKey][$itemKey] .= $string; - break; - default: - throw new Swift_SwiftException( - 'Invalid mode ['.$mode.'] used to set nsKey='. - $nsKey.', itemKey='.$itemKey - ); - } - } - - /** - * Set a ByteStream into the cache under $itemKey for the namespace $nsKey. - * - * @see MODE_WRITE, MODE_APPEND - * - * @param string $nsKey - * @param string $itemKey - * @param Swift_OutputByteStream $os - * @param int $mode - */ - public function importFromByteStream($nsKey, $itemKey, Swift_OutputByteStream $os, $mode) - { - $this->_prepareCache($nsKey); - switch ($mode) { - case self::MODE_WRITE: - $this->clearKey($nsKey, $itemKey); - case self::MODE_APPEND: - if (!$this->hasKey($nsKey, $itemKey)) { - $this->_contents[$nsKey][$itemKey] = ''; - } - while (false !== $bytes = $os->read(8192)) { - $this->_contents[$nsKey][$itemKey] .= $bytes; - } - break; - default: - throw new Swift_SwiftException( - 'Invalid mode ['.$mode.'] used to set nsKey='. - $nsKey.', itemKey='.$itemKey - ); - } - } - - /** - * Provides a ByteStream which when written to, writes data to $itemKey. - * - * NOTE: The stream will always write in append mode. - * - * @param string $nsKey - * @param string $itemKey - * @param Swift_InputByteStream $writeThrough - * - * @return Swift_InputByteStream - */ - public function getInputByteStream($nsKey, $itemKey, Swift_InputByteStream $writeThrough = null) - { - $is = clone $this->_stream; - $is->setKeyCache($this); - $is->setNsKey($nsKey); - $is->setItemKey($itemKey); - if (isset($writeThrough)) { - $is->setWriteThroughStream($writeThrough); - } - - return $is; - } - - /** - * Get data back out of the cache as a string. - * - * @param string $nsKey - * @param string $itemKey - * - * @return string - */ - public function getString($nsKey, $itemKey) - { - $this->_prepareCache($nsKey); - if ($this->hasKey($nsKey, $itemKey)) { - return $this->_contents[$nsKey][$itemKey]; - } - } - - /** - * Get data back out of the cache as a ByteStream. - * - * @param string $nsKey - * @param string $itemKey - * @param Swift_InputByteStream $is to write the data to - */ - public function exportToByteStream($nsKey, $itemKey, Swift_InputByteStream $is) - { - $this->_prepareCache($nsKey); - $is->write($this->getString($nsKey, $itemKey)); - } - - /** - * Check if the given $itemKey exists in the namespace $nsKey. - * - * @param string $nsKey - * @param string $itemKey - * - * @return bool - */ - public function hasKey($nsKey, $itemKey) - { - $this->_prepareCache($nsKey); - - return array_key_exists($itemKey, $this->_contents[$nsKey]); - } - - /** - * Clear data for $itemKey in the namespace $nsKey if it exists. - * - * @param string $nsKey - * @param string $itemKey - */ - public function clearKey($nsKey, $itemKey) - { - unset($this->_contents[$nsKey][$itemKey]); - } - - /** - * Clear all data in the namespace $nsKey if it exists. - * - * @param string $nsKey - */ - public function clearAll($nsKey) - { - unset($this->_contents[$nsKey]); - } - - /** - * Initialize the namespace of $nsKey if needed. - * - * @param string $nsKey - */ - private function _prepareCache($nsKey) - { - if (!array_key_exists($nsKey, $this->_contents)) { - $this->_contents[$nsKey] = array(); - } - } -} diff --git a/lib/swiftmailer/swiftmailer/lib/classes/Swift/KeyCache/DiskKeyCache.php b/lib/swiftmailer/swiftmailer/lib/classes/Swift/KeyCache/DiskKeyCache.php deleted file mode 100644 index 453f50a15..000000000 --- a/lib/swiftmailer/swiftmailer/lib/classes/Swift/KeyCache/DiskKeyCache.php +++ /dev/null @@ -1,321 +0,0 @@ -_stream = $stream; - $this->_path = $path; - - if (function_exists('get_magic_quotes_runtime') && @get_magic_quotes_runtime() == 1) { - $this->_quotes = true; - } - } - - /** - * Set a string into the cache under $itemKey for the namespace $nsKey. - * - * @see MODE_WRITE, MODE_APPEND - * - * @param string $nsKey - * @param string $itemKey - * @param string $string - * @param int $mode - * - * @throws Swift_IoException - */ - public function setString($nsKey, $itemKey, $string, $mode) - { - $this->_prepareCache($nsKey); - switch ($mode) { - case self::MODE_WRITE: - $fp = $this->_getHandle($nsKey, $itemKey, self::POSITION_START); - break; - case self::MODE_APPEND: - $fp = $this->_getHandle($nsKey, $itemKey, self::POSITION_END); - break; - default: - throw new Swift_SwiftException( - 'Invalid mode ['.$mode.'] used to set nsKey='. - $nsKey.', itemKey='.$itemKey - ); - break; - } - fwrite($fp, $string); - $this->_freeHandle($nsKey, $itemKey); - } - - /** - * Set a ByteStream into the cache under $itemKey for the namespace $nsKey. - * - * @see MODE_WRITE, MODE_APPEND - * - * @param string $nsKey - * @param string $itemKey - * @param Swift_OutputByteStream $os - * @param int $mode - * - * @throws Swift_IoException - */ - public function importFromByteStream($nsKey, $itemKey, Swift_OutputByteStream $os, $mode) - { - $this->_prepareCache($nsKey); - switch ($mode) { - case self::MODE_WRITE: - $fp = $this->_getHandle($nsKey, $itemKey, self::POSITION_START); - break; - case self::MODE_APPEND: - $fp = $this->_getHandle($nsKey, $itemKey, self::POSITION_END); - break; - default: - throw new Swift_SwiftException( - 'Invalid mode ['.$mode.'] used to set nsKey='. - $nsKey.', itemKey='.$itemKey - ); - break; - } - while (false !== $bytes = $os->read(8192)) { - fwrite($fp, $bytes); - } - $this->_freeHandle($nsKey, $itemKey); - } - - /** - * Provides a ByteStream which when written to, writes data to $itemKey. - * - * NOTE: The stream will always write in append mode. - * - * @param string $nsKey - * @param string $itemKey - * @param Swift_InputByteStream $writeThrough - * - * @return Swift_InputByteStream - */ - public function getInputByteStream($nsKey, $itemKey, Swift_InputByteStream $writeThrough = null) - { - $is = clone $this->_stream; - $is->setKeyCache($this); - $is->setNsKey($nsKey); - $is->setItemKey($itemKey); - if (isset($writeThrough)) { - $is->setWriteThroughStream($writeThrough); - } - - return $is; - } - - /** - * Get data back out of the cache as a string. - * - * @param string $nsKey - * @param string $itemKey - * - * @throws Swift_IoException - * - * @return string - */ - public function getString($nsKey, $itemKey) - { - $this->_prepareCache($nsKey); - if ($this->hasKey($nsKey, $itemKey)) { - $fp = $this->_getHandle($nsKey, $itemKey, self::POSITION_START); - if ($this->_quotes) { - ini_set('magic_quotes_runtime', 0); - } - $str = ''; - while (!feof($fp) && false !== $bytes = fread($fp, 8192)) { - $str .= $bytes; - } - if ($this->_quotes) { - ini_set('magic_quotes_runtime', 1); - } - $this->_freeHandle($nsKey, $itemKey); - - return $str; - } - } - - /** - * Get data back out of the cache as a ByteStream. - * - * @param string $nsKey - * @param string $itemKey - * @param Swift_InputByteStream $is to write the data to - */ - public function exportToByteStream($nsKey, $itemKey, Swift_InputByteStream $is) - { - if ($this->hasKey($nsKey, $itemKey)) { - $fp = $this->_getHandle($nsKey, $itemKey, self::POSITION_START); - if ($this->_quotes) { - ini_set('magic_quotes_runtime', 0); - } - while (!feof($fp) && false !== $bytes = fread($fp, 8192)) { - $is->write($bytes); - } - if ($this->_quotes) { - ini_set('magic_quotes_runtime', 1); - } - $this->_freeHandle($nsKey, $itemKey); - } - } - - /** - * Check if the given $itemKey exists in the namespace $nsKey. - * - * @param string $nsKey - * @param string $itemKey - * - * @return bool - */ - public function hasKey($nsKey, $itemKey) - { - return is_file($this->_path.'/'.$nsKey.'/'.$itemKey); - } - - /** - * Clear data for $itemKey in the namespace $nsKey if it exists. - * - * @param string $nsKey - * @param string $itemKey - */ - public function clearKey($nsKey, $itemKey) - { - if ($this->hasKey($nsKey, $itemKey)) { - $this->_freeHandle($nsKey, $itemKey); - unlink($this->_path.'/'.$nsKey.'/'.$itemKey); - } - } - - /** - * Clear all data in the namespace $nsKey if it exists. - * - * @param string $nsKey - */ - public function clearAll($nsKey) - { - if (array_key_exists($nsKey, $this->_keys)) { - foreach ($this->_keys[$nsKey] as $itemKey => $null) { - $this->clearKey($nsKey, $itemKey); - } - if (is_dir($this->_path.'/'.$nsKey)) { - rmdir($this->_path.'/'.$nsKey); - } - unset($this->_keys[$nsKey]); - } - } - - /** - * Initialize the namespace of $nsKey if needed. - * - * @param string $nsKey - */ - private function _prepareCache($nsKey) - { - $cacheDir = $this->_path.'/'.$nsKey; - if (!is_dir($cacheDir)) { - if (!mkdir($cacheDir)) { - throw new Swift_IoException('Failed to create cache directory '.$cacheDir); - } - $this->_keys[$nsKey] = array(); - } - } - - /** - * Get a file handle on the cache item. - * - * @param string $nsKey - * @param string $itemKey - * @param int $position - * - * @return resource - */ - private function _getHandle($nsKey, $itemKey, $position) - { - if (!isset($this->_keys[$nsKey][$itemKey])) { - $openMode = $this->hasKey($nsKey, $itemKey) ? 'r+b' : 'w+b'; - $fp = fopen($this->_path.'/'.$nsKey.'/'.$itemKey, $openMode); - $this->_keys[$nsKey][$itemKey] = $fp; - } - if (self::POSITION_START == $position) { - fseek($this->_keys[$nsKey][$itemKey], 0, SEEK_SET); - } elseif (self::POSITION_END == $position) { - fseek($this->_keys[$nsKey][$itemKey], 0, SEEK_END); - } - - return $this->_keys[$nsKey][$itemKey]; - } - - private function _freeHandle($nsKey, $itemKey) - { - $fp = $this->_getHandle($nsKey, $itemKey, self::POSITION_CURRENT); - fclose($fp); - $this->_keys[$nsKey][$itemKey] = null; - } - - /** - * Destructor. - */ - public function __destruct() - { - foreach ($this->_keys as $nsKey => $null) { - $this->clearAll($nsKey); - } - } -} diff --git a/lib/swiftmailer/swiftmailer/lib/classes/Swift/KeyCache/KeyCacheInputStream.php b/lib/swiftmailer/swiftmailer/lib/classes/Swift/KeyCache/KeyCacheInputStream.php deleted file mode 100644 index af80bdca6..000000000 --- a/lib/swiftmailer/swiftmailer/lib/classes/Swift/KeyCache/KeyCacheInputStream.php +++ /dev/null @@ -1,51 +0,0 @@ -_keyCache = $keyCache; - } - - /** - * Specify a stream to write through for each write(). - * - * @param Swift_InputByteStream $is - */ - public function setWriteThroughStream(Swift_InputByteStream $is) - { - $this->_writeThrough = $is; - } - - /** - * Writes $bytes to the end of the stream. - * - * @param string $bytes - * @param Swift_InputByteStream $is optional - */ - public function write($bytes, Swift_InputByteStream $is = null) - { - $this->_keyCache->setString( - $this->_nsKey, $this->_itemKey, $bytes, Swift_KeyCache::MODE_APPEND - ); - if (isset($is)) { - $is->write($bytes); - } - if (isset($this->_writeThrough)) { - $this->_writeThrough->write($bytes); - } - } - - /** - * Not used. - */ - public function commit() - { - } - - /** - * Not used. - */ - public function bind(Swift_InputByteStream $is) - { - } - - /** - * Not used. - */ - public function unbind(Swift_InputByteStream $is) - { - } - - /** - * Flush the contents of the stream (empty it) and set the internal pointer - * to the beginning. - */ - public function flushBuffers() - { - $this->_keyCache->clearKey($this->_nsKey, $this->_itemKey); - } - - /** - * Set the nsKey which will be written to. - * - * @param string $nsKey - */ - public function setNsKey($nsKey) - { - $this->_nsKey = $nsKey; - } - - /** - * Set the itemKey which will be written to. - * - * @param string $itemKey - */ - public function setItemKey($itemKey) - { - $this->_itemKey = $itemKey; - } - - /** - * Any implementation should be cloneable, allowing the clone to access a - * separate $nsKey and $itemKey. - */ - public function __clone() - { - $this->_writeThrough = null; - } -} diff --git a/lib/swiftmailer/swiftmailer/lib/classes/Swift/LoadBalancedTransport.php b/lib/swiftmailer/swiftmailer/lib/classes/Swift/LoadBalancedTransport.php deleted file mode 100644 index e151b8a9c..000000000 --- a/lib/swiftmailer/swiftmailer/lib/classes/Swift/LoadBalancedTransport.php +++ /dev/null @@ -1,45 +0,0 @@ -createDependenciesFor('transport.loadbalanced') - ); - - $this->setTransports($transports); - } - - /** - * Create a new LoadBalancedTransport instance. - * - * @param array $transports - * - * @return self - */ - public static function newInstance($transports = array()) - { - return new self($transports); - } -} diff --git a/lib/swiftmailer/swiftmailer/lib/classes/Swift/MailTransport.php b/lib/swiftmailer/swiftmailer/lib/classes/Swift/MailTransport.php deleted file mode 100644 index 18556989a..000000000 --- a/lib/swiftmailer/swiftmailer/lib/classes/Swift/MailTransport.php +++ /dev/null @@ -1,47 +0,0 @@ -createDependenciesFor('transport.mail') - ); - - $this->setExtraParams($extraParams); - } - - /** - * Create a new MailTransport instance. - * - * @param string $extraParams To be passed to mail() - * - * @return self - */ - public static function newInstance($extraParams = '-f%s') - { - return new self($extraParams); - } -} diff --git a/lib/swiftmailer/swiftmailer/lib/classes/Swift/Mailer.php b/lib/swiftmailer/swiftmailer/lib/classes/Swift/Mailer.php deleted file mode 100644 index 8314fe8fc..000000000 --- a/lib/swiftmailer/swiftmailer/lib/classes/Swift/Mailer.php +++ /dev/null @@ -1,114 +0,0 @@ -_transport = $transport; - } - - /** - * Create a new Mailer instance. - * - * @param Swift_Transport $transport - * - * @return self - */ - public static function newInstance(Swift_Transport $transport) - { - return new self($transport); - } - - /** - * Create a new class instance of one of the message services. - * - * For example 'mimepart' would create a 'message.mimepart' instance - * - * @param string $service - * - * @return object - */ - public function createMessage($service = 'message') - { - return Swift_DependencyContainer::getInstance() - ->lookup('message.'.$service); - } - - /** - * Send the given Message like it would be sent in a mail client. - * - * All recipients (with the exception of Bcc) will be able to see the other - * recipients this message was sent to. - * - * Recipient/sender data will be retrieved from the Message object. - * - * The return value is the number of recipients who were accepted for - * delivery. - * - * @param Swift_Mime_Message $message - * @param array $failedRecipients An array of failures by-reference - * - * @return int The number of successful recipients. Can be 0 which indicates failure - */ - public function send(Swift_Mime_Message $message, &$failedRecipients = null) - { - $failedRecipients = (array) $failedRecipients; - - if (!$this->_transport->isStarted()) { - $this->_transport->start(); - } - - $sent = 0; - - try { - $sent = $this->_transport->send($message, $failedRecipients); - } catch (Swift_RfcComplianceException $e) { - foreach ($message->getTo() as $address => $name) { - $failedRecipients[] = $address; - } - } - - return $sent; - } - - /** - * Register a plugin using a known unique key (e.g. myPlugin). - * - * @param Swift_Events_EventListener $plugin - */ - public function registerPlugin(Swift_Events_EventListener $plugin) - { - $this->_transport->registerPlugin($plugin); - } - - /** - * The Transport used to send messages. - * - * @return Swift_Transport - */ - public function getTransport() - { - return $this->_transport; - } -} diff --git a/lib/swiftmailer/swiftmailer/lib/classes/Swift/Mailer/ArrayRecipientIterator.php b/lib/swiftmailer/swiftmailer/lib/classes/Swift/Mailer/ArrayRecipientIterator.php deleted file mode 100644 index e3e6cad05..000000000 --- a/lib/swiftmailer/swiftmailer/lib/classes/Swift/Mailer/ArrayRecipientIterator.php +++ /dev/null @@ -1,55 +0,0 @@ -_recipients = $recipients; - } - - /** - * Returns true only if there are more recipients to send to. - * - * @return bool - */ - public function hasNext() - { - return !empty($this->_recipients); - } - - /** - * Returns an array where the keys are the addresses of recipients and the - * values are the names. e.g. ('foo@bar' => 'Foo') or ('foo@bar' => NULL). - * - * @return array - */ - public function nextRecipient() - { - return array_splice($this->_recipients, 0, 1); - } -} diff --git a/lib/swiftmailer/swiftmailer/lib/classes/Swift/Mailer/RecipientIterator.php b/lib/swiftmailer/swiftmailer/lib/classes/Swift/Mailer/RecipientIterator.php deleted file mode 100644 index 650f3ec3d..000000000 --- a/lib/swiftmailer/swiftmailer/lib/classes/Swift/Mailer/RecipientIterator.php +++ /dev/null @@ -1,32 +0,0 @@ - 'Foo') or ('foo@bar' => NULL). - * - * @return array - */ - public function nextRecipient(); -} diff --git a/lib/swiftmailer/swiftmailer/lib/classes/Swift/MemorySpool.php b/lib/swiftmailer/swiftmailer/lib/classes/Swift/MemorySpool.php deleted file mode 100644 index 2cafb6751..000000000 --- a/lib/swiftmailer/swiftmailer/lib/classes/Swift/MemorySpool.php +++ /dev/null @@ -1,110 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -/** - * Stores Messages in memory. - * - * @author Fabien Potencier - */ -class Swift_MemorySpool implements Swift_Spool -{ - protected $messages = array(); - private $flushRetries = 3; - - /** - * Tests if this Transport mechanism has started. - * - * @return bool - */ - public function isStarted() - { - return true; - } - - /** - * Starts this Transport mechanism. - */ - public function start() - { - } - - /** - * Stops this Transport mechanism. - */ - public function stop() - { - } - - /** - * @param int $retries - */ - public function setFlushRetries($retries) - { - $this->flushRetries = $retries; - } - - /** - * Stores a message in the queue. - * - * @param Swift_Mime_Message $message The message to store - * - * @return bool Whether the operation has succeeded - */ - public function queueMessage(Swift_Mime_Message $message) - { - //clone the message to make sure it is not changed while in the queue - $this->messages[] = clone $message; - - return true; - } - - /** - * Sends messages using the given transport instance. - * - * @param Swift_Transport $transport A transport instance - * @param string[] $failedRecipients An array of failures by-reference - * - * @return int The number of sent emails - */ - public function flushQueue(Swift_Transport $transport, &$failedRecipients = null) - { - if (!$this->messages) { - return 0; - } - - if (!$transport->isStarted()) { - $transport->start(); - } - - $count = 0; - $retries = $this->flushRetries; - while ($retries--) { - try { - while ($message = array_pop($this->messages)) { - $count += $transport->send($message, $failedRecipients); - } - } catch (Swift_TransportException $exception) { - if ($retries) { - // re-queue the message at the end of the queue to give a chance - // to the other messages to be sent, in case the failure was due to - // this message and not just the transport failing - array_unshift($this->messages, $message); - - // wait half a second before we try again - usleep(500000); - } else { - throw $exception; - } - } - } - - return $count; - } -} diff --git a/lib/swiftmailer/swiftmailer/lib/classes/Swift/Message.php b/lib/swiftmailer/swiftmailer/lib/classes/Swift/Message.php deleted file mode 100644 index 242cbf314..000000000 --- a/lib/swiftmailer/swiftmailer/lib/classes/Swift/Message.php +++ /dev/null @@ -1,289 +0,0 @@ -createDependenciesFor('mime.message') - ); - - if (!isset($charset)) { - $charset = Swift_DependencyContainer::getInstance() - ->lookup('properties.charset'); - } - $this->setSubject($subject); - $this->setBody($body); - $this->setCharset($charset); - if ($contentType) { - $this->setContentType($contentType); - } - } - - /** - * Create a new Message. - * - * @param string $subject - * @param string $body - * @param string $contentType - * @param string $charset - * - * @return $this - */ - public static function newInstance($subject = null, $body = null, $contentType = null, $charset = null) - { - return new self($subject, $body, $contentType, $charset); - } - - /** - * Add a MimePart to this Message. - * - * @param string|Swift_OutputByteStream $body - * @param string $contentType - * @param string $charset - * - * @return $this - */ - public function addPart($body, $contentType = null, $charset = null) - { - return $this->attach(Swift_MimePart::newInstance($body, $contentType, $charset)->setEncoder($this->getEncoder())); - } - - /** - * Detach a signature handler from a message. - * - * @param Swift_Signer $signer - * - * @return $this - */ - public function attachSigner(Swift_Signer $signer) - { - if ($signer instanceof Swift_Signers_HeaderSigner) { - $this->headerSigners[] = $signer; - } elseif ($signer instanceof Swift_Signers_BodySigner) { - $this->bodySigners[] = $signer; - } - - return $this; - } - - /** - * Attach a new signature handler to the message. - * - * @param Swift_Signer $signer - * - * @return $this - */ - public function detachSigner(Swift_Signer $signer) - { - if ($signer instanceof Swift_Signers_HeaderSigner) { - foreach ($this->headerSigners as $k => $headerSigner) { - if ($headerSigner === $signer) { - unset($this->headerSigners[$k]); - - return $this; - } - } - } elseif ($signer instanceof Swift_Signers_BodySigner) { - foreach ($this->bodySigners as $k => $bodySigner) { - if ($bodySigner === $signer) { - unset($this->bodySigners[$k]); - - return $this; - } - } - } - - return $this; - } - - /** - * Get this message as a complete string. - * - * @return string - */ - public function toString() - { - if (empty($this->headerSigners) && empty($this->bodySigners)) { - return parent::toString(); - } - - $this->saveMessage(); - - $this->doSign(); - - $string = parent::toString(); - - $this->restoreMessage(); - - return $string; - } - - /** - * Write this message to a {@link Swift_InputByteStream}. - * - * @param Swift_InputByteStream $is - */ - public function toByteStream(Swift_InputByteStream $is) - { - if (empty($this->headerSigners) && empty($this->bodySigners)) { - parent::toByteStream($is); - - return; - } - - $this->saveMessage(); - - $this->doSign(); - - parent::toByteStream($is); - - $this->restoreMessage(); - } - - public function __wakeup() - { - Swift_DependencyContainer::getInstance()->createDependenciesFor('mime.message'); - } - - /** - * loops through signers and apply the signatures. - */ - protected function doSign() - { - foreach ($this->bodySigners as $signer) { - $altered = $signer->getAlteredHeaders(); - $this->saveHeaders($altered); - $signer->signMessage($this); - } - - foreach ($this->headerSigners as $signer) { - $altered = $signer->getAlteredHeaders(); - $this->saveHeaders($altered); - $signer->reset(); - - $signer->setHeaders($this->getHeaders()); - - $signer->startBody(); - $this->_bodyToByteStream($signer); - $signer->endBody(); - - $signer->addSignature($this->getHeaders()); - } - } - - /** - * save the message before any signature is applied. - */ - protected function saveMessage() - { - $this->savedMessage = array('headers' => array()); - $this->savedMessage['body'] = $this->getBody(); - $this->savedMessage['children'] = $this->getChildren(); - if (count($this->savedMessage['children']) > 0 && $this->getBody() != '') { - $this->setChildren(array_merge(array($this->_becomeMimePart()), $this->savedMessage['children'])); - $this->setBody(''); - } - } - - /** - * save the original headers. - * - * @param array $altered - */ - protected function saveHeaders(array $altered) - { - foreach ($altered as $head) { - $lc = strtolower($head); - - if (!isset($this->savedMessage['headers'][$lc])) { - $this->savedMessage['headers'][$lc] = $this->getHeaders()->getAll($head); - } - } - } - - /** - * Remove or restore altered headers. - */ - protected function restoreHeaders() - { - foreach ($this->savedMessage['headers'] as $name => $savedValue) { - $headers = $this->getHeaders()->getAll($name); - - foreach ($headers as $key => $value) { - if (!isset($savedValue[$key])) { - $this->getHeaders()->remove($name, $key); - } - } - } - } - - /** - * Restore message body. - */ - protected function restoreMessage() - { - $this->setBody($this->savedMessage['body']); - $this->setChildren($this->savedMessage['children']); - - $this->restoreHeaders(); - $this->savedMessage = array(); - } - - /** - * Clone Message Signers. - * - * @see Swift_Mime_SimpleMimeEntity::__clone() - */ - public function __clone() - { - parent::__clone(); - foreach ($this->bodySigners as $key => $bodySigner) { - $this->bodySigners[$key] = clone $bodySigner; - } - - foreach ($this->headerSigners as $key => $headerSigner) { - $this->headerSigners[$key] = clone $headerSigner; - } - } -} diff --git a/lib/swiftmailer/swiftmailer/lib/classes/Swift/Mime/Attachment.php b/lib/swiftmailer/swiftmailer/lib/classes/Swift/Mime/Attachment.php deleted file mode 100644 index d5ba14b91..000000000 --- a/lib/swiftmailer/swiftmailer/lib/classes/Swift/Mime/Attachment.php +++ /dev/null @@ -1,149 +0,0 @@ -setDisposition('attachment'); - $this->setContentType('application/octet-stream'); - $this->_mimeTypes = $mimeTypes; - } - - /** - * Get the nesting level used for this attachment. - * - * Always returns {@link LEVEL_MIXED}. - * - * @return int - */ - public function getNestingLevel() - { - return self::LEVEL_MIXED; - } - - /** - * Get the Content-Disposition of this attachment. - * - * By default attachments have a disposition of "attachment". - * - * @return string - */ - public function getDisposition() - { - return $this->_getHeaderFieldModel('Content-Disposition'); - } - - /** - * Set the Content-Disposition of this attachment. - * - * @param string $disposition - * - * @return $this - */ - public function setDisposition($disposition) - { - if (!$this->_setHeaderFieldModel('Content-Disposition', $disposition)) { - $this->getHeaders()->addParameterizedHeader('Content-Disposition', $disposition); - } - - return $this; - } - - /** - * Get the filename of this attachment when downloaded. - * - * @return string - */ - public function getFilename() - { - return $this->_getHeaderParameter('Content-Disposition', 'filename'); - } - - /** - * Set the filename of this attachment. - * - * @param string $filename - * - * @return $this - */ - public function setFilename($filename) - { - $this->_setHeaderParameter('Content-Disposition', 'filename', $filename); - $this->_setHeaderParameter('Content-Type', 'name', $filename); - - return $this; - } - - /** - * Get the file size of this attachment. - * - * @return int - */ - public function getSize() - { - return $this->_getHeaderParameter('Content-Disposition', 'size'); - } - - /** - * Set the file size of this attachment. - * - * @param int $size - * - * @return $this - */ - public function setSize($size) - { - $this->_setHeaderParameter('Content-Disposition', 'size', $size); - - return $this; - } - - /** - * Set the file that this attachment is for. - * - * @param Swift_FileStream $file - * @param string $contentType optional - * - * @return $this - */ - public function setFile(Swift_FileStream $file, $contentType = null) - { - $this->setFilename(basename($file->getPath())); - $this->setBody($file, $contentType); - if (!isset($contentType)) { - $extension = strtolower(substr($file->getPath(), strrpos($file->getPath(), '.') + 1)); - - if (array_key_exists($extension, $this->_mimeTypes)) { - $this->setContentType($this->_mimeTypes[$extension]); - } - } - - return $this; - } -} diff --git a/lib/swiftmailer/swiftmailer/lib/classes/Swift/Mime/CharsetObserver.php b/lib/swiftmailer/swiftmailer/lib/classes/Swift/Mime/CharsetObserver.php deleted file mode 100644 index b49c3a873..000000000 --- a/lib/swiftmailer/swiftmailer/lib/classes/Swift/Mime/CharsetObserver.php +++ /dev/null @@ -1,24 +0,0 @@ -= $maxLineLength || 76 < $maxLineLength) { - $maxLineLength = 76; - } - - $remainder = 0; - $base64ReadBufferRemainderBytes = null; - - // To reduce memory usage, the output buffer is streamed to the input buffer like so: - // Output Stream => base64encode => wrap line length => Input Stream - // HOWEVER it's important to note that base64_encode() should only be passed whole triplets of data (except for the final chunk of data) - // otherwise it will assume the input data has *ended* and it will incorrectly pad/terminate the base64 data mid-stream. - // We use $base64ReadBufferRemainderBytes to carry over 1-2 "remainder" bytes from the each chunk from OutputStream and pre-pend those onto the - // chunk of bytes read in the next iteration. - // When the OutputStream is empty, we must flush any remainder bytes. - while (true) { - $readBytes = $os->read(8192); - $atEOF = ($readBytes === false); - - if ($atEOF) { - $streamTheseBytes = $base64ReadBufferRemainderBytes; - } else { - $streamTheseBytes = $base64ReadBufferRemainderBytes.$readBytes; - } - $base64ReadBufferRemainderBytes = null; - $bytesLength = strlen($streamTheseBytes); - - if ($bytesLength === 0) { // no data left to encode - break; - } - - // if we're not on the last block of the ouput stream, make sure $streamTheseBytes ends with a complete triplet of data - // and carry over remainder 1-2 bytes to the next loop iteration - if (!$atEOF) { - $excessBytes = $bytesLength % 3; - if ($excessBytes !== 0) { - $base64ReadBufferRemainderBytes = substr($streamTheseBytes, -$excessBytes); - $streamTheseBytes = substr($streamTheseBytes, 0, $bytesLength - $excessBytes); - } - } - - $encoded = base64_encode($streamTheseBytes); - $encodedTransformed = ''; - $thisMaxLineLength = $maxLineLength - $remainder - $firstLineOffset; - - while ($thisMaxLineLength < strlen($encoded)) { - $encodedTransformed .= substr($encoded, 0, $thisMaxLineLength)."\r\n"; - $firstLineOffset = 0; - $encoded = substr($encoded, $thisMaxLineLength); - $thisMaxLineLength = $maxLineLength; - $remainder = 0; - } - - if (0 < $remainingLength = strlen($encoded)) { - $remainder += $remainingLength; - $encodedTransformed .= $encoded; - $encoded = null; - } - - $is->write($encodedTransformed); - - if ($atEOF) { - break; - } - } - } - - /** - * Get the name of this encoding scheme. - * Returns the string 'base64'. - * - * @return string - */ - public function getName() - { - return 'base64'; - } -} diff --git a/lib/swiftmailer/swiftmailer/lib/classes/Swift/Mime/ContentEncoder/NativeQpContentEncoder.php b/lib/swiftmailer/swiftmailer/lib/classes/Swift/Mime/ContentEncoder/NativeQpContentEncoder.php deleted file mode 100644 index 710b5ac9e..000000000 --- a/lib/swiftmailer/swiftmailer/lib/classes/Swift/Mime/ContentEncoder/NativeQpContentEncoder.php +++ /dev/null @@ -1,123 +0,0 @@ -charset = $charset ? $charset : 'utf-8'; - } - - /** - * Notify this observer that the entity's charset has changed. - * - * @param string $charset - */ - public function charsetChanged($charset) - { - $this->charset = $charset; - } - - /** - * Encode $in to $out. - * - * @param Swift_OutputByteStream $os to read from - * @param Swift_InputByteStream $is to write to - * @param int $firstLineOffset - * @param int $maxLineLength 0 indicates the default length for this encoding - * - * @throws RuntimeException - */ - public function encodeByteStream(Swift_OutputByteStream $os, Swift_InputByteStream $is, $firstLineOffset = 0, $maxLineLength = 0) - { - if ($this->charset !== 'utf-8') { - throw new RuntimeException( - sprintf('Charset "%s" not supported. NativeQpContentEncoder only supports "utf-8"', $this->charset)); - } - - $string = ''; - - while (false !== $bytes = $os->read(8192)) { - $string .= $bytes; - } - - $is->write($this->encodeString($string)); - } - - /** - * Get the MIME name of this content encoding scheme. - * - * @return string - */ - public function getName() - { - return 'quoted-printable'; - } - - /** - * Encode a given string to produce an encoded string. - * - * @param string $string - * @param int $firstLineOffset if first line needs to be shorter - * @param int $maxLineLength 0 indicates the default length for this encoding - * - * @throws RuntimeException - * - * @return string - */ - public function encodeString($string, $firstLineOffset = 0, $maxLineLength = 0) - { - if ($this->charset !== 'utf-8') { - throw new RuntimeException( - sprintf('Charset "%s" not supported. NativeQpContentEncoder only supports "utf-8"', $this->charset)); - } - - return $this->_standardize(quoted_printable_encode($string)); - } - - /** - * Make sure CRLF is correct and HT/SPACE are in valid places. - * - * @param string $string - * - * @return string - */ - protected function _standardize($string) - { - // transform CR or LF to CRLF - $string = preg_replace('~=0D(?!=0A)|(?_name = $name; - $this->_canonical = $canonical; - } - - /** - * Encode a given string to produce an encoded string. - * - * @param string $string - * @param int $firstLineOffset ignored - * @param int $maxLineLength - 0 means no wrapping will occur - * - * @return string - */ - public function encodeString($string, $firstLineOffset = 0, $maxLineLength = 0) - { - if ($this->_canonical) { - $string = $this->_canonicalize($string); - } - - return $this->_safeWordWrap($string, $maxLineLength, "\r\n"); - } - - /** - * Encode stream $in to stream $out. - * - * @param Swift_OutputByteStream $os - * @param Swift_InputByteStream $is - * @param int $firstLineOffset ignored - * @param int $maxLineLength optional, 0 means no wrapping will occur - */ - public function encodeByteStream(Swift_OutputByteStream $os, Swift_InputByteStream $is, $firstLineOffset = 0, $maxLineLength = 0) - { - $leftOver = ''; - while (false !== $bytes = $os->read(8192)) { - $toencode = $leftOver.$bytes; - if ($this->_canonical) { - $toencode = $this->_canonicalize($toencode); - } - $wrapped = $this->_safeWordWrap($toencode, $maxLineLength, "\r\n"); - $lastLinePos = strrpos($wrapped, "\r\n"); - $leftOver = substr($wrapped, $lastLinePos); - $wrapped = substr($wrapped, 0, $lastLinePos); - - $is->write($wrapped); - } - if (strlen($leftOver)) { - $is->write($leftOver); - } - } - - /** - * Get the name of this encoding scheme. - * - * @return string - */ - public function getName() - { - return $this->_name; - } - - /** - * Not used. - */ - public function charsetChanged($charset) - { - } - - /** - * A safer (but weaker) wordwrap for unicode. - * - * @param string $string - * @param int $length - * @param string $le - * - * @return string - */ - private function _safeWordwrap($string, $length = 75, $le = "\r\n") - { - if (0 >= $length) { - return $string; - } - - $originalLines = explode($le, $string); - - $lines = array(); - $lineCount = 0; - - foreach ($originalLines as $originalLine) { - $lines[] = ''; - $currentLine = &$lines[$lineCount++]; - - //$chunks = preg_split('/(?<=[\ \t,\.!\?\-&\+\/])/', $originalLine); - $chunks = preg_split('/(?<=\s)/', $originalLine); - - foreach ($chunks as $chunk) { - if (0 != strlen($currentLine) - && strlen($currentLine.$chunk) > $length) { - $lines[] = ''; - $currentLine = &$lines[$lineCount++]; - } - $currentLine .= $chunk; - } - } - - return implode("\r\n", $lines); - } - - /** - * Canonicalize string input (fix CRLF). - * - * @param string $string - * - * @return string - */ - private function _canonicalize($string) - { - return str_replace( - array("\r\n", "\r", "\n"), - array("\n", "\n", "\r\n"), - $string - ); - } -} diff --git a/lib/swiftmailer/swiftmailer/lib/classes/Swift/Mime/ContentEncoder/QpContentEncoder.php b/lib/swiftmailer/swiftmailer/lib/classes/Swift/Mime/ContentEncoder/QpContentEncoder.php deleted file mode 100644 index 5cc907b8e..000000000 --- a/lib/swiftmailer/swiftmailer/lib/classes/Swift/Mime/ContentEncoder/QpContentEncoder.php +++ /dev/null @@ -1,134 +0,0 @@ -_dotEscape = $dotEscape; - parent::__construct($charStream, $filter); - } - - public function __sleep() - { - return array('_charStream', '_filter', '_dotEscape'); - } - - protected function getSafeMapShareId() - { - return get_class($this).($this->_dotEscape ? '.dotEscape' : ''); - } - - protected function initSafeMap() - { - parent::initSafeMap(); - if ($this->_dotEscape) { - /* Encode . as =2e for buggy remote servers */ - unset($this->_safeMap[0x2e]); - } - } - - /** - * Encode stream $in to stream $out. - * - * QP encoded strings have a maximum line length of 76 characters. - * If the first line needs to be shorter, indicate the difference with - * $firstLineOffset. - * - * @param Swift_OutputByteStream $os output stream - * @param Swift_InputByteStream $is input stream - * @param int $firstLineOffset - * @param int $maxLineLength - */ - public function encodeByteStream(Swift_OutputByteStream $os, Swift_InputByteStream $is, $firstLineOffset = 0, $maxLineLength = 0) - { - if ($maxLineLength > 76 || $maxLineLength <= 0) { - $maxLineLength = 76; - } - - $thisLineLength = $maxLineLength - $firstLineOffset; - - $this->_charStream->flushContents(); - $this->_charStream->importByteStream($os); - - $currentLine = ''; - $prepend = ''; - $size = $lineLen = 0; - - while (false !== $bytes = $this->_nextSequence()) { - // If we're filtering the input - if (isset($this->_filter)) { - // If we can't filter because we need more bytes - while ($this->_filter->shouldBuffer($bytes)) { - // Then collect bytes into the buffer - if (false === $moreBytes = $this->_nextSequence(1)) { - break; - } - - foreach ($moreBytes as $b) { - $bytes[] = $b; - } - } - // And filter them - $bytes = $this->_filter->filter($bytes); - } - - $enc = $this->_encodeByteSequence($bytes, $size); - - $i = strpos($enc, '=0D=0A'); - $newLineLength = $lineLen + ($i === false ? $size : $i); - - if ($currentLine && $newLineLength >= $thisLineLength) { - $is->write($prepend.$this->_standardize($currentLine)); - $currentLine = ''; - $prepend = "=\r\n"; - $thisLineLength = $maxLineLength; - $lineLen = 0; - } - - $currentLine .= $enc; - - if ($i === false) { - $lineLen += $size; - } else { - // 6 is the length of '=0D=0A'. - $lineLen = $size - strrpos($enc, '=0D=0A') - 6; - } - } - if (strlen($currentLine)) { - $is->write($prepend.$this->_standardize($currentLine)); - } - } - - /** - * Get the name of this encoding scheme. - * Returns the string 'quoted-printable'. - * - * @return string - */ - public function getName() - { - return 'quoted-printable'; - } -} diff --git a/lib/swiftmailer/swiftmailer/lib/classes/Swift/Mime/ContentEncoder/QpContentEncoderProxy.php b/lib/swiftmailer/swiftmailer/lib/classes/Swift/Mime/ContentEncoder/QpContentEncoderProxy.php deleted file mode 100644 index 3214e1cf3..000000000 --- a/lib/swiftmailer/swiftmailer/lib/classes/Swift/Mime/ContentEncoder/QpContentEncoderProxy.php +++ /dev/null @@ -1,98 +0,0 @@ - - */ -class Swift_Mime_ContentEncoder_QpContentEncoderProxy implements Swift_Mime_ContentEncoder -{ - /** - * @var Swift_Mime_ContentEncoder_QpContentEncoder - */ - private $safeEncoder; - - /** - * @var Swift_Mime_ContentEncoder_NativeQpContentEncoder - */ - private $nativeEncoder; - - /** - * @var null|string - */ - private $charset; - - /** - * Constructor. - * - * @param Swift_Mime_ContentEncoder_QpContentEncoder $safeEncoder - * @param Swift_Mime_ContentEncoder_NativeQpContentEncoder $nativeEncoder - * @param string|null $charset - */ - public function __construct(Swift_Mime_ContentEncoder_QpContentEncoder $safeEncoder, Swift_Mime_ContentEncoder_NativeQpContentEncoder $nativeEncoder, $charset) - { - $this->safeEncoder = $safeEncoder; - $this->nativeEncoder = $nativeEncoder; - $this->charset = $charset; - } - - /** - * Make a deep copy of object. - */ - public function __clone() - { - $this->safeEncoder = clone $this->safeEncoder; - $this->nativeEncoder = clone $this->nativeEncoder; - } - - /** - * {@inheritdoc} - */ - public function charsetChanged($charset) - { - $this->charset = $charset; - $this->safeEncoder->charsetChanged($charset); - } - - /** - * {@inheritdoc} - */ - public function encodeByteStream(Swift_OutputByteStream $os, Swift_InputByteStream $is, $firstLineOffset = 0, $maxLineLength = 0) - { - $this->getEncoder()->encodeByteStream($os, $is, $firstLineOffset, $maxLineLength); - } - - /** - * {@inheritdoc} - */ - public function getName() - { - return 'quoted-printable'; - } - - /** - * {@inheritdoc} - */ - public function encodeString($string, $firstLineOffset = 0, $maxLineLength = 0) - { - return $this->getEncoder()->encodeString($string, $firstLineOffset, $maxLineLength); - } - - /** - * @return Swift_Mime_ContentEncoder - */ - private function getEncoder() - { - return 'utf-8' === $this->charset ? $this->nativeEncoder : $this->safeEncoder; - } -} diff --git a/lib/swiftmailer/swiftmailer/lib/classes/Swift/Mime/ContentEncoder/RawContentEncoder.php b/lib/swiftmailer/swiftmailer/lib/classes/Swift/Mime/ContentEncoder/RawContentEncoder.php deleted file mode 100644 index 0b8526e38..000000000 --- a/lib/swiftmailer/swiftmailer/lib/classes/Swift/Mime/ContentEncoder/RawContentEncoder.php +++ /dev/null @@ -1,64 +0,0 @@ - - */ -class Swift_Mime_ContentEncoder_RawContentEncoder implements Swift_Mime_ContentEncoder -{ - /** - * Encode a given string to produce an encoded string. - * - * @param string $string - * @param int $firstLineOffset ignored - * @param int $maxLineLength ignored - * - * @return string - */ - public function encodeString($string, $firstLineOffset = 0, $maxLineLength = 0) - { - return $string; - } - - /** - * Encode stream $in to stream $out. - * - * @param Swift_OutputByteStream $in - * @param Swift_InputByteStream $out - * @param int $firstLineOffset ignored - * @param int $maxLineLength ignored - */ - public function encodeByteStream(Swift_OutputByteStream $os, Swift_InputByteStream $is, $firstLineOffset = 0, $maxLineLength = 0) - { - while (false !== ($bytes = $os->read(8192))) { - $is->write($bytes); - } - } - - /** - * Get the name of this encoding scheme. - * - * @return string - */ - public function getName() - { - return 'raw'; - } - - /** - * Not used. - */ - public function charsetChanged($charset) - { - } -} diff --git a/lib/swiftmailer/swiftmailer/lib/classes/Swift/Mime/EmbeddedFile.php b/lib/swiftmailer/swiftmailer/lib/classes/Swift/Mime/EmbeddedFile.php deleted file mode 100644 index 6af757124..000000000 --- a/lib/swiftmailer/swiftmailer/lib/classes/Swift/Mime/EmbeddedFile.php +++ /dev/null @@ -1,45 +0,0 @@ -setDisposition('inline'); - $this->setId($this->getId()); - } - - /** - * Get the nesting level of this EmbeddedFile. - * - * Returns {@see LEVEL_RELATED}. - * - * @return int - */ - public function getNestingLevel() - { - return self::LEVEL_RELATED; - } -} diff --git a/lib/swiftmailer/swiftmailer/lib/classes/Swift/Mime/EncodingObserver.php b/lib/swiftmailer/swiftmailer/lib/classes/Swift/Mime/EncodingObserver.php deleted file mode 100644 index cc44a6efb..000000000 --- a/lib/swiftmailer/swiftmailer/lib/classes/Swift/Mime/EncodingObserver.php +++ /dev/null @@ -1,24 +0,0 @@ -init(); - } - - public function __wakeup() - { - $this->init(); - } - - protected function init() - { - if (count(self::$_specials) > 0) { - return; - } - - self::$_specials = array( - '(', ')', '<', '>', '[', ']', - ':', ';', '@', ',', '.', '"', - ); - - /*** Refer to RFC 2822 for ABNF grammar ***/ - - // All basic building blocks - self::$_grammar['NO-WS-CTL'] = '[\x01-\x08\x0B\x0C\x0E-\x19\x7F]'; - self::$_grammar['WSP'] = '[ \t]'; - self::$_grammar['CRLF'] = '(?:\r\n)'; - self::$_grammar['FWS'] = '(?:(?:'.self::$_grammar['WSP'].'*'. - self::$_grammar['CRLF'].')?'.self::$_grammar['WSP'].')'; - self::$_grammar['text'] = '[\x00-\x08\x0B\x0C\x0E-\x7F]'; - self::$_grammar['quoted-pair'] = '(?:\\\\'.self::$_grammar['text'].')'; - self::$_grammar['ctext'] = '(?:'.self::$_grammar['NO-WS-CTL']. - '|[\x21-\x27\x2A-\x5B\x5D-\x7E])'; - // Uses recursive PCRE (?1) -- could be a weak point?? - self::$_grammar['ccontent'] = '(?:'.self::$_grammar['ctext'].'|'. - self::$_grammar['quoted-pair'].'|(?1))'; - self::$_grammar['comment'] = '(\((?:'.self::$_grammar['FWS'].'|'. - self::$_grammar['ccontent'].')*'.self::$_grammar['FWS'].'?\))'; - self::$_grammar['CFWS'] = '(?:(?:'.self::$_grammar['FWS'].'?'. - self::$_grammar['comment'].')*(?:(?:'.self::$_grammar['FWS'].'?'. - self::$_grammar['comment'].')|'.self::$_grammar['FWS'].'))'; - self::$_grammar['qtext'] = '(?:'.self::$_grammar['NO-WS-CTL']. - '|[\x21\x23-\x5B\x5D-\x7E])'; - self::$_grammar['qcontent'] = '(?:'.self::$_grammar['qtext'].'|'. - self::$_grammar['quoted-pair'].')'; - self::$_grammar['quoted-string'] = '(?:'.self::$_grammar['CFWS'].'?"'. - '('.self::$_grammar['FWS'].'?'.self::$_grammar['qcontent'].')*'. - self::$_grammar['FWS'].'?"'.self::$_grammar['CFWS'].'?)'; - self::$_grammar['atext'] = '[a-zA-Z0-9!#\$%&\'\*\+\-\/=\?\^_`\{\}\|~]'; - self::$_grammar['atom'] = '(?:'.self::$_grammar['CFWS'].'?'. - self::$_grammar['atext'].'+'.self::$_grammar['CFWS'].'?)'; - self::$_grammar['dot-atom-text'] = '(?:'.self::$_grammar['atext'].'+'. - '(\.'.self::$_grammar['atext'].'+)*)'; - self::$_grammar['dot-atom'] = '(?:'.self::$_grammar['CFWS'].'?'. - self::$_grammar['dot-atom-text'].'+'.self::$_grammar['CFWS'].'?)'; - self::$_grammar['word'] = '(?:'.self::$_grammar['atom'].'|'. - self::$_grammar['quoted-string'].')'; - self::$_grammar['phrase'] = '(?:'.self::$_grammar['word'].'+?)'; - self::$_grammar['no-fold-quote'] = '(?:"(?:'.self::$_grammar['qtext']. - '|'.self::$_grammar['quoted-pair'].')*")'; - self::$_grammar['dtext'] = '(?:'.self::$_grammar['NO-WS-CTL']. - '|[\x21-\x5A\x5E-\x7E])'; - self::$_grammar['no-fold-literal'] = '(?:\[(?:'.self::$_grammar['dtext']. - '|'.self::$_grammar['quoted-pair'].')*\])'; - - // Message IDs - self::$_grammar['id-left'] = '(?:'.self::$_grammar['dot-atom-text'].'|'. - self::$_grammar['no-fold-quote'].')'; - self::$_grammar['id-right'] = '(?:'.self::$_grammar['dot-atom-text'].'|'. - self::$_grammar['no-fold-literal'].')'; - - // Addresses, mailboxes and paths - self::$_grammar['local-part'] = '(?:'.self::$_grammar['dot-atom'].'|'. - self::$_grammar['quoted-string'].')'; - self::$_grammar['dcontent'] = '(?:'.self::$_grammar['dtext'].'|'. - self::$_grammar['quoted-pair'].')'; - self::$_grammar['domain-literal'] = '(?:'.self::$_grammar['CFWS'].'?\[('. - self::$_grammar['FWS'].'?'.self::$_grammar['dcontent'].')*?'. - self::$_grammar['FWS'].'?\]'.self::$_grammar['CFWS'].'?)'; - self::$_grammar['domain'] = '(?:'.self::$_grammar['dot-atom'].'|'. - self::$_grammar['domain-literal'].')'; - self::$_grammar['addr-spec'] = '(?:'.self::$_grammar['local-part'].'@'. - self::$_grammar['domain'].')'; - } - - /** - * Get the grammar defined for $name token. - * - * @param string $name exactly as written in the RFC - * - * @return string - */ - public function getDefinition($name) - { - if (array_key_exists($name, self::$_grammar)) { - return self::$_grammar[$name]; - } - - throw new Swift_RfcComplianceException( - "No such grammar '".$name."' defined." - ); - } - - /** - * Returns the tokens defined in RFC 2822 (and some related RFCs). - * - * @return array - */ - public function getGrammarDefinitions() - { - return self::$_grammar; - } - - /** - * Returns the current special characters used in the syntax which need to be escaped. - * - * @return array - */ - public function getSpecials() - { - return self::$_specials; - } - - /** - * Escape special characters in a string (convert to quoted-pairs). - * - * @param string $token - * @param string[] $include additional chars to escape - * @param string[] $exclude chars from escaping - * - * @return string - */ - public function escapeSpecials($token, $include = array(), $exclude = array()) - { - foreach (array_merge(array('\\'), array_diff(self::$_specials, $exclude), $include) as $char) { - $token = str_replace($char, '\\'.$char, $token); - } - - return $token; - } -} diff --git a/lib/swiftmailer/swiftmailer/lib/classes/Swift/Mime/Header.php b/lib/swiftmailer/swiftmailer/lib/classes/Swift/Mime/Header.php deleted file mode 100644 index a8ddd2721..000000000 --- a/lib/swiftmailer/swiftmailer/lib/classes/Swift/Mime/Header.php +++ /dev/null @@ -1,93 +0,0 @@ -getName(), "\r\n"); - mb_internal_encoding($old); - - return $newstring; - } - - return parent::encodeString($string, $firstLineOffset, $maxLineLength); - } -} diff --git a/lib/swiftmailer/swiftmailer/lib/classes/Swift/Mime/HeaderEncoder/QpHeaderEncoder.php b/lib/swiftmailer/swiftmailer/lib/classes/Swift/Mime/HeaderEncoder/QpHeaderEncoder.php deleted file mode 100644 index 510dd6637..000000000 --- a/lib/swiftmailer/swiftmailer/lib/classes/Swift/Mime/HeaderEncoder/QpHeaderEncoder.php +++ /dev/null @@ -1,65 +0,0 @@ -_safeMap[$byte] = chr($byte); - } - } - - /** - * Get the name of this encoding scheme. - * - * Returns the string 'Q'. - * - * @return string - */ - public function getName() - { - return 'Q'; - } - - /** - * Takes an unencoded string and produces a QP encoded string from it. - * - * @param string $string string to encode - * @param int $firstLineOffset optional - * @param int $maxLineLength optional, 0 indicates the default of 76 chars - * - * @return string - */ - public function encodeString($string, $firstLineOffset = 0, $maxLineLength = 0) - { - return str_replace(array(' ', '=20', "=\r\n"), array('_', '_', "\r\n"), - parent::encodeString($string, $firstLineOffset, $maxLineLength) - ); - } -} diff --git a/lib/swiftmailer/swiftmailer/lib/classes/Swift/Mime/HeaderFactory.php b/lib/swiftmailer/swiftmailer/lib/classes/Swift/Mime/HeaderFactory.php deleted file mode 100644 index c65f26d72..000000000 --- a/lib/swiftmailer/swiftmailer/lib/classes/Swift/Mime/HeaderFactory.php +++ /dev/null @@ -1,78 +0,0 @@ -setGrammar($grammar); - } - - /** - * Set the character set used in this Header. - * - * @param string $charset - */ - public function setCharset($charset) - { - $this->clearCachedValueIf($charset != $this->_charset); - $this->_charset = $charset; - if (isset($this->_encoder)) { - $this->_encoder->charsetChanged($charset); - } - } - - /** - * Get the character set used in this Header. - * - * @return string - */ - public function getCharset() - { - return $this->_charset; - } - - /** - * Set the language used in this Header. - * - * For example, for US English, 'en-us'. - * This can be unspecified. - * - * @param string $lang - */ - public function setLanguage($lang) - { - $this->clearCachedValueIf($this->_lang != $lang); - $this->_lang = $lang; - } - - /** - * Get the language used in this Header. - * - * @return string - */ - public function getLanguage() - { - return $this->_lang; - } - - /** - * Set the encoder used for encoding the header. - * - * @param Swift_Mime_HeaderEncoder $encoder - */ - public function setEncoder(Swift_Mime_HeaderEncoder $encoder) - { - $this->_encoder = $encoder; - $this->setCachedValue(null); - } - - /** - * Get the encoder used for encoding this Header. - * - * @return Swift_Mime_HeaderEncoder - */ - public function getEncoder() - { - return $this->_encoder; - } - - /** - * Set the grammar used for the header. - * - * @param Swift_Mime_Grammar $grammar - */ - public function setGrammar(Swift_Mime_Grammar $grammar) - { - $this->_grammar = $grammar; - $this->setCachedValue(null); - } - - /** - * Get the grammar used for this Header. - * - * @return Swift_Mime_Grammar - */ - public function getGrammar() - { - return $this->_grammar; - } - - /** - * Get the name of this header (e.g. charset). - * - * @return string - */ - public function getFieldName() - { - return $this->_name; - } - - /** - * Set the maximum length of lines in the header (excluding EOL). - * - * @param int $lineLength - */ - public function setMaxLineLength($lineLength) - { - $this->clearCachedValueIf($this->_lineLength != $lineLength); - $this->_lineLength = $lineLength; - } - - /** - * Get the maximum permitted length of lines in this Header. - * - * @return int - */ - public function getMaxLineLength() - { - return $this->_lineLength; - } - - /** - * Get this Header rendered as a RFC 2822 compliant string. - * - * @throws Swift_RfcComplianceException - * - * @return string - */ - public function toString() - { - return $this->_tokensToString($this->toTokens()); - } - - /** - * Returns a string representation of this object. - * - * @return string - * - * @see toString() - */ - public function __toString() - { - return $this->toString(); - } - - /** - * Set the name of this Header field. - * - * @param string $name - */ - protected function setFieldName($name) - { - $this->_name = $name; - } - - /** - * Produces a compliant, formatted RFC 2822 'phrase' based on the string given. - * - * @param Swift_Mime_Header $header - * @param string $string as displayed - * @param string $charset of the text - * @param Swift_Mime_HeaderEncoder $encoder - * @param bool $shorten the first line to make remove for header name - * - * @return string - */ - protected function createPhrase(Swift_Mime_Header $header, $string, $charset, Swift_Mime_HeaderEncoder $encoder = null, $shorten = false) - { - // Treat token as exactly what was given - $phraseStr = $string; - // If it's not valid - if (!preg_match('/^'.$this->getGrammar()->getDefinition('phrase').'$/D', $phraseStr)) { - // .. but it is just ascii text, try escaping some characters - // and make it a quoted-string - if (preg_match('/^'.$this->getGrammar()->getDefinition('text').'*$/D', $phraseStr)) { - $phraseStr = $this->getGrammar()->escapeSpecials( - $phraseStr, array('"'), $this->getGrammar()->getSpecials() - ); - $phraseStr = '"'.$phraseStr.'"'; - } else { - // ... otherwise it needs encoding - // Determine space remaining on line if first line - if ($shorten) { - $usedLength = strlen($header->getFieldName().': '); - } else { - $usedLength = 0; - } - $phraseStr = $this->encodeWords($header, $string, $usedLength); - } - } - - return $phraseStr; - } - - /** - * Encode needed word tokens within a string of input. - * - * @param Swift_Mime_Header $header - * @param string $input - * @param string $usedLength optional - * - * @return string - */ - protected function encodeWords(Swift_Mime_Header $header, $input, $usedLength = -1) - { - $value = ''; - - $tokens = $this->getEncodableWordTokens($input); - - foreach ($tokens as $token) { - // See RFC 2822, Sect 2.2 (really 2.2 ??) - if ($this->tokenNeedsEncoding($token)) { - // Don't encode starting WSP - $firstChar = substr($token, 0, 1); - switch ($firstChar) { - case ' ': - case "\t": - $value .= $firstChar; - $token = substr($token, 1); - } - - if (-1 == $usedLength) { - $usedLength = strlen($header->getFieldName().': ') + strlen($value); - } - $value .= $this->getTokenAsEncodedWord($token, $usedLength); - - $header->setMaxLineLength(76); // Forcefully override - } else { - $value .= $token; - } - } - - return $value; - } - - /** - * Test if a token needs to be encoded or not. - * - * @param string $token - * - * @return bool - */ - protected function tokenNeedsEncoding($token) - { - return preg_match('~[\x00-\x08\x10-\x19\x7F-\xFF\r\n]~', $token); - } - - /** - * Splits a string into tokens in blocks of words which can be encoded quickly. - * - * @param string $string - * - * @return string[] - */ - protected function getEncodableWordTokens($string) - { - $tokens = array(); - - $encodedToken = ''; - // Split at all whitespace boundaries - foreach (preg_split('~(?=[\t ])~', $string) as $token) { - if ($this->tokenNeedsEncoding($token)) { - $encodedToken .= $token; - } else { - if (strlen($encodedToken) > 0) { - $tokens[] = $encodedToken; - $encodedToken = ''; - } - $tokens[] = $token; - } - } - if (strlen($encodedToken)) { - $tokens[] = $encodedToken; - } - - return $tokens; - } - - /** - * Get a token as an encoded word for safe insertion into headers. - * - * @param string $token token to encode - * @param int $firstLineOffset optional - * - * @return string - */ - protected function getTokenAsEncodedWord($token, $firstLineOffset = 0) - { - // Adjust $firstLineOffset to account for space needed for syntax - $charsetDecl = $this->_charset; - if (isset($this->_lang)) { - $charsetDecl .= '*'.$this->_lang; - } - $encodingWrapperLength = strlen( - '=?'.$charsetDecl.'?'.$this->_encoder->getName().'??=' - ); - - if ($firstLineOffset >= 75) { - //Does this logic need to be here? - $firstLineOffset = 0; - } - - $encodedTextLines = explode("\r\n", - $this->_encoder->encodeString( - $token, $firstLineOffset, 75 - $encodingWrapperLength, $this->_charset - ) - ); - - if (strtolower($this->_charset) !== 'iso-2022-jp') { - // special encoding for iso-2022-jp using mb_encode_mimeheader - foreach ($encodedTextLines as $lineNum => $line) { - $encodedTextLines[$lineNum] = '=?'.$charsetDecl. - '?'.$this->_encoder->getName(). - '?'.$line.'?='; - } - } - - return implode("\r\n ", $encodedTextLines); - } - - /** - * Generates tokens from the given string which include CRLF as individual tokens. - * - * @param string $token - * - * @return string[] - */ - protected function generateTokenLines($token) - { - return preg_split('~(\r\n)~', $token, -1, PREG_SPLIT_DELIM_CAPTURE); - } - - /** - * Set a value into the cache. - * - * @param string $value - */ - protected function setCachedValue($value) - { - $this->_cachedValue = $value; - } - - /** - * Get the value in the cache. - * - * @return string - */ - protected function getCachedValue() - { - return $this->_cachedValue; - } - - /** - * Clear the cached value if $condition is met. - * - * @param bool $condition - */ - protected function clearCachedValueIf($condition) - { - if ($condition) { - $this->setCachedValue(null); - } - } - - /** - * Generate a list of all tokens in the final header. - * - * @param string $string The string to tokenize - * - * @return array An array of tokens as strings - */ - protected function toTokens($string = null) - { - if (null === $string) { - $string = $this->getFieldBody(); - } - - $tokens = array(); - - // Generate atoms; split at all invisible boundaries followed by WSP - foreach (preg_split('~(?=[ \t])~', $string) as $token) { - $newTokens = $this->generateTokenLines($token); - foreach ($newTokens as $newToken) { - $tokens[] = $newToken; - } - } - - return $tokens; - } - - /** - * Takes an array of tokens which appear in the header and turns them into - * an RFC 2822 compliant string, adding FWSP where needed. - * - * @param string[] $tokens - * - * @return string - */ - private function _tokensToString(array $tokens) - { - $lineCount = 0; - $headerLines = array(); - $headerLines[] = $this->_name.': '; - $currentLine = &$headerLines[$lineCount++]; - - // Build all tokens back into compliant header - foreach ($tokens as $i => $token) { - // Line longer than specified maximum or token was just a new line - if (("\r\n" == $token) || - ($i > 0 && strlen($currentLine.$token) > $this->_lineLength) - && 0 < strlen($currentLine)) { - $headerLines[] = ''; - $currentLine = &$headerLines[$lineCount++]; - } - - // Append token to the line - if ("\r\n" != $token) { - $currentLine .= $token; - } - } - - // Implode with FWS (RFC 2822, 2.2.3) - return implode("\r\n", $headerLines)."\r\n"; - } -} diff --git a/lib/swiftmailer/swiftmailer/lib/classes/Swift/Mime/Headers/DateHeader.php b/lib/swiftmailer/swiftmailer/lib/classes/Swift/Mime/Headers/DateHeader.php deleted file mode 100644 index 4075cbfa1..000000000 --- a/lib/swiftmailer/swiftmailer/lib/classes/Swift/Mime/Headers/DateHeader.php +++ /dev/null @@ -1,125 +0,0 @@ - - * - * - * - * @param string $name of Header - * @param Swift_Mime_Grammar $grammar - */ - public function __construct($name, Swift_Mime_Grammar $grammar) - { - $this->setFieldName($name); - parent::__construct($grammar); - } - - /** - * Get the type of Header that this instance represents. - * - * @see TYPE_TEXT, TYPE_PARAMETERIZED, TYPE_MAILBOX - * @see TYPE_DATE, TYPE_ID, TYPE_PATH - * - * @return int - */ - public function getFieldType() - { - return self::TYPE_DATE; - } - - /** - * Set the model for the field body. - * - * This method takes a UNIX timestamp. - * - * @param int $model - */ - public function setFieldBodyModel($model) - { - $this->setTimestamp($model); - } - - /** - * Get the model for the field body. - * - * This method returns a UNIX timestamp. - * - * @return mixed - */ - public function getFieldBodyModel() - { - return $this->getTimestamp(); - } - - /** - * Get the UNIX timestamp of the Date in this Header. - * - * @return int - */ - public function getTimestamp() - { - return $this->_timestamp; - } - - /** - * Set the UNIX timestamp of the Date in this Header. - * - * @param int $timestamp - */ - public function setTimestamp($timestamp) - { - if (null !== $timestamp) { - $timestamp = (int) $timestamp; - } - $this->clearCachedValueIf($this->_timestamp != $timestamp); - $this->_timestamp = $timestamp; - } - - /** - * Get the string value of the body in this Header. - * - * This is not necessarily RFC 2822 compliant since folding white space will - * not be added at this stage (see {@link toString()} for that). - * - * @see toString() - * - * @return string - */ - public function getFieldBody() - { - if (!$this->getCachedValue()) { - if (isset($this->_timestamp)) { - $this->setCachedValue(date('r', $this->_timestamp)); - } - } - - return $this->getCachedValue(); - } -} diff --git a/lib/swiftmailer/swiftmailer/lib/classes/Swift/Mime/Headers/IdentificationHeader.php b/lib/swiftmailer/swiftmailer/lib/classes/Swift/Mime/Headers/IdentificationHeader.php deleted file mode 100644 index b114506b4..000000000 --- a/lib/swiftmailer/swiftmailer/lib/classes/Swift/Mime/Headers/IdentificationHeader.php +++ /dev/null @@ -1,180 +0,0 @@ -setFieldName($name); - parent::__construct($grammar); - } - - /** - * Get the type of Header that this instance represents. - * - * @see TYPE_TEXT, TYPE_PARAMETERIZED, TYPE_MAILBOX - * @see TYPE_DATE, TYPE_ID, TYPE_PATH - * - * @return int - */ - public function getFieldType() - { - return self::TYPE_ID; - } - - /** - * Set the model for the field body. - * - * This method takes a string ID, or an array of IDs. - * - * @param mixed $model - * - * @throws Swift_RfcComplianceException - */ - public function setFieldBodyModel($model) - { - $this->setId($model); - } - - /** - * Get the model for the field body. - * - * This method returns an array of IDs - * - * @return array - */ - public function getFieldBodyModel() - { - return $this->getIds(); - } - - /** - * Set the ID used in the value of this header. - * - * @param string|array $id - * - * @throws Swift_RfcComplianceException - */ - public function setId($id) - { - $this->setIds(is_array($id) ? $id : array($id)); - } - - /** - * Get the ID used in the value of this Header. - * - * If multiple IDs are set only the first is returned. - * - * @return string - */ - public function getId() - { - if (count($this->_ids) > 0) { - return $this->_ids[0]; - } - } - - /** - * Set a collection of IDs to use in the value of this Header. - * - * @param string[] $ids - * - * @throws Swift_RfcComplianceException - */ - public function setIds(array $ids) - { - $actualIds = array(); - - foreach ($ids as $id) { - $this->_assertValidId($id); - $actualIds[] = $id; - } - - $this->clearCachedValueIf($this->_ids != $actualIds); - $this->_ids = $actualIds; - } - - /** - * Get the list of IDs used in this Header. - * - * @return string[] - */ - public function getIds() - { - return $this->_ids; - } - - /** - * Get the string value of the body in this Header. - * - * This is not necessarily RFC 2822 compliant since folding white space will - * not be added at this stage (see {@see toString()} for that). - * - * @see toString() - * - * @throws Swift_RfcComplianceException - * - * @return string - */ - public function getFieldBody() - { - if (!$this->getCachedValue()) { - $angleAddrs = array(); - - foreach ($this->_ids as $id) { - $angleAddrs[] = '<'.$id.'>'; - } - - $this->setCachedValue(implode(' ', $angleAddrs)); - } - - return $this->getCachedValue(); - } - - /** - * Throws an Exception if the id passed does not comply with RFC 2822. - * - * @param string $id - * - * @throws Swift_RfcComplianceException - */ - private function _assertValidId($id) - { - if (!preg_match( - '/^'.$this->getGrammar()->getDefinition('id-left').'@'. - $this->getGrammar()->getDefinition('id-right').'$/D', - $id - )) { - throw new Swift_RfcComplianceException( - 'Invalid ID given <'.$id.'>' - ); - } - } -} diff --git a/lib/swiftmailer/swiftmailer/lib/classes/Swift/Mime/Headers/MailboxHeader.php b/lib/swiftmailer/swiftmailer/lib/classes/Swift/Mime/Headers/MailboxHeader.php deleted file mode 100644 index e4567fc80..000000000 --- a/lib/swiftmailer/swiftmailer/lib/classes/Swift/Mime/Headers/MailboxHeader.php +++ /dev/null @@ -1,351 +0,0 @@ -setFieldName($name); - $this->setEncoder($encoder); - parent::__construct($grammar); - } - - /** - * Get the type of Header that this instance represents. - * - * @see TYPE_TEXT, TYPE_PARAMETERIZED, TYPE_MAILBOX - * @see TYPE_DATE, TYPE_ID, TYPE_PATH - * - * @return int - */ - public function getFieldType() - { - return self::TYPE_MAILBOX; - } - - /** - * Set the model for the field body. - * - * This method takes a string, or an array of addresses. - * - * @param mixed $model - * - * @throws Swift_RfcComplianceException - */ - public function setFieldBodyModel($model) - { - $this->setNameAddresses($model); - } - - /** - * Get the model for the field body. - * - * This method returns an associative array like {@link getNameAddresses()} - * - * @throws Swift_RfcComplianceException - * - * @return array - */ - public function getFieldBodyModel() - { - return $this->getNameAddresses(); - } - - /** - * Set a list of mailboxes to be shown in this Header. - * - * The mailboxes can be a simple array of addresses, or an array of - * key=>value pairs where (email => personalName). - * Example: - * - * setNameAddresses(array( - * 'chris@swiftmailer.org' => 'Chris Corbyn', - * 'mark@swiftmailer.org' //No associated personal name - * )); - * ?> - * - * - * @see __construct() - * @see setAddresses() - * @see setValue() - * - * @param string|string[] $mailboxes - * - * @throws Swift_RfcComplianceException - */ - public function setNameAddresses($mailboxes) - { - $this->_mailboxes = $this->normalizeMailboxes((array) $mailboxes); - $this->setCachedValue(null); //Clear any cached value - } - - /** - * Get the full mailbox list of this Header as an array of valid RFC 2822 strings. - * - * Example: - * - * 'Chris Corbyn', - * 'mark@swiftmailer.org' => 'Mark Corbyn') - * ); - * print_r($header->getNameAddressStrings()); - * // array ( - * // 0 => Chris Corbyn , - * // 1 => Mark Corbyn - * // ) - * ?> - * - * - * @see getNameAddresses() - * @see toString() - * - * @throws Swift_RfcComplianceException - * - * @return string[] - */ - public function getNameAddressStrings() - { - return $this->_createNameAddressStrings($this->getNameAddresses()); - } - - /** - * Get all mailboxes in this Header as key=>value pairs. - * - * The key is the address and the value is the name (or null if none set). - * Example: - * - * 'Chris Corbyn', - * 'mark@swiftmailer.org' => 'Mark Corbyn') - * ); - * print_r($header->getNameAddresses()); - * // array ( - * // chris@swiftmailer.org => Chris Corbyn, - * // mark@swiftmailer.org => Mark Corbyn - * // ) - * ?> - * - * - * @see getAddresses() - * @see getNameAddressStrings() - * - * @return string[] - */ - public function getNameAddresses() - { - return $this->_mailboxes; - } - - /** - * Makes this Header represent a list of plain email addresses with no names. - * - * Example: - * - * setAddresses( - * array('one@domain.tld', 'two@domain.tld', 'three@domain.tld') - * ); - * ?> - * - * - * @see setNameAddresses() - * @see setValue() - * - * @param string[] $addresses - * - * @throws Swift_RfcComplianceException - */ - public function setAddresses($addresses) - { - $this->setNameAddresses(array_values((array) $addresses)); - } - - /** - * Get all email addresses in this Header. - * - * @see getNameAddresses() - * - * @return string[] - */ - public function getAddresses() - { - return array_keys($this->_mailboxes); - } - - /** - * Remove one or more addresses from this Header. - * - * @param string|string[] $addresses - */ - public function removeAddresses($addresses) - { - $this->setCachedValue(null); - foreach ((array) $addresses as $address) { - unset($this->_mailboxes[$address]); - } - } - - /** - * Get the string value of the body in this Header. - * - * This is not necessarily RFC 2822 compliant since folding white space will - * not be added at this stage (see {@link toString()} for that). - * - * @see toString() - * - * @throws Swift_RfcComplianceException - * - * @return string - */ - public function getFieldBody() - { - // Compute the string value of the header only if needed - if (null === $this->getCachedValue()) { - $this->setCachedValue($this->createMailboxListString($this->_mailboxes)); - } - - return $this->getCachedValue(); - } - - /** - * Normalizes a user-input list of mailboxes into consistent key=>value pairs. - * - * @param string[] $mailboxes - * - * @return string[] - */ - protected function normalizeMailboxes(array $mailboxes) - { - $actualMailboxes = array(); - - foreach ($mailboxes as $key => $value) { - if (is_string($key)) { - //key is email addr - $address = $key; - $name = $value; - } else { - $address = $value; - $name = null; - } - $this->_assertValidAddress($address); - $actualMailboxes[$address] = $name; - } - - return $actualMailboxes; - } - - /** - * Produces a compliant, formatted display-name based on the string given. - * - * @param string $displayName as displayed - * @param bool $shorten the first line to make remove for header name - * - * @return string - */ - protected function createDisplayNameString($displayName, $shorten = false) - { - return $this->createPhrase($this, $displayName, $this->getCharset(), $this->getEncoder(), $shorten); - } - - /** - * Creates a string form of all the mailboxes in the passed array. - * - * @param string[] $mailboxes - * - * @throws Swift_RfcComplianceException - * - * @return string - */ - protected function createMailboxListString(array $mailboxes) - { - return implode(', ', $this->_createNameAddressStrings($mailboxes)); - } - - /** - * Redefine the encoding requirements for mailboxes. - * - * All "specials" must be encoded as the full header value will not be quoted - * - * @see RFC 2822 3.2.1 - * - * @param string $token - * - * @return bool - */ - protected function tokenNeedsEncoding($token) - { - return preg_match('/[()<>\[\]:;@\,."]/', $token) || parent::tokenNeedsEncoding($token); - } - - /** - * Return an array of strings conforming the the name-addr spec of RFC 2822. - * - * @param string[] $mailboxes - * - * @return string[] - */ - private function _createNameAddressStrings(array $mailboxes) - { - $strings = array(); - - foreach ($mailboxes as $email => $name) { - $mailboxStr = $email; - if (null !== $name) { - $nameStr = $this->createDisplayNameString($name, empty($strings)); - $mailboxStr = $nameStr.' <'.$mailboxStr.'>'; - } - $strings[] = $mailboxStr; - } - - return $strings; - } - - /** - * Throws an Exception if the address passed does not comply with RFC 2822. - * - * @param string $address - * - * @throws Swift_RfcComplianceException If invalid. - */ - private function _assertValidAddress($address) - { - if (!preg_match('/^'.$this->getGrammar()->getDefinition('addr-spec').'$/D', - $address)) { - throw new Swift_RfcComplianceException( - 'Address in mailbox given ['.$address. - '] does not comply with RFC 2822, 3.6.2.' - ); - } - } -} diff --git a/lib/swiftmailer/swiftmailer/lib/classes/Swift/Mime/Headers/OpenDKIMHeader.php b/lib/swiftmailer/swiftmailer/lib/classes/Swift/Mime/Headers/OpenDKIMHeader.php deleted file mode 100644 index d74955007..000000000 --- a/lib/swiftmailer/swiftmailer/lib/classes/Swift/Mime/Headers/OpenDKIMHeader.php +++ /dev/null @@ -1,133 +0,0 @@ - - */ -class Swift_Mime_Headers_OpenDKIMHeader implements Swift_Mime_Header -{ - /** - * The value of this Header. - * - * @var string - */ - private $_value; - - /** - * The name of this Header. - * - * @var string - */ - private $_fieldName; - - /** - * @param string $name - */ - public function __construct($name) - { - $this->_fieldName = $name; - } - - /** - * Get the type of Header that this instance represents. - * - * @see TYPE_TEXT, TYPE_PARAMETERIZED, TYPE_MAILBOX - * @see TYPE_DATE, TYPE_ID, TYPE_PATH - * - * @return int - */ - public function getFieldType() - { - return self::TYPE_TEXT; - } - - /** - * Set the model for the field body. - * - * This method takes a string for the field value. - * - * @param string $model - */ - public function setFieldBodyModel($model) - { - $this->setValue($model); - } - - /** - * Get the model for the field body. - * - * This method returns a string. - * - * @return string - */ - public function getFieldBodyModel() - { - return $this->getValue(); - } - - /** - * Get the (unencoded) value of this header. - * - * @return string - */ - public function getValue() - { - return $this->_value; - } - - /** - * Set the (unencoded) value of this header. - * - * @param string $value - */ - public function setValue($value) - { - $this->_value = $value; - } - - /** - * Get the value of this header prepared for rendering. - * - * @return string - */ - public function getFieldBody() - { - return $this->_value; - } - - /** - * Get this Header rendered as a RFC 2822 compliant string. - * - * @return string - */ - public function toString() - { - return $this->_fieldName.': '.$this->_value; - } - - /** - * Set the Header FieldName. - * - * @see Swift_Mime_Header::getFieldName() - */ - public function getFieldName() - { - return $this->_fieldName; - } - - /** - * Ignored. - */ - public function setCharset($charset) - { - } -} diff --git a/lib/swiftmailer/swiftmailer/lib/classes/Swift/Mime/Headers/ParameterizedHeader.php b/lib/swiftmailer/swiftmailer/lib/classes/Swift/Mime/Headers/ParameterizedHeader.php deleted file mode 100644 index c1777d333..000000000 --- a/lib/swiftmailer/swiftmailer/lib/classes/Swift/Mime/Headers/ParameterizedHeader.php +++ /dev/null @@ -1,258 +0,0 @@ -_paramEncoder = $paramEncoder; - } - - /** - * Get the type of Header that this instance represents. - * - * @see TYPE_TEXT, TYPE_PARAMETERIZED, TYPE_MAILBOX - * @see TYPE_DATE, TYPE_ID, TYPE_PATH - * - * @return int - */ - public function getFieldType() - { - return self::TYPE_PARAMETERIZED; - } - - /** - * Set the character set used in this Header. - * - * @param string $charset - */ - public function setCharset($charset) - { - parent::setCharset($charset); - if (isset($this->_paramEncoder)) { - $this->_paramEncoder->charsetChanged($charset); - } - } - - /** - * Set the value of $parameter. - * - * @param string $parameter - * @param string $value - */ - public function setParameter($parameter, $value) - { - $this->setParameters(array_merge($this->getParameters(), array($parameter => $value))); - } - - /** - * Get the value of $parameter. - * - * @param string $parameter - * - * @return string - */ - public function getParameter($parameter) - { - $params = $this->getParameters(); - - return array_key_exists($parameter, $params) ? $params[$parameter] : null; - } - - /** - * Set an associative array of parameter names mapped to values. - * - * @param string[] $parameters - */ - public function setParameters(array $parameters) - { - $this->clearCachedValueIf($this->_params != $parameters); - $this->_params = $parameters; - } - - /** - * Returns an associative array of parameter names mapped to values. - * - * @return string[] - */ - public function getParameters() - { - return $this->_params; - } - - /** - * Get the value of this header prepared for rendering. - * - * @return string - */ - public function getFieldBody() //TODO: Check caching here - { - $body = parent::getFieldBody(); - foreach ($this->_params as $name => $value) { - if (null !== $value) { - // Add the parameter - $body .= '; '.$this->_createParameter($name, $value); - } - } - - return $body; - } - - /** - * Generate a list of all tokens in the final header. - * - * This doesn't need to be overridden in theory, but it is for implementation - * reasons to prevent potential breakage of attributes. - * - * @param string $string The string to tokenize - * - * @return array An array of tokens as strings - */ - protected function toTokens($string = null) - { - $tokens = parent::toTokens(parent::getFieldBody()); - - // Try creating any parameters - foreach ($this->_params as $name => $value) { - if (null !== $value) { - // Add the semi-colon separator - $tokens[count($tokens) - 1] .= ';'; - $tokens = array_merge($tokens, $this->generateTokenLines( - ' '.$this->_createParameter($name, $value) - )); - } - } - - return $tokens; - } - - /** - * Render a RFC 2047 compliant header parameter from the $name and $value. - * - * @param string $name - * @param string $value - * - * @return string - */ - private function _createParameter($name, $value) - { - $origValue = $value; - - $encoded = false; - // Allow room for parameter name, indices, "=" and DQUOTEs - $maxValueLength = $this->getMaxLineLength() - strlen($name.'=*N"";') - 1; - $firstLineOffset = 0; - - // If it's not already a valid parameter value... - if (!preg_match('/^'.self::TOKEN_REGEX.'$/D', $value)) { - // TODO: text, or something else?? - // ... and it's not ascii - if (!preg_match('/^'.$this->getGrammar()->getDefinition('text').'*$/D', $value)) { - $encoded = true; - // Allow space for the indices, charset and language - $maxValueLength = $this->getMaxLineLength() - strlen($name.'*N*="";') - 1; - $firstLineOffset = strlen( - $this->getCharset()."'".$this->getLanguage()."'" - ); - } - } - - // Encode if we need to - if ($encoded || strlen($value) > $maxValueLength) { - if (isset($this->_paramEncoder)) { - $value = $this->_paramEncoder->encodeString( - $origValue, $firstLineOffset, $maxValueLength, $this->getCharset() - ); - } else { - // We have to go against RFC 2183/2231 in some areas for interoperability - $value = $this->getTokenAsEncodedWord($origValue); - $encoded = false; - } - } - - $valueLines = isset($this->_paramEncoder) ? explode("\r\n", $value) : array($value); - - // Need to add indices - if (count($valueLines) > 1) { - $paramLines = array(); - foreach ($valueLines as $i => $line) { - $paramLines[] = $name.'*'.$i. - $this->_getEndOfParameterValue($line, true, $i == 0); - } - - return implode(";\r\n ", $paramLines); - } else { - return $name.$this->_getEndOfParameterValue( - $valueLines[0], $encoded, true - ); - } - } - - /** - * Returns the parameter value from the "=" and beyond. - * - * @param string $value to append - * @param bool $encoded - * @param bool $firstLine - * - * @return string - */ - private function _getEndOfParameterValue($value, $encoded = false, $firstLine = false) - { - if (!preg_match('/^'.self::TOKEN_REGEX.'$/D', $value)) { - $value = '"'.$value.'"'; - } - $prepend = '='; - if ($encoded) { - $prepend = '*='; - if ($firstLine) { - $prepend = '*='.$this->getCharset()."'".$this->getLanguage(). - "'"; - } - } - - return $prepend.$value; - } -} diff --git a/lib/swiftmailer/swiftmailer/lib/classes/Swift/Mime/Headers/PathHeader.php b/lib/swiftmailer/swiftmailer/lib/classes/Swift/Mime/Headers/PathHeader.php deleted file mode 100644 index 4a814b122..000000000 --- a/lib/swiftmailer/swiftmailer/lib/classes/Swift/Mime/Headers/PathHeader.php +++ /dev/null @@ -1,143 +0,0 @@ -setFieldName($name); - parent::__construct($grammar); - } - - /** - * Get the type of Header that this instance represents. - * - * @see TYPE_TEXT, TYPE_PARAMETERIZED, TYPE_MAILBOX - * @see TYPE_DATE, TYPE_ID, TYPE_PATH - * - * @return int - */ - public function getFieldType() - { - return self::TYPE_PATH; - } - - /** - * Set the model for the field body. - * This method takes a string for an address. - * - * @param string $model - * - * @throws Swift_RfcComplianceException - */ - public function setFieldBodyModel($model) - { - $this->setAddress($model); - } - - /** - * Get the model for the field body. - * This method returns a string email address. - * - * @return mixed - */ - public function getFieldBodyModel() - { - return $this->getAddress(); - } - - /** - * Set the Address which should appear in this Header. - * - * @param string $address - * - * @throws Swift_RfcComplianceException - */ - public function setAddress($address) - { - if (null === $address) { - $this->_address = null; - } elseif ('' == $address) { - $this->_address = ''; - } else { - $this->_assertValidAddress($address); - $this->_address = $address; - } - $this->setCachedValue(null); - } - - /** - * Get the address which is used in this Header (if any). - * - * Null is returned if no address is set. - * - * @return string - */ - public function getAddress() - { - return $this->_address; - } - - /** - * Get the string value of the body in this Header. - * - * This is not necessarily RFC 2822 compliant since folding white space will - * not be added at this stage (see {@link toString()} for that). - * - * @see toString() - * - * @return string - */ - public function getFieldBody() - { - if (!$this->getCachedValue()) { - if (isset($this->_address)) { - $this->setCachedValue('<'.$this->_address.'>'); - } - } - - return $this->getCachedValue(); - } - - /** - * Throws an Exception if the address passed does not comply with RFC 2822. - * - * @param string $address - * - * @throws Swift_RfcComplianceException If address is invalid - */ - private function _assertValidAddress($address) - { - if (!preg_match('/^'.$this->getGrammar()->getDefinition('addr-spec').'$/D', - $address)) { - throw new Swift_RfcComplianceException( - 'Address set in PathHeader does not comply with addr-spec of RFC 2822.' - ); - } - } -} diff --git a/lib/swiftmailer/swiftmailer/lib/classes/Swift/Mime/Headers/UnstructuredHeader.php b/lib/swiftmailer/swiftmailer/lib/classes/Swift/Mime/Headers/UnstructuredHeader.php deleted file mode 100644 index 86177f14a..000000000 --- a/lib/swiftmailer/swiftmailer/lib/classes/Swift/Mime/Headers/UnstructuredHeader.php +++ /dev/null @@ -1,112 +0,0 @@ -setFieldName($name); - $this->setEncoder($encoder); - parent::__construct($grammar); - } - - /** - * Get the type of Header that this instance represents. - * - * @see TYPE_TEXT, TYPE_PARAMETERIZED, TYPE_MAILBOX - * @see TYPE_DATE, TYPE_ID, TYPE_PATH - * - * @return int - */ - public function getFieldType() - { - return self::TYPE_TEXT; - } - - /** - * Set the model for the field body. - * - * This method takes a string for the field value. - * - * @param string $model - */ - public function setFieldBodyModel($model) - { - $this->setValue($model); - } - - /** - * Get the model for the field body. - * - * This method returns a string. - * - * @return string - */ - public function getFieldBodyModel() - { - return $this->getValue(); - } - - /** - * Get the (unencoded) value of this header. - * - * @return string - */ - public function getValue() - { - return $this->_value; - } - - /** - * Set the (unencoded) value of this header. - * - * @param string $value - */ - public function setValue($value) - { - $this->clearCachedValueIf($this->_value != $value); - $this->_value = $value; - } - - /** - * Get the value of this header prepared for rendering. - * - * @return string - */ - public function getFieldBody() - { - if (!$this->getCachedValue()) { - $this->setCachedValue( - $this->encodeWords($this, $this->_value) - ); - } - - return $this->getCachedValue(); - } -} diff --git a/lib/swiftmailer/swiftmailer/lib/classes/Swift/Mime/Message.php b/lib/swiftmailer/swiftmailer/lib/classes/Swift/Mime/Message.php deleted file mode 100644 index 9b36d2162..000000000 --- a/lib/swiftmailer/swiftmailer/lib/classes/Swift/Mime/Message.php +++ /dev/null @@ -1,223 +0,0 @@ - 'Real Name'). - * - * If the second parameter is provided and the first is a string, then $name - * is associated with the address. - * - * @param mixed $address - * @param string $name optional - */ - public function setSender($address, $name = null); - - /** - * Get the sender address for this message. - * - * This has a higher significance than the From address. - * - * @return string - */ - public function getSender(); - - /** - * Set the From address of this message. - * - * It is permissible for multiple From addresses to be set using an array. - * - * If multiple From addresses are used, you SHOULD set the Sender address and - * according to RFC 2822, MUST set the sender address. - * - * An array can be used if display names are to be provided: i.e. - * array('email@address.com' => 'Real Name'). - * - * If the second parameter is provided and the first is a string, then $name - * is associated with the address. - * - * @param mixed $addresses - * @param string $name optional - */ - public function setFrom($addresses, $name = null); - - /** - * Get the From address(es) of this message. - * - * This method always returns an associative array where the keys are the - * addresses. - * - * @return string[] - */ - public function getFrom(); - - /** - * Set the Reply-To address(es). - * - * Any replies from the receiver will be sent to this address. - * - * It is permissible for multiple reply-to addresses to be set using an array. - * - * This method has the same synopsis as {@link setFrom()} and {@link setTo()}. - * - * If the second parameter is provided and the first is a string, then $name - * is associated with the address. - * - * @param mixed $addresses - * @param string $name optional - */ - public function setReplyTo($addresses, $name = null); - - /** - * Get the Reply-To addresses for this message. - * - * This method always returns an associative array where the keys provide the - * email addresses. - * - * @return string[] - */ - public function getReplyTo(); - - /** - * Set the To address(es). - * - * Recipients set in this field will receive a copy of this message. - * - * This method has the same synopsis as {@link setFrom()} and {@link setCc()}. - * - * If the second parameter is provided and the first is a string, then $name - * is associated with the address. - * - * @param mixed $addresses - * @param string $name optional - */ - public function setTo($addresses, $name = null); - - /** - * Get the To addresses for this message. - * - * This method always returns an associative array, whereby the keys provide - * the actual email addresses. - * - * @return string[] - */ - public function getTo(); - - /** - * Set the Cc address(es). - * - * Recipients set in this field will receive a 'carbon-copy' of this message. - * - * This method has the same synopsis as {@link setFrom()} and {@link setTo()}. - * - * @param mixed $addresses - * @param string $name optional - */ - public function setCc($addresses, $name = null); - - /** - * Get the Cc addresses for this message. - * - * This method always returns an associative array, whereby the keys provide - * the actual email addresses. - * - * @return string[] - */ - public function getCc(); - - /** - * Set the Bcc address(es). - * - * Recipients set in this field will receive a 'blind-carbon-copy' of this - * message. - * - * In other words, they will get the message, but any other recipients of the - * message will have no such knowledge of their receipt of it. - * - * This method has the same synopsis as {@link setFrom()} and {@link setTo()}. - * - * @param mixed $addresses - * @param string $name optional - */ - public function setBcc($addresses, $name = null); - - /** - * Get the Bcc addresses for this message. - * - * This method always returns an associative array, whereby the keys provide - * the actual email addresses. - * - * @return string[] - */ - public function getBcc(); -} diff --git a/lib/swiftmailer/swiftmailer/lib/classes/Swift/Mime/MimeEntity.php b/lib/swiftmailer/swiftmailer/lib/classes/Swift/Mime/MimeEntity.php deleted file mode 100644 index 30f460cdc..000000000 --- a/lib/swiftmailer/swiftmailer/lib/classes/Swift/Mime/MimeEntity.php +++ /dev/null @@ -1,117 +0,0 @@ -setContentType('text/plain'); - if (null !== $charset) { - $this->setCharset($charset); - } - } - - /** - * Set the body of this entity, either as a string, or as an instance of - * {@link Swift_OutputByteStream}. - * - * @param mixed $body - * @param string $contentType optional - * @param string $charset optional - * - * @return $this - */ - public function setBody($body, $contentType = null, $charset = null) - { - if (isset($charset)) { - $this->setCharset($charset); - } - $body = $this->_convertString($body); - - parent::setBody($body, $contentType); - - return $this; - } - - /** - * Get the character set of this entity. - * - * @return string - */ - public function getCharset() - { - return $this->_getHeaderParameter('Content-Type', 'charset'); - } - - /** - * Set the character set of this entity. - * - * @param string $charset - * - * @return $this - */ - public function setCharset($charset) - { - $this->_setHeaderParameter('Content-Type', 'charset', $charset); - if ($charset !== $this->_userCharset) { - $this->_clearCache(); - } - $this->_userCharset = $charset; - parent::charsetChanged($charset); - - return $this; - } - - /** - * Get the format of this entity (i.e. flowed or fixed). - * - * @return string - */ - public function getFormat() - { - return $this->_getHeaderParameter('Content-Type', 'format'); - } - - /** - * Set the format of this entity (flowed or fixed). - * - * @param string $format - * - * @return $this - */ - public function setFormat($format) - { - $this->_setHeaderParameter('Content-Type', 'format', $format); - $this->_userFormat = $format; - - return $this; - } - - /** - * Test if delsp is being used for this entity. - * - * @return bool - */ - public function getDelSp() - { - return 'yes' == $this->_getHeaderParameter('Content-Type', 'delsp') ? true : false; - } - - /** - * Turn delsp on or off for this entity. - * - * @param bool $delsp - * - * @return $this - */ - public function setDelSp($delsp = true) - { - $this->_setHeaderParameter('Content-Type', 'delsp', $delsp ? 'yes' : null); - $this->_userDelSp = $delsp; - - return $this; - } - - /** - * Get the nesting level of this entity. - * - * @see LEVEL_TOP, LEVEL_ALTERNATIVE, LEVEL_MIXED, LEVEL_RELATED - * - * @return int - */ - public function getNestingLevel() - { - return $this->_nestingLevel; - } - - /** - * Receive notification that the charset has changed on this document, or a - * parent document. - * - * @param string $charset - */ - public function charsetChanged($charset) - { - $this->setCharset($charset); - } - - /** Fix the content-type and encoding of this entity */ - protected function _fixHeaders() - { - parent::_fixHeaders(); - if (count($this->getChildren())) { - $this->_setHeaderParameter('Content-Type', 'charset', null); - $this->_setHeaderParameter('Content-Type', 'format', null); - $this->_setHeaderParameter('Content-Type', 'delsp', null); - } else { - $this->setCharset($this->_userCharset); - $this->setFormat($this->_userFormat); - $this->setDelSp($this->_userDelSp); - } - } - - /** Set the nesting level of this entity */ - protected function _setNestingLevel($level) - { - $this->_nestingLevel = $level; - } - - /** Encode charset when charset is not utf-8 */ - protected function _convertString($string) - { - $charset = strtolower($this->getCharset()); - if (!in_array($charset, array('utf-8', 'iso-8859-1', 'iso-8859-15', ''))) { - // mb_convert_encoding must be the first one to check, since iconv cannot convert some words. - if (function_exists('mb_convert_encoding')) { - $string = mb_convert_encoding($string, $charset, 'utf-8'); - } elseif (function_exists('iconv')) { - $string = iconv('utf-8//TRANSLIT//IGNORE', $charset, $string); - } else { - throw new Swift_SwiftException('No suitable convert encoding function (use UTF-8 as your charset or install the mbstring or iconv extension).'); - } - - return $string; - } - - return $string; - } -} diff --git a/lib/swiftmailer/swiftmailer/lib/classes/Swift/Mime/ParameterizedHeader.php b/lib/swiftmailer/swiftmailer/lib/classes/Swift/Mime/ParameterizedHeader.php deleted file mode 100644 index e15c6ef95..000000000 --- a/lib/swiftmailer/swiftmailer/lib/classes/Swift/Mime/ParameterizedHeader.php +++ /dev/null @@ -1,34 +0,0 @@ -_encoder = $encoder; - $this->_paramEncoder = $paramEncoder; - $this->_grammar = $grammar; - $this->_charset = $charset; - } - - /** - * Create a new Mailbox Header with a list of $addresses. - * - * @param string $name - * @param array|string|null $addresses - * - * @return Swift_Mime_Header - */ - public function createMailboxHeader($name, $addresses = null) - { - $header = new Swift_Mime_Headers_MailboxHeader($name, $this->_encoder, $this->_grammar); - if (isset($addresses)) { - $header->setFieldBodyModel($addresses); - } - $this->_setHeaderCharset($header); - - return $header; - } - - /** - * Create a new Date header using $timestamp (UNIX time). - * - * @param string $name - * @param int|null $timestamp - * - * @return Swift_Mime_Header - */ - public function createDateHeader($name, $timestamp = null) - { - $header = new Swift_Mime_Headers_DateHeader($name, $this->_grammar); - if (isset($timestamp)) { - $header->setFieldBodyModel($timestamp); - } - $this->_setHeaderCharset($header); - - return $header; - } - - /** - * Create a new basic text header with $name and $value. - * - * @param string $name - * @param string $value - * - * @return Swift_Mime_Header - */ - public function createTextHeader($name, $value = null) - { - $header = new Swift_Mime_Headers_UnstructuredHeader($name, $this->_encoder, $this->_grammar); - if (isset($value)) { - $header->setFieldBodyModel($value); - } - $this->_setHeaderCharset($header); - - return $header; - } - - /** - * Create a new ParameterizedHeader with $name, $value and $params. - * - * @param string $name - * @param string $value - * @param array $params - * - * @return Swift_Mime_ParameterizedHeader - */ - public function createParameterizedHeader($name, $value = null, - $params = array()) - { - $header = new Swift_Mime_Headers_ParameterizedHeader($name, $this->_encoder, strtolower($name) == 'content-disposition' ? $this->_paramEncoder : null, $this->_grammar); - if (isset($value)) { - $header->setFieldBodyModel($value); - } - foreach ($params as $k => $v) { - $header->setParameter($k, $v); - } - $this->_setHeaderCharset($header); - - return $header; - } - - /** - * Create a new ID header for Message-ID or Content-ID. - * - * @param string $name - * @param string|array $ids - * - * @return Swift_Mime_Header - */ - public function createIdHeader($name, $ids = null) - { - $header = new Swift_Mime_Headers_IdentificationHeader($name, $this->_grammar); - if (isset($ids)) { - $header->setFieldBodyModel($ids); - } - $this->_setHeaderCharset($header); - - return $header; - } - - /** - * Create a new Path header with an address (path) in it. - * - * @param string $name - * @param string $path - * - * @return Swift_Mime_Header - */ - public function createPathHeader($name, $path = null) - { - $header = new Swift_Mime_Headers_PathHeader($name, $this->_grammar); - if (isset($path)) { - $header->setFieldBodyModel($path); - } - $this->_setHeaderCharset($header); - - return $header; - } - - /** - * Notify this observer that the entity's charset has changed. - * - * @param string $charset - */ - public function charsetChanged($charset) - { - $this->_charset = $charset; - $this->_encoder->charsetChanged($charset); - $this->_paramEncoder->charsetChanged($charset); - } - - /** - * Make a deep copy of object. - */ - public function __clone() - { - $this->_encoder = clone $this->_encoder; - $this->_paramEncoder = clone $this->_paramEncoder; - } - - /** Apply the charset to the Header */ - private function _setHeaderCharset(Swift_Mime_Header $header) - { - if (isset($this->_charset)) { - $header->setCharset($this->_charset); - } - } -} diff --git a/lib/swiftmailer/swiftmailer/lib/classes/Swift/Mime/SimpleHeaderSet.php b/lib/swiftmailer/swiftmailer/lib/classes/Swift/Mime/SimpleHeaderSet.php deleted file mode 100644 index a06ce7247..000000000 --- a/lib/swiftmailer/swiftmailer/lib/classes/Swift/Mime/SimpleHeaderSet.php +++ /dev/null @@ -1,414 +0,0 @@ -_factory = $factory; - if (isset($charset)) { - $this->setCharset($charset); - } - } - - /** - * Set the charset used by these headers. - * - * @param string $charset - */ - public function setCharset($charset) - { - $this->_charset = $charset; - $this->_factory->charsetChanged($charset); - $this->_notifyHeadersOfCharset($charset); - } - - /** - * Add a new Mailbox Header with a list of $addresses. - * - * @param string $name - * @param array|string $addresses - */ - public function addMailboxHeader($name, $addresses = null) - { - $this->_storeHeader($name, - $this->_factory->createMailboxHeader($name, $addresses)); - } - - /** - * Add a new Date header using $timestamp (UNIX time). - * - * @param string $name - * @param int $timestamp - */ - public function addDateHeader($name, $timestamp = null) - { - $this->_storeHeader($name, - $this->_factory->createDateHeader($name, $timestamp)); - } - - /** - * Add a new basic text header with $name and $value. - * - * @param string $name - * @param string $value - */ - public function addTextHeader($name, $value = null) - { - $this->_storeHeader($name, - $this->_factory->createTextHeader($name, $value)); - } - - /** - * Add a new ParameterizedHeader with $name, $value and $params. - * - * @param string $name - * @param string $value - * @param array $params - */ - public function addParameterizedHeader($name, $value = null, $params = array()) - { - $this->_storeHeader($name, $this->_factory->createParameterizedHeader($name, $value, $params)); - } - - /** - * Add a new ID header for Message-ID or Content-ID. - * - * @param string $name - * @param string|array $ids - */ - public function addIdHeader($name, $ids = null) - { - $this->_storeHeader($name, $this->_factory->createIdHeader($name, $ids)); - } - - /** - * Add a new Path header with an address (path) in it. - * - * @param string $name - * @param string $path - */ - public function addPathHeader($name, $path = null) - { - $this->_storeHeader($name, $this->_factory->createPathHeader($name, $path)); - } - - /** - * Returns true if at least one header with the given $name exists. - * - * If multiple headers match, the actual one may be specified by $index. - * - * @param string $name - * @param int $index - * - * @return bool - */ - public function has($name, $index = 0) - { - $lowerName = strtolower($name); - - if (!array_key_exists($lowerName, $this->_headers)) { - return false; - } - - if (func_num_args() < 2) { - // index was not specified, so we only need to check that there is at least one header value set - return (bool) count($this->_headers[$lowerName]); - } - - return array_key_exists($index, $this->_headers[$lowerName]); - } - - /** - * Set a header in the HeaderSet. - * - * The header may be a previously fetched header via {@link get()} or it may - * be one that has been created separately. - * - * If $index is specified, the header will be inserted into the set at this - * offset. - * - * @param Swift_Mime_Header $header - * @param int $index - */ - public function set(Swift_Mime_Header $header, $index = 0) - { - $this->_storeHeader($header->getFieldName(), $header, $index); - } - - /** - * Get the header with the given $name. - * - * If multiple headers match, the actual one may be specified by $index. - * Returns NULL if none present. - * - * @param string $name - * @param int $index - * - * @return Swift_Mime_Header - */ - public function get($name, $index = 0) - { - $name = strtolower($name); - - if (func_num_args() < 2) { - if ($this->has($name)) { - $values = array_values($this->_headers[$name]); - - return array_shift($values); - } - } else { - if ($this->has($name, $index)) { - return $this->_headers[$name][$index]; - } - } - } - - /** - * Get all headers with the given $name. - * - * @param string $name - * - * @return array - */ - public function getAll($name = null) - { - if (!isset($name)) { - $headers = array(); - foreach ($this->_headers as $collection) { - $headers = array_merge($headers, $collection); - } - - return $headers; - } - - $lowerName = strtolower($name); - if (!array_key_exists($lowerName, $this->_headers)) { - return array(); - } - - return $this->_headers[$lowerName]; - } - - /** - * Return the name of all Headers. - * - * @return array - */ - public function listAll() - { - $headers = $this->_headers; - if ($this->_canSort()) { - uksort($headers, array($this, '_sortHeaders')); - } - - return array_keys($headers); - } - - /** - * Remove the header with the given $name if it's set. - * - * If multiple headers match, the actual one may be specified by $index. - * - * @param string $name - * @param int $index - */ - public function remove($name, $index = 0) - { - $lowerName = strtolower($name); - unset($this->_headers[$lowerName][$index]); - } - - /** - * Remove all headers with the given $name. - * - * @param string $name - */ - public function removeAll($name) - { - $lowerName = strtolower($name); - unset($this->_headers[$lowerName]); - } - - /** - * Create a new instance of this HeaderSet. - * - * @return self - */ - public function newInstance() - { - return new self($this->_factory); - } - - /** - * Define a list of Header names as an array in the correct order. - * - * These Headers will be output in the given order where present. - * - * @param array $sequence - */ - public function defineOrdering(array $sequence) - { - $this->_order = array_flip(array_map('strtolower', $sequence)); - } - - /** - * Set a list of header names which must always be displayed when set. - * - * Usually headers without a field value won't be output unless set here. - * - * @param array $names - */ - public function setAlwaysDisplayed(array $names) - { - $this->_required = array_flip(array_map('strtolower', $names)); - } - - /** - * Notify this observer that the entity's charset has changed. - * - * @param string $charset - */ - public function charsetChanged($charset) - { - $this->setCharset($charset); - } - - /** - * Returns a string with a representation of all headers. - * - * @return string - */ - public function toString() - { - $string = ''; - $headers = $this->_headers; - if ($this->_canSort()) { - uksort($headers, array($this, '_sortHeaders')); - } - foreach ($headers as $collection) { - foreach ($collection as $header) { - if ($this->_isDisplayed($header) || $header->getFieldBody() != '') { - $string .= $header->toString(); - } - } - } - - return $string; - } - - /** - * Returns a string representation of this object. - * - * @return string - * - * @see toString() - */ - public function __toString() - { - return $this->toString(); - } - - /** Save a Header to the internal collection */ - private function _storeHeader($name, Swift_Mime_Header $header, $offset = null) - { - if (!isset($this->_headers[strtolower($name)])) { - $this->_headers[strtolower($name)] = array(); - } - if (!isset($offset)) { - $this->_headers[strtolower($name)][] = $header; - } else { - $this->_headers[strtolower($name)][$offset] = $header; - } - } - - /** Test if the headers can be sorted */ - private function _canSort() - { - return count($this->_order) > 0; - } - - /** uksort() algorithm for Header ordering */ - private function _sortHeaders($a, $b) - { - $lowerA = strtolower($a); - $lowerB = strtolower($b); - $aPos = array_key_exists($lowerA, $this->_order) ? $this->_order[$lowerA] : -1; - $bPos = array_key_exists($lowerB, $this->_order) ? $this->_order[$lowerB] : -1; - - if (-1 === $aPos && -1 === $bPos) { - // just be sure to be determinist here - return $a > $b ? -1 : 1; - } - - if ($aPos == -1) { - return 1; - } elseif ($bPos == -1) { - return -1; - } - - return $aPos < $bPos ? -1 : 1; - } - - /** Test if the given Header is always displayed */ - private function _isDisplayed(Swift_Mime_Header $header) - { - return array_key_exists(strtolower($header->getFieldName()), $this->_required); - } - - /** Notify all Headers of the new charset */ - private function _notifyHeadersOfCharset($charset) - { - foreach ($this->_headers as $headerGroup) { - foreach ($headerGroup as $header) { - $header->setCharset($charset); - } - } - } - - /** - * Make a deep copy of object. - */ - public function __clone() - { - $this->_factory = clone $this->_factory; - foreach ($this->_headers as $groupKey => $headerGroup) { - foreach ($headerGroup as $key => $header) { - $this->_headers[$groupKey][$key] = clone $header; - } - } - } -} diff --git a/lib/swiftmailer/swiftmailer/lib/classes/Swift/Mime/SimpleMessage.php b/lib/swiftmailer/swiftmailer/lib/classes/Swift/Mime/SimpleMessage.php deleted file mode 100644 index 72d40cee0..000000000 --- a/lib/swiftmailer/swiftmailer/lib/classes/Swift/Mime/SimpleMessage.php +++ /dev/null @@ -1,655 +0,0 @@ -getHeaders()->defineOrdering(array( - 'Return-Path', - 'Received', - 'DKIM-Signature', - 'DomainKey-Signature', - 'Sender', - 'Message-ID', - 'Date', - 'Subject', - 'From', - 'Reply-To', - 'To', - 'Cc', - 'Bcc', - 'MIME-Version', - 'Content-Type', - 'Content-Transfer-Encoding', - )); - $this->getHeaders()->setAlwaysDisplayed(array('Date', 'Message-ID', 'From')); - $this->getHeaders()->addTextHeader('MIME-Version', '1.0'); - $this->setDate(time()); - $this->setId($this->getId()); - $this->getHeaders()->addMailboxHeader('From'); - } - - /** - * Always returns {@link LEVEL_TOP} for a message instance. - * - * @return int - */ - public function getNestingLevel() - { - return self::LEVEL_TOP; - } - - /** - * Set the subject of this message. - * - * @param string $subject - * - * @return $this - */ - public function setSubject($subject) - { - if (!$this->_setHeaderFieldModel('Subject', $subject)) { - $this->getHeaders()->addTextHeader('Subject', $subject); - } - - return $this; - } - - /** - * Get the subject of this message. - * - * @return string - */ - public function getSubject() - { - return $this->_getHeaderFieldModel('Subject'); - } - - /** - * Set the date at which this message was created. - * - * @param int $date - * - * @return $this - */ - public function setDate($date) - { - if (!$this->_setHeaderFieldModel('Date', $date)) { - $this->getHeaders()->addDateHeader('Date', $date); - } - - return $this; - } - - /** - * Get the date at which this message was created. - * - * @return int - */ - public function getDate() - { - return $this->_getHeaderFieldModel('Date'); - } - - /** - * Set the return-path (the bounce address) of this message. - * - * @param string $address - * - * @return $this - */ - public function setReturnPath($address) - { - if (!$this->_setHeaderFieldModel('Return-Path', $address)) { - $this->getHeaders()->addPathHeader('Return-Path', $address); - } - - return $this; - } - - /** - * Get the return-path (bounce address) of this message. - * - * @return string - */ - public function getReturnPath() - { - return $this->_getHeaderFieldModel('Return-Path'); - } - - /** - * Set the sender of this message. - * - * This does not override the From field, but it has a higher significance. - * - * @param string $address - * @param string $name optional - * - * @return $this - */ - public function setSender($address, $name = null) - { - if (!is_array($address) && isset($name)) { - $address = array($address => $name); - } - - if (!$this->_setHeaderFieldModel('Sender', (array) $address)) { - $this->getHeaders()->addMailboxHeader('Sender', (array) $address); - } - - return $this; - } - - /** - * Get the sender of this message. - * - * @return string - */ - public function getSender() - { - return $this->_getHeaderFieldModel('Sender'); - } - - /** - * Add a From: address to this message. - * - * If $name is passed this name will be associated with the address. - * - * @param string $address - * @param string $name optional - * - * @return $this - */ - public function addFrom($address, $name = null) - { - $current = $this->getFrom(); - $current[$address] = $name; - - return $this->setFrom($current); - } - - /** - * Set the from address of this message. - * - * You may pass an array of addresses if this message is from multiple people. - * - * If $name is passed and the first parameter is a string, this name will be - * associated with the address. - * - * @param string|array $addresses - * @param string $name optional - * - * @return $this - */ - public function setFrom($addresses, $name = null) - { - if (!is_array($addresses) && isset($name)) { - $addresses = array($addresses => $name); - } - - if (!$this->_setHeaderFieldModel('From', (array) $addresses)) { - $this->getHeaders()->addMailboxHeader('From', (array) $addresses); - } - - return $this; - } - - /** - * Get the from address of this message. - * - * @return mixed - */ - public function getFrom() - { - return $this->_getHeaderFieldModel('From'); - } - - /** - * Add a Reply-To: address to this message. - * - * If $name is passed this name will be associated with the address. - * - * @param string $address - * @param string $name optional - * - * @return $this - */ - public function addReplyTo($address, $name = null) - { - $current = $this->getReplyTo(); - $current[$address] = $name; - - return $this->setReplyTo($current); - } - - /** - * Set the reply-to address of this message. - * - * You may pass an array of addresses if replies will go to multiple people. - * - * If $name is passed and the first parameter is a string, this name will be - * associated with the address. - * - * @param mixed $addresses - * @param string $name optional - * - * @return $this - */ - public function setReplyTo($addresses, $name = null) - { - if (!is_array($addresses) && isset($name)) { - $addresses = array($addresses => $name); - } - - if (!$this->_setHeaderFieldModel('Reply-To', (array) $addresses)) { - $this->getHeaders()->addMailboxHeader('Reply-To', (array) $addresses); - } - - return $this; - } - - /** - * Get the reply-to address of this message. - * - * @return string - */ - public function getReplyTo() - { - return $this->_getHeaderFieldModel('Reply-To'); - } - - /** - * Add a To: address to this message. - * - * If $name is passed this name will be associated with the address. - * - * @param string $address - * @param string $name optional - * - * @return $this - */ - public function addTo($address, $name = null) - { - $current = $this->getTo(); - $current[$address] = $name; - - return $this->setTo($current); - } - - /** - * Set the to addresses of this message. - * - * If multiple recipients will receive the message an array should be used. - * Example: array('receiver@domain.org', 'other@domain.org' => 'A name') - * - * If $name is passed and the first parameter is a string, this name will be - * associated with the address. - * - * @param mixed $addresses - * @param string $name optional - * - * @return $this - */ - public function setTo($addresses, $name = null) - { - if (!is_array($addresses) && isset($name)) { - $addresses = array($addresses => $name); - } - - if (!$this->_setHeaderFieldModel('To', (array) $addresses)) { - $this->getHeaders()->addMailboxHeader('To', (array) $addresses); - } - - return $this; - } - - /** - * Get the To addresses of this message. - * - * @return array - */ - public function getTo() - { - return $this->_getHeaderFieldModel('To'); - } - - /** - * Add a Cc: address to this message. - * - * If $name is passed this name will be associated with the address. - * - * @param string $address - * @param string $name optional - * - * @return $this - */ - public function addCc($address, $name = null) - { - $current = $this->getCc(); - $current[$address] = $name; - - return $this->setCc($current); - } - - /** - * Set the Cc addresses of this message. - * - * If $name is passed and the first parameter is a string, this name will be - * associated with the address. - * - * @param mixed $addresses - * @param string $name optional - * - * @return $this - */ - public function setCc($addresses, $name = null) - { - if (!is_array($addresses) && isset($name)) { - $addresses = array($addresses => $name); - } - - if (!$this->_setHeaderFieldModel('Cc', (array) $addresses)) { - $this->getHeaders()->addMailboxHeader('Cc', (array) $addresses); - } - - return $this; - } - - /** - * Get the Cc address of this message. - * - * @return array - */ - public function getCc() - { - return $this->_getHeaderFieldModel('Cc'); - } - - /** - * Add a Bcc: address to this message. - * - * If $name is passed this name will be associated with the address. - * - * @param string $address - * @param string $name optional - * - * @return $this - */ - public function addBcc($address, $name = null) - { - $current = $this->getBcc(); - $current[$address] = $name; - - return $this->setBcc($current); - } - - /** - * Set the Bcc addresses of this message. - * - * If $name is passed and the first parameter is a string, this name will be - * associated with the address. - * - * @param mixed $addresses - * @param string $name optional - * - * @return $this - */ - public function setBcc($addresses, $name = null) - { - if (!is_array($addresses) && isset($name)) { - $addresses = array($addresses => $name); - } - - if (!$this->_setHeaderFieldModel('Bcc', (array) $addresses)) { - $this->getHeaders()->addMailboxHeader('Bcc', (array) $addresses); - } - - return $this; - } - - /** - * Get the Bcc addresses of this message. - * - * @return array - */ - public function getBcc() - { - return $this->_getHeaderFieldModel('Bcc'); - } - - /** - * Set the priority of this message. - * - * The value is an integer where 1 is the highest priority and 5 is the lowest. - * - * @param int $priority - * - * @return $this - */ - public function setPriority($priority) - { - $priorityMap = array( - self::PRIORITY_HIGHEST => 'Highest', - self::PRIORITY_HIGH => 'High', - self::PRIORITY_NORMAL => 'Normal', - self::PRIORITY_LOW => 'Low', - self::PRIORITY_LOWEST => 'Lowest', - ); - $pMapKeys = array_keys($priorityMap); - if ($priority > max($pMapKeys)) { - $priority = max($pMapKeys); - } elseif ($priority < min($pMapKeys)) { - $priority = min($pMapKeys); - } - if (!$this->_setHeaderFieldModel('X-Priority', - sprintf('%d (%s)', $priority, $priorityMap[$priority]))) { - $this->getHeaders()->addTextHeader('X-Priority', - sprintf('%d (%s)', $priority, $priorityMap[$priority])); - } - - return $this; - } - - /** - * Get the priority of this message. - * - * The returned value is an integer where 1 is the highest priority and 5 - * is the lowest. - * - * @return int - */ - public function getPriority() - { - list($priority) = sscanf($this->_getHeaderFieldModel('X-Priority'), - '%[1-5]' - ); - - return isset($priority) ? $priority : 3; - } - - /** - * Ask for a delivery receipt from the recipient to be sent to $addresses. - * - * @param array $addresses - * - * @return $this - */ - public function setReadReceiptTo($addresses) - { - if (!$this->_setHeaderFieldModel('Disposition-Notification-To', $addresses)) { - $this->getHeaders() - ->addMailboxHeader('Disposition-Notification-To', $addresses); - } - - return $this; - } - - /** - * Get the addresses to which a read-receipt will be sent. - * - * @return string - */ - public function getReadReceiptTo() - { - return $this->_getHeaderFieldModel('Disposition-Notification-To'); - } - - /** - * Attach a {@link Swift_Mime_MimeEntity} such as an Attachment or MimePart. - * - * @param Swift_Mime_MimeEntity $entity - * - * @return $this - */ - public function attach(Swift_Mime_MimeEntity $entity) - { - $this->setChildren(array_merge($this->getChildren(), array($entity))); - - return $this; - } - - /** - * Remove an already attached entity. - * - * @param Swift_Mime_MimeEntity $entity - * - * @return $this - */ - public function detach(Swift_Mime_MimeEntity $entity) - { - $newChildren = array(); - foreach ($this->getChildren() as $child) { - if ($entity !== $child) { - $newChildren[] = $child; - } - } - $this->setChildren($newChildren); - - return $this; - } - - /** - * Attach a {@link Swift_Mime_MimeEntity} and return it's CID source. - * This method should be used when embedding images or other data in a message. - * - * @param Swift_Mime_MimeEntity $entity - * - * @return string - */ - public function embed(Swift_Mime_MimeEntity $entity) - { - $this->attach($entity); - - return 'cid:'.$entity->getId(); - } - - /** - * Get this message as a complete string. - * - * @return string - */ - public function toString() - { - if (count($children = $this->getChildren()) > 0 && $this->getBody() != '') { - $this->setChildren(array_merge(array($this->_becomeMimePart()), $children)); - $string = parent::toString(); - $this->setChildren($children); - } else { - $string = parent::toString(); - } - - return $string; - } - - /** - * Returns a string representation of this object. - * - * @see toString() - * - * @return string - */ - public function __toString() - { - return $this->toString(); - } - - /** - * Write this message to a {@link Swift_InputByteStream}. - * - * @param Swift_InputByteStream $is - */ - public function toByteStream(Swift_InputByteStream $is) - { - if (count($children = $this->getChildren()) > 0 && $this->getBody() != '') { - $this->setChildren(array_merge(array($this->_becomeMimePart()), $children)); - parent::toByteStream($is); - $this->setChildren($children); - } else { - parent::toByteStream($is); - } - } - - /** @see Swift_Mime_SimpleMimeEntity::_getIdField() */ - protected function _getIdField() - { - return 'Message-ID'; - } - - /** Turn the body of this message into a child of itself if needed */ - protected function _becomeMimePart() - { - $part = new parent($this->getHeaders()->newInstance(), $this->getEncoder(), - $this->_getCache(), $this->_getGrammar(), $this->_userCharset - ); - $part->setContentType($this->_userContentType); - $part->setBody($this->getBody()); - $part->setFormat($this->_userFormat); - $part->setDelSp($this->_userDelSp); - $part->_setNestingLevel($this->_getTopNestingLevel()); - - return $part; - } - - /** Get the highest nesting level nested inside this message */ - private function _getTopNestingLevel() - { - $highestLevel = $this->getNestingLevel(); - foreach ($this->getChildren() as $child) { - $childLevel = $child->getNestingLevel(); - if ($highestLevel < $childLevel) { - $highestLevel = $childLevel; - } - } - - return $highestLevel; - } -} diff --git a/lib/swiftmailer/swiftmailer/lib/classes/Swift/Mime/SimpleMimeEntity.php b/lib/swiftmailer/swiftmailer/lib/classes/Swift/Mime/SimpleMimeEntity.php deleted file mode 100644 index a13f1b23d..000000000 --- a/lib/swiftmailer/swiftmailer/lib/classes/Swift/Mime/SimpleMimeEntity.php +++ /dev/null @@ -1,846 +0,0 @@ - array(self::LEVEL_TOP, self::LEVEL_MIXED), - 'multipart/alternative' => array(self::LEVEL_MIXED, self::LEVEL_ALTERNATIVE), - 'multipart/related' => array(self::LEVEL_ALTERNATIVE, self::LEVEL_RELATED), - ); - - /** A set of filter rules to define what level an entity should be nested at */ - private $_compoundLevelFilters = array(); - - /** The nesting level of this entity */ - private $_nestingLevel = self::LEVEL_ALTERNATIVE; - - /** A KeyCache instance used during encoding and streaming */ - private $_cache; - - /** Direct descendants of this entity */ - private $_immediateChildren = array(); - - /** All descendants of this entity */ - private $_children = array(); - - /** The maximum line length of the body of this entity */ - private $_maxLineLength = 78; - - /** The order in which alternative mime types should appear */ - private $_alternativePartOrder = array( - 'text/plain' => 1, - 'text/html' => 2, - 'multipart/related' => 3, - ); - - /** The CID of this entity */ - private $_id; - - /** The key used for accessing the cache */ - private $_cacheKey; - - protected $_userContentType; - - /** - * Create a new SimpleMimeEntity with $headers, $encoder and $cache. - * - * @param Swift_Mime_HeaderSet $headers - * @param Swift_Mime_ContentEncoder $encoder - * @param Swift_KeyCache $cache - * @param Swift_Mime_Grammar $grammar - */ - public function __construct(Swift_Mime_HeaderSet $headers, Swift_Mime_ContentEncoder $encoder, Swift_KeyCache $cache, Swift_Mime_Grammar $grammar) - { - $this->_cacheKey = md5(uniqid(getmypid().mt_rand(), true)); - $this->_cache = $cache; - $this->_headers = $headers; - $this->_grammar = $grammar; - $this->setEncoder($encoder); - $this->_headers->defineOrdering(array('Content-Type', 'Content-Transfer-Encoding')); - - // This array specifies that, when the entire MIME document contains - // $compoundLevel, then for each child within $level, if its Content-Type - // is $contentType then it should be treated as if it's level is - // $neededLevel instead. I tried to write that unambiguously! :-\ - // Data Structure: - // array ( - // $compoundLevel => array( - // $level => array( - // $contentType => $neededLevel - // ) - // ) - // ) - - $this->_compoundLevelFilters = array( - (self::LEVEL_ALTERNATIVE + self::LEVEL_RELATED) => array( - self::LEVEL_ALTERNATIVE => array( - 'text/plain' => self::LEVEL_ALTERNATIVE, - 'text/html' => self::LEVEL_RELATED, - ), - ), - ); - - $this->_id = $this->getRandomId(); - } - - /** - * Generate a new Content-ID or Message-ID for this MIME entity. - * - * @return string - */ - public function generateId() - { - $this->setId($this->getRandomId()); - - return $this->_id; - } - - /** - * Get the {@link Swift_Mime_HeaderSet} for this entity. - * - * @return Swift_Mime_HeaderSet - */ - public function getHeaders() - { - return $this->_headers; - } - - /** - * Get the nesting level of this entity. - * - * @see LEVEL_TOP, LEVEL_MIXED, LEVEL_RELATED, LEVEL_ALTERNATIVE - * - * @return int - */ - public function getNestingLevel() - { - return $this->_nestingLevel; - } - - /** - * Get the Content-type of this entity. - * - * @return string - */ - public function getContentType() - { - return $this->_getHeaderFieldModel('Content-Type'); - } - - /** - * Set the Content-type of this entity. - * - * @param string $type - * - * @return $this - */ - public function setContentType($type) - { - $this->_setContentTypeInHeaders($type); - // Keep track of the value so that if the content-type changes automatically - // due to added child entities, it can be restored if they are later removed - $this->_userContentType = $type; - - return $this; - } - - /** - * Get the CID of this entity. - * - * The CID will only be present in headers if a Content-ID header is present. - * - * @return string - */ - public function getId() - { - $tmp = (array) $this->_getHeaderFieldModel($this->_getIdField()); - - return $this->_headers->has($this->_getIdField()) ? current($tmp) : $this->_id; - } - - /** - * Set the CID of this entity. - * - * @param string $id - * - * @return $this - */ - public function setId($id) - { - if (!$this->_setHeaderFieldModel($this->_getIdField(), $id)) { - $this->_headers->addIdHeader($this->_getIdField(), $id); - } - $this->_id = $id; - - return $this; - } - - /** - * Get the description of this entity. - * - * This value comes from the Content-Description header if set. - * - * @return string - */ - public function getDescription() - { - return $this->_getHeaderFieldModel('Content-Description'); - } - - /** - * Set the description of this entity. - * - * This method sets a value in the Content-ID header. - * - * @param string $description - * - * @return $this - */ - public function setDescription($description) - { - if (!$this->_setHeaderFieldModel('Content-Description', $description)) { - $this->_headers->addTextHeader('Content-Description', $description); - } - - return $this; - } - - /** - * Get the maximum line length of the body of this entity. - * - * @return int - */ - public function getMaxLineLength() - { - return $this->_maxLineLength; - } - - /** - * Set the maximum line length of lines in this body. - * - * Though not enforced by the library, lines should not exceed 1000 chars. - * - * @param int $length - * - * @return $this - */ - public function setMaxLineLength($length) - { - $this->_maxLineLength = $length; - - return $this; - } - - /** - * Get all children added to this entity. - * - * @return Swift_Mime_MimeEntity[] - */ - public function getChildren() - { - return $this->_children; - } - - /** - * Set all children of this entity. - * - * @param Swift_Mime_MimeEntity[] $children - * @param int $compoundLevel For internal use only - * - * @return $this - */ - public function setChildren(array $children, $compoundLevel = null) - { - // TODO: Try to refactor this logic - - $compoundLevel = isset($compoundLevel) ? $compoundLevel : $this->_getCompoundLevel($children); - $immediateChildren = array(); - $grandchildren = array(); - $newContentType = $this->_userContentType; - - foreach ($children as $child) { - $level = $this->_getNeededChildLevel($child, $compoundLevel); - if (empty($immediateChildren)) { - //first iteration - $immediateChildren = array($child); - } else { - $nextLevel = $this->_getNeededChildLevel($immediateChildren[0], $compoundLevel); - if ($nextLevel == $level) { - $immediateChildren[] = $child; - } elseif ($level < $nextLevel) { - // Re-assign immediateChildren to grandchildren - $grandchildren = array_merge($grandchildren, $immediateChildren); - // Set new children - $immediateChildren = array($child); - } else { - $grandchildren[] = $child; - } - } - } - - if ($immediateChildren) { - $lowestLevel = $this->_getNeededChildLevel($immediateChildren[0], $compoundLevel); - - // Determine which composite media type is needed to accommodate the - // immediate children - foreach ($this->_compositeRanges as $mediaType => $range) { - if ($lowestLevel > $range[0] && $lowestLevel <= $range[1]) { - $newContentType = $mediaType; - - break; - } - } - - // Put any grandchildren in a subpart - if (!empty($grandchildren)) { - $subentity = $this->_createChild(); - $subentity->_setNestingLevel($lowestLevel); - $subentity->setChildren($grandchildren, $compoundLevel); - array_unshift($immediateChildren, $subentity); - } - } - - $this->_immediateChildren = $immediateChildren; - $this->_children = $children; - $this->_setContentTypeInHeaders($newContentType); - $this->_fixHeaders(); - $this->_sortChildren(); - - return $this; - } - - /** - * Get the body of this entity as a string. - * - * @return string - */ - public function getBody() - { - return $this->_body instanceof Swift_OutputByteStream ? $this->_readStream($this->_body) : $this->_body; - } - - /** - * Set the body of this entity, either as a string, or as an instance of - * {@link Swift_OutputByteStream}. - * - * @param mixed $body - * @param string $contentType optional - * - * @return $this - */ - public function setBody($body, $contentType = null) - { - if ($body !== $this->_body) { - $this->_clearCache(); - } - - $this->_body = $body; - if (isset($contentType)) { - $this->setContentType($contentType); - } - - return $this; - } - - /** - * Get the encoder used for the body of this entity. - * - * @return Swift_Mime_ContentEncoder - */ - public function getEncoder() - { - return $this->_encoder; - } - - /** - * Set the encoder used for the body of this entity. - * - * @param Swift_Mime_ContentEncoder $encoder - * - * @return $this - */ - public function setEncoder(Swift_Mime_ContentEncoder $encoder) - { - if ($encoder !== $this->_encoder) { - $this->_clearCache(); - } - - $this->_encoder = $encoder; - $this->_setEncoding($encoder->getName()); - $this->_notifyEncoderChanged($encoder); - - return $this; - } - - /** - * Get the boundary used to separate children in this entity. - * - * @return string - */ - public function getBoundary() - { - if (!isset($this->_boundary)) { - $this->_boundary = '_=_swift_v4_'.time().'_'.md5(getmypid().mt_rand().uniqid('', true)).'_=_'; - } - - return $this->_boundary; - } - - /** - * Set the boundary used to separate children in this entity. - * - * @param string $boundary - * - * @throws Swift_RfcComplianceException - * - * @return $this - */ - public function setBoundary($boundary) - { - $this->_assertValidBoundary($boundary); - $this->_boundary = $boundary; - - return $this; - } - - /** - * Receive notification that the charset of this entity, or a parent entity - * has changed. - * - * @param string $charset - */ - public function charsetChanged($charset) - { - $this->_notifyCharsetChanged($charset); - } - - /** - * Receive notification that the encoder of this entity or a parent entity - * has changed. - * - * @param Swift_Mime_ContentEncoder $encoder - */ - public function encoderChanged(Swift_Mime_ContentEncoder $encoder) - { - $this->_notifyEncoderChanged($encoder); - } - - /** - * Get this entire entity as a string. - * - * @return string - */ - public function toString() - { - $string = $this->_headers->toString(); - $string .= $this->_bodyToString(); - - return $string; - } - - /** - * Get this entire entity as a string. - * - * @return string - */ - protected function _bodyToString() - { - $string = ''; - - if (isset($this->_body) && empty($this->_immediateChildren)) { - if ($this->_cache->hasKey($this->_cacheKey, 'body')) { - $body = $this->_cache->getString($this->_cacheKey, 'body'); - } else { - $body = "\r\n".$this->_encoder->encodeString($this->getBody(), 0, $this->getMaxLineLength()); - $this->_cache->setString($this->_cacheKey, 'body', $body, Swift_KeyCache::MODE_WRITE); - } - $string .= $body; - } - - if (!empty($this->_immediateChildren)) { - foreach ($this->_immediateChildren as $child) { - $string .= "\r\n\r\n--".$this->getBoundary()."\r\n"; - $string .= $child->toString(); - } - $string .= "\r\n\r\n--".$this->getBoundary()."--\r\n"; - } - - return $string; - } - - /** - * Returns a string representation of this object. - * - * @see toString() - * - * @return string - */ - public function __toString() - { - return $this->toString(); - } - - /** - * Write this entire entity to a {@see Swift_InputByteStream}. - * - * @param Swift_InputByteStream - */ - public function toByteStream(Swift_InputByteStream $is) - { - $is->write($this->_headers->toString()); - $is->commit(); - - $this->_bodyToByteStream($is); - } - - /** - * Write this entire entity to a {@link Swift_InputByteStream}. - * - * @param Swift_InputByteStream - */ - protected function _bodyToByteStream(Swift_InputByteStream $is) - { - if (empty($this->_immediateChildren)) { - if (isset($this->_body)) { - if ($this->_cache->hasKey($this->_cacheKey, 'body')) { - $this->_cache->exportToByteStream($this->_cacheKey, 'body', $is); - } else { - $cacheIs = $this->_cache->getInputByteStream($this->_cacheKey, 'body'); - if ($cacheIs) { - $is->bind($cacheIs); - } - - $is->write("\r\n"); - - if ($this->_body instanceof Swift_OutputByteStream) { - $this->_body->setReadPointer(0); - - $this->_encoder->encodeByteStream($this->_body, $is, 0, $this->getMaxLineLength()); - } else { - $is->write($this->_encoder->encodeString($this->getBody(), 0, $this->getMaxLineLength())); - } - - if ($cacheIs) { - $is->unbind($cacheIs); - } - } - } - } - - if (!empty($this->_immediateChildren)) { - foreach ($this->_immediateChildren as $child) { - $is->write("\r\n\r\n--".$this->getBoundary()."\r\n"); - $child->toByteStream($is); - } - $is->write("\r\n\r\n--".$this->getBoundary()."--\r\n"); - } - } - - /** - * Get the name of the header that provides the ID of this entity. - */ - protected function _getIdField() - { - return 'Content-ID'; - } - - /** - * Get the model data (usually an array or a string) for $field. - */ - protected function _getHeaderFieldModel($field) - { - if ($this->_headers->has($field)) { - return $this->_headers->get($field)->getFieldBodyModel(); - } - } - - /** - * Set the model data for $field. - */ - protected function _setHeaderFieldModel($field, $model) - { - if ($this->_headers->has($field)) { - $this->_headers->get($field)->setFieldBodyModel($model); - - return true; - } - - return false; - } - - /** - * Get the parameter value of $parameter on $field header. - */ - protected function _getHeaderParameter($field, $parameter) - { - if ($this->_headers->has($field)) { - return $this->_headers->get($field)->getParameter($parameter); - } - } - - /** - * Set the parameter value of $parameter on $field header. - */ - protected function _setHeaderParameter($field, $parameter, $value) - { - if ($this->_headers->has($field)) { - $this->_headers->get($field)->setParameter($parameter, $value); - - return true; - } - - return false; - } - - /** - * Re-evaluate what content type and encoding should be used on this entity. - */ - protected function _fixHeaders() - { - if (count($this->_immediateChildren)) { - $this->_setHeaderParameter('Content-Type', 'boundary', - $this->getBoundary() - ); - $this->_headers->remove('Content-Transfer-Encoding'); - } else { - $this->_setHeaderParameter('Content-Type', 'boundary', null); - $this->_setEncoding($this->_encoder->getName()); - } - } - - /** - * Get the KeyCache used in this entity. - * - * @return Swift_KeyCache - */ - protected function _getCache() - { - return $this->_cache; - } - - /** - * Get the grammar used for validation. - * - * @return Swift_Mime_Grammar - */ - protected function _getGrammar() - { - return $this->_grammar; - } - - /** - * Empty the KeyCache for this entity. - */ - protected function _clearCache() - { - $this->_cache->clearKey($this->_cacheKey, 'body'); - } - - /** - * Returns a random Content-ID or Message-ID. - * - * @return string - */ - protected function getRandomId() - { - $idLeft = md5(getmypid().'.'.time().'.'.uniqid(mt_rand(), true)); - $idRight = !empty($_SERVER['SERVER_NAME']) ? $_SERVER['SERVER_NAME'] : 'swift.generated'; - $id = $idLeft.'@'.$idRight; - - try { - $this->_assertValidId($id); - } catch (Swift_RfcComplianceException $e) { - $id = $idLeft.'@swift.generated'; - } - - return $id; - } - - private function _readStream(Swift_OutputByteStream $os) - { - $string = ''; - while (false !== $bytes = $os->read(8192)) { - $string .= $bytes; - } - - $os->setReadPointer(0); - - return $string; - } - - private function _setEncoding($encoding) - { - if (!$this->_setHeaderFieldModel('Content-Transfer-Encoding', $encoding)) { - $this->_headers->addTextHeader('Content-Transfer-Encoding', $encoding); - } - } - - private function _assertValidBoundary($boundary) - { - if (!preg_match('/^[a-z0-9\'\(\)\+_\-,\.\/:=\?\ ]{0,69}[a-z0-9\'\(\)\+_\-,\.\/:=\?]$/Di', $boundary)) { - throw new Swift_RfcComplianceException('Mime boundary set is not RFC 2046 compliant.'); - } - } - - private function _setContentTypeInHeaders($type) - { - if (!$this->_setHeaderFieldModel('Content-Type', $type)) { - $this->_headers->addParameterizedHeader('Content-Type', $type); - } - } - - private function _setNestingLevel($level) - { - $this->_nestingLevel = $level; - } - - private function _getCompoundLevel($children) - { - $level = 0; - foreach ($children as $child) { - $level |= $child->getNestingLevel(); - } - - return $level; - } - - private function _getNeededChildLevel($child, $compoundLevel) - { - $filter = array(); - foreach ($this->_compoundLevelFilters as $bitmask => $rules) { - if (($compoundLevel & $bitmask) === $bitmask) { - $filter = $rules + $filter; - } - } - - $realLevel = $child->getNestingLevel(); - $lowercaseType = strtolower($child->getContentType()); - - if (isset($filter[$realLevel]) && isset($filter[$realLevel][$lowercaseType])) { - return $filter[$realLevel][$lowercaseType]; - } - - return $realLevel; - } - - private function _createChild() - { - return new self($this->_headers->newInstance(), $this->_encoder, $this->_cache, $this->_grammar); - } - - private function _notifyEncoderChanged(Swift_Mime_ContentEncoder $encoder) - { - foreach ($this->_immediateChildren as $child) { - $child->encoderChanged($encoder); - } - } - - private function _notifyCharsetChanged($charset) - { - $this->_encoder->charsetChanged($charset); - $this->_headers->charsetChanged($charset); - foreach ($this->_immediateChildren as $child) { - $child->charsetChanged($charset); - } - } - - private function _sortChildren() - { - $shouldSort = false; - foreach ($this->_immediateChildren as $child) { - // NOTE: This include alternative parts moved into a related part - if ($child->getNestingLevel() == self::LEVEL_ALTERNATIVE) { - $shouldSort = true; - break; - } - } - - // Sort in order of preference, if there is one - if ($shouldSort) { - // Group the messages by order of preference - $sorted = array(); - foreach ($this->_immediateChildren as $child) { - $type = $child->getContentType(); - $level = array_key_exists($type, $this->_alternativePartOrder) ? $this->_alternativePartOrder[$type] : max($this->_alternativePartOrder) + 1; - - if (empty($sorted[$level])) { - $sorted[$level] = array(); - } - - $sorted[$level][] = $child; - } - - ksort($sorted); - - $this->_immediateChildren = array_reduce($sorted, 'array_merge', array()); - } - } - - /** - * Empties it's own contents from the cache. - */ - public function __destruct() - { - if ($this->_cache instanceof Swift_KeyCache) { - $this->_cache->clearAll($this->_cacheKey); - } - } - - /** - * Throws an Exception if the id passed does not comply with RFC 2822. - * - * @param string $id - * - * @throws Swift_RfcComplianceException - */ - private function _assertValidId($id) - { - if (!preg_match('/^'.$this->_grammar->getDefinition('id-left').'@'.$this->_grammar->getDefinition('id-right').'$/D', $id)) { - throw new Swift_RfcComplianceException('Invalid ID given <'.$id.'>'); - } - } - - /** - * Make a deep copy of object. - */ - public function __clone() - { - $this->_headers = clone $this->_headers; - $this->_encoder = clone $this->_encoder; - $this->_cacheKey = md5(uniqid(getmypid().mt_rand(), true)); - $children = array(); - foreach ($this->_children as $pos => $child) { - $children[$pos] = clone $child; - } - $this->setChildren($children); - } -} diff --git a/lib/swiftmailer/swiftmailer/lib/classes/Swift/MimePart.php b/lib/swiftmailer/swiftmailer/lib/classes/Swift/MimePart.php deleted file mode 100644 index 525b7ec8e..000000000 --- a/lib/swiftmailer/swiftmailer/lib/classes/Swift/MimePart.php +++ /dev/null @@ -1,59 +0,0 @@ -createDependenciesFor('mime.part') - ); - - if (!isset($charset)) { - $charset = Swift_DependencyContainer::getInstance() - ->lookup('properties.charset'); - } - $this->setBody($body); - $this->setCharset($charset); - if ($contentType) { - $this->setContentType($contentType); - } - } - - /** - * Create a new MimePart. - * - * @param string $body - * @param string $contentType - * @param string $charset - * - * @return self - */ - public static function newInstance($body = null, $contentType = null, $charset = null) - { - return new self($body, $contentType, $charset); - } -} diff --git a/lib/swiftmailer/swiftmailer/lib/classes/Swift/NullTransport.php b/lib/swiftmailer/swiftmailer/lib/classes/Swift/NullTransport.php deleted file mode 100644 index ddde335c5..000000000 --- a/lib/swiftmailer/swiftmailer/lib/classes/Swift/NullTransport.php +++ /dev/null @@ -1,36 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -/** - * Pretends messages have been sent, but just ignores them. - * - * @author Fabien Potencier - */ -class Swift_NullTransport extends Swift_Transport_NullTransport -{ - public function __construct() - { - call_user_func_array( - array($this, 'Swift_Transport_NullTransport::__construct'), - Swift_DependencyContainer::getInstance() - ->createDependenciesFor('transport.null') - ); - } - - /** - * Create a new NullTransport instance. - * - * @return self - */ - public static function newInstance() - { - return new self(); - } -} diff --git a/lib/swiftmailer/swiftmailer/lib/classes/Swift/OutputByteStream.php b/lib/swiftmailer/swiftmailer/lib/classes/Swift/OutputByteStream.php deleted file mode 100644 index 1f26f9be5..000000000 --- a/lib/swiftmailer/swiftmailer/lib/classes/Swift/OutputByteStream.php +++ /dev/null @@ -1,46 +0,0 @@ -setThreshold($threshold); - $this->setSleepTime($sleep); - $this->_sleeper = $sleeper; - } - - /** - * Set the number of emails to send before restarting. - * - * @param int $threshold - */ - public function setThreshold($threshold) - { - $this->_threshold = $threshold; - } - - /** - * Get the number of emails to send before restarting. - * - * @return int - */ - public function getThreshold() - { - return $this->_threshold; - } - - /** - * Set the number of seconds to sleep for during a restart. - * - * @param int $sleep time - */ - public function setSleepTime($sleep) - { - $this->_sleep = $sleep; - } - - /** - * Get the number of seconds to sleep for during a restart. - * - * @return int - */ - public function getSleepTime() - { - return $this->_sleep; - } - - /** - * Invoked immediately before the Message is sent. - * - * @param Swift_Events_SendEvent $evt - */ - public function beforeSendPerformed(Swift_Events_SendEvent $evt) - { - } - - /** - * Invoked immediately after the Message is sent. - * - * @param Swift_Events_SendEvent $evt - */ - public function sendPerformed(Swift_Events_SendEvent $evt) - { - ++$this->_counter; - if ($this->_counter >= $this->_threshold) { - $transport = $evt->getTransport(); - $transport->stop(); - if ($this->_sleep) { - $this->sleep($this->_sleep); - } - $transport->start(); - $this->_counter = 0; - } - } - - /** - * Sleep for $seconds. - * - * @param int $seconds - */ - public function sleep($seconds) - { - if (isset($this->_sleeper)) { - $this->_sleeper->sleep($seconds); - } else { - sleep($seconds); - } - } -} diff --git a/lib/swiftmailer/swiftmailer/lib/classes/Swift/Plugins/BandwidthMonitorPlugin.php b/lib/swiftmailer/swiftmailer/lib/classes/Swift/Plugins/BandwidthMonitorPlugin.php deleted file mode 100644 index f7e18d0eb..000000000 --- a/lib/swiftmailer/swiftmailer/lib/classes/Swift/Plugins/BandwidthMonitorPlugin.php +++ /dev/null @@ -1,164 +0,0 @@ -getMessage(); - $message->toByteStream($this); - } - - /** - * Invoked immediately following a command being sent. - * - * @param Swift_Events_CommandEvent $evt - */ - public function commandSent(Swift_Events_CommandEvent $evt) - { - $command = $evt->getCommand(); - $this->_out += strlen($command); - } - - /** - * Invoked immediately following a response coming back. - * - * @param Swift_Events_ResponseEvent $evt - */ - public function responseReceived(Swift_Events_ResponseEvent $evt) - { - $response = $evt->getResponse(); - $this->_in += strlen($response); - } - - /** - * Called when a message is sent so that the outgoing counter can be increased. - * - * @param string $bytes - */ - public function write($bytes) - { - $this->_out += strlen($bytes); - foreach ($this->_mirrors as $stream) { - $stream->write($bytes); - } - } - - /** - * Not used. - */ - public function commit() - { - } - - /** - * Attach $is to this stream. - * - * The stream acts as an observer, receiving all data that is written. - * All {@link write()} and {@link flushBuffers()} operations will be mirrored. - * - * @param Swift_InputByteStream $is - */ - public function bind(Swift_InputByteStream $is) - { - $this->_mirrors[] = $is; - } - - /** - * Remove an already bound stream. - * - * If $is is not bound, no errors will be raised. - * If the stream currently has any buffered data it will be written to $is - * before unbinding occurs. - * - * @param Swift_InputByteStream $is - */ - public function unbind(Swift_InputByteStream $is) - { - foreach ($this->_mirrors as $k => $stream) { - if ($is === $stream) { - unset($this->_mirrors[$k]); - } - } - } - - /** - * Not used. - */ - public function flushBuffers() - { - foreach ($this->_mirrors as $stream) { - $stream->flushBuffers(); - } - } - - /** - * Get the total number of bytes sent to the server. - * - * @return int - */ - public function getBytesOut() - { - return $this->_out; - } - - /** - * Get the total number of bytes received from the server. - * - * @return int - */ - public function getBytesIn() - { - return $this->_in; - } - - /** - * Reset the internal counters to zero. - */ - public function reset() - { - $this->_out = 0; - $this->_in = 0; - } -} diff --git a/lib/swiftmailer/swiftmailer/lib/classes/Swift/Plugins/Decorator/Replacements.php b/lib/swiftmailer/swiftmailer/lib/classes/Swift/Plugins/Decorator/Replacements.php deleted file mode 100644 index 9f9f08b56..000000000 --- a/lib/swiftmailer/swiftmailer/lib/classes/Swift/Plugins/Decorator/Replacements.php +++ /dev/null @@ -1,31 +0,0 @@ - - * $replacements = array( - * "address1@domain.tld" => array("{a}" => "b", "{c}" => "d"), - * "address2@domain.tld" => array("{a}" => "x", "{c}" => "y") - * ) - * - * - * When using an instance of {@link Swift_Plugins_Decorator_Replacements}, - * the object should return just the array of replacements for the address - * given to {@link Swift_Plugins_Decorator_Replacements::getReplacementsFor()}. - * - * @param mixed $replacements Array or Swift_Plugins_Decorator_Replacements - */ - public function __construct($replacements) - { - $this->setReplacements($replacements); - } - - /** - * Sets replacements. - * - * @param mixed $replacements Array or Swift_Plugins_Decorator_Replacements - * - * @see __construct() - */ - public function setReplacements($replacements) - { - if (!($replacements instanceof Swift_Plugins_Decorator_Replacements)) { - $this->_replacements = (array) $replacements; - } else { - $this->_replacements = $replacements; - } - } - - /** - * Invoked immediately before the Message is sent. - * - * @param Swift_Events_SendEvent $evt - */ - public function beforeSendPerformed(Swift_Events_SendEvent $evt) - { - $message = $evt->getMessage(); - $this->_restoreMessage($message); - $to = array_keys($message->getTo()); - $address = array_shift($to); - if ($replacements = $this->getReplacementsFor($address)) { - $body = $message->getBody(); - $search = array_keys($replacements); - $replace = array_values($replacements); - $bodyReplaced = str_replace( - $search, $replace, $body - ); - if ($body != $bodyReplaced) { - $this->_originalBody = $body; - $message->setBody($bodyReplaced); - } - - foreach ($message->getHeaders()->getAll() as $header) { - $body = $header->getFieldBodyModel(); - $count = 0; - if (is_array($body)) { - $bodyReplaced = array(); - foreach ($body as $key => $value) { - $count1 = 0; - $count2 = 0; - $key = is_string($key) ? str_replace($search, $replace, $key, $count1) : $key; - $value = is_string($value) ? str_replace($search, $replace, $value, $count2) : $value; - $bodyReplaced[$key] = $value; - - if (!$count && ($count1 || $count2)) { - $count = 1; - } - } - } else { - $bodyReplaced = str_replace($search, $replace, $body, $count); - } - - if ($count) { - $this->_originalHeaders[$header->getFieldName()] = $body; - $header->setFieldBodyModel($bodyReplaced); - } - } - - $children = (array) $message->getChildren(); - foreach ($children as $child) { - list($type) = sscanf($child->getContentType(), '%[^/]/%s'); - if ('text' == $type) { - $body = $child->getBody(); - $bodyReplaced = str_replace( - $search, $replace, $body - ); - if ($body != $bodyReplaced) { - $child->setBody($bodyReplaced); - $this->_originalChildBodies[$child->getId()] = $body; - } - } - } - $this->_lastMessage = $message; - } - } - - /** - * Find a map of replacements for the address. - * - * If this plugin was provided with a delegate instance of - * {@link Swift_Plugins_Decorator_Replacements} then the call will be - * delegated to it. Otherwise, it will attempt to find the replacements - * from the array provided in the constructor. - * - * If no replacements can be found, an empty value (NULL) is returned. - * - * @param string $address - * - * @return array - */ - public function getReplacementsFor($address) - { - if ($this->_replacements instanceof Swift_Plugins_Decorator_Replacements) { - return $this->_replacements->getReplacementsFor($address); - } - - return isset($this->_replacements[$address]) ? $this->_replacements[$address] : null; - } - - /** - * Invoked immediately after the Message is sent. - * - * @param Swift_Events_SendEvent $evt - */ - public function sendPerformed(Swift_Events_SendEvent $evt) - { - $this->_restoreMessage($evt->getMessage()); - } - - /** Restore a changed message back to its original state */ - private function _restoreMessage(Swift_Mime_Message $message) - { - if ($this->_lastMessage === $message) { - if (isset($this->_originalBody)) { - $message->setBody($this->_originalBody); - $this->_originalBody = null; - } - if (!empty($this->_originalHeaders)) { - foreach ($message->getHeaders()->getAll() as $header) { - if (array_key_exists($header->getFieldName(), $this->_originalHeaders)) { - $header->setFieldBodyModel($this->_originalHeaders[$header->getFieldName()]); - } - } - $this->_originalHeaders = array(); - } - if (!empty($this->_originalChildBodies)) { - $children = (array) $message->getChildren(); - foreach ($children as $child) { - $id = $child->getId(); - if (array_key_exists($id, $this->_originalChildBodies)) { - $child->setBody($this->_originalChildBodies[$id]); - } - } - $this->_originalChildBodies = array(); - } - $this->_lastMessage = null; - } - } -} diff --git a/lib/swiftmailer/swiftmailer/lib/classes/Swift/Plugins/ImpersonatePlugin.php b/lib/swiftmailer/swiftmailer/lib/classes/Swift/Plugins/ImpersonatePlugin.php deleted file mode 100644 index 583444053..000000000 --- a/lib/swiftmailer/swiftmailer/lib/classes/Swift/Plugins/ImpersonatePlugin.php +++ /dev/null @@ -1,69 +0,0 @@ -_sender = $sender; - } - - /** - * Invoked immediately before the Message is sent. - * - * @param Swift_Events_SendEvent $evt - */ - public function beforeSendPerformed(Swift_Events_SendEvent $evt) - { - $message = $evt->getMessage(); - $headers = $message->getHeaders(); - - // save current recipients - $headers->addPathHeader('X-Swift-Return-Path', $message->getReturnPath()); - - // replace them with the one to send to - $message->setReturnPath($this->_sender); - } - - /** - * Invoked immediately after the Message is sent. - * - * @param Swift_Events_SendEvent $evt - */ - public function sendPerformed(Swift_Events_SendEvent $evt) - { - $message = $evt->getMessage(); - - // restore original headers - $headers = $message->getHeaders(); - - if ($headers->has('X-Swift-Return-Path')) { - $message->setReturnPath($headers->get('X-Swift-Return-Path')->getAddress()); - $headers->removeAll('X-Swift-Return-Path'); - } - } -} diff --git a/lib/swiftmailer/swiftmailer/lib/classes/Swift/Plugins/Logger.php b/lib/swiftmailer/swiftmailer/lib/classes/Swift/Plugins/Logger.php deleted file mode 100644 index d9bce8935..000000000 --- a/lib/swiftmailer/swiftmailer/lib/classes/Swift/Plugins/Logger.php +++ /dev/null @@ -1,36 +0,0 @@ -_logger = $logger; - } - - /** - * Add a log entry. - * - * @param string $entry - */ - public function add($entry) - { - $this->_logger->add($entry); - } - - /** - * Clear the log contents. - */ - public function clear() - { - $this->_logger->clear(); - } - - /** - * Get this log as a string. - * - * @return string - */ - public function dump() - { - return $this->_logger->dump(); - } - - /** - * Invoked immediately following a command being sent. - * - * @param Swift_Events_CommandEvent $evt - */ - public function commandSent(Swift_Events_CommandEvent $evt) - { - $command = $evt->getCommand(); - $this->_logger->add(sprintf('>> %s', $command)); - } - - /** - * Invoked immediately following a response coming back. - * - * @param Swift_Events_ResponseEvent $evt - */ - public function responseReceived(Swift_Events_ResponseEvent $evt) - { - $response = $evt->getResponse(); - $this->_logger->add(sprintf('<< %s', $response)); - } - - /** - * Invoked just before a Transport is started. - * - * @param Swift_Events_TransportChangeEvent $evt - */ - public function beforeTransportStarted(Swift_Events_TransportChangeEvent $evt) - { - $transportName = get_class($evt->getSource()); - $this->_logger->add(sprintf('++ Starting %s', $transportName)); - } - - /** - * Invoked immediately after the Transport is started. - * - * @param Swift_Events_TransportChangeEvent $evt - */ - public function transportStarted(Swift_Events_TransportChangeEvent $evt) - { - $transportName = get_class($evt->getSource()); - $this->_logger->add(sprintf('++ %s started', $transportName)); - } - - /** - * Invoked just before a Transport is stopped. - * - * @param Swift_Events_TransportChangeEvent $evt - */ - public function beforeTransportStopped(Swift_Events_TransportChangeEvent $evt) - { - $transportName = get_class($evt->getSource()); - $this->_logger->add(sprintf('++ Stopping %s', $transportName)); - } - - /** - * Invoked immediately after the Transport is stopped. - * - * @param Swift_Events_TransportChangeEvent $evt - */ - public function transportStopped(Swift_Events_TransportChangeEvent $evt) - { - $transportName = get_class($evt->getSource()); - $this->_logger->add(sprintf('++ %s stopped', $transportName)); - } - - /** - * Invoked as a TransportException is thrown in the Transport system. - * - * @param Swift_Events_TransportExceptionEvent $evt - */ - public function exceptionThrown(Swift_Events_TransportExceptionEvent $evt) - { - $e = $evt->getException(); - $message = $e->getMessage(); - $code = $e->getCode(); - $this->_logger->add(sprintf('!! %s (code: %s)', $message, $code)); - $message .= PHP_EOL; - $message .= 'Log data:'.PHP_EOL; - $message .= $this->_logger->dump(); - $evt->cancelBubble(); - throw new Swift_TransportException($message, $code, $e->getPrevious()); - } -} diff --git a/lib/swiftmailer/swiftmailer/lib/classes/Swift/Plugins/Loggers/ArrayLogger.php b/lib/swiftmailer/swiftmailer/lib/classes/Swift/Plugins/Loggers/ArrayLogger.php deleted file mode 100644 index 865bb0aa3..000000000 --- a/lib/swiftmailer/swiftmailer/lib/classes/Swift/Plugins/Loggers/ArrayLogger.php +++ /dev/null @@ -1,72 +0,0 @@ -_size = $size; - } - - /** - * Add a log entry. - * - * @param string $entry - */ - public function add($entry) - { - $this->_log[] = $entry; - while (count($this->_log) > $this->_size) { - array_shift($this->_log); - } - } - - /** - * Clear the log contents. - */ - public function clear() - { - $this->_log = array(); - } - - /** - * Get this log as a string. - * - * @return string - */ - public function dump() - { - return implode(PHP_EOL, $this->_log); - } -} diff --git a/lib/swiftmailer/swiftmailer/lib/classes/Swift/Plugins/Loggers/EchoLogger.php b/lib/swiftmailer/swiftmailer/lib/classes/Swift/Plugins/Loggers/EchoLogger.php deleted file mode 100644 index 3583297ab..000000000 --- a/lib/swiftmailer/swiftmailer/lib/classes/Swift/Plugins/Loggers/EchoLogger.php +++ /dev/null @@ -1,58 +0,0 @@ -_isHtml = $isHtml; - } - - /** - * Add a log entry. - * - * @param string $entry - */ - public function add($entry) - { - if ($this->_isHtml) { - printf('%s%s%s', htmlspecialchars($entry, ENT_QUOTES), '
', PHP_EOL); - } else { - printf('%s%s', $entry, PHP_EOL); - } - } - - /** - * Not implemented. - */ - public function clear() - { - } - - /** - * Not implemented. - */ - public function dump() - { - } -} diff --git a/lib/swiftmailer/swiftmailer/lib/classes/Swift/Plugins/MessageLogger.php b/lib/swiftmailer/swiftmailer/lib/classes/Swift/Plugins/MessageLogger.php deleted file mode 100644 index 5ff1d9321..000000000 --- a/lib/swiftmailer/swiftmailer/lib/classes/Swift/Plugins/MessageLogger.php +++ /dev/null @@ -1,74 +0,0 @@ -messages = array(); - } - - /** - * Get the message list. - * - * @return Swift_Mime_Message[] - */ - public function getMessages() - { - return $this->messages; - } - - /** - * Get the message count. - * - * @return int count - */ - public function countMessages() - { - return count($this->messages); - } - - /** - * Empty the message list. - */ - public function clear() - { - $this->messages = array(); - } - - /** - * Invoked immediately before the Message is sent. - * - * @param Swift_Events_SendEvent $evt - */ - public function beforeSendPerformed(Swift_Events_SendEvent $evt) - { - $this->messages[] = clone $evt->getMessage(); - } - - /** - * Invoked immediately after the Message is sent. - * - * @param Swift_Events_SendEvent $evt - */ - public function sendPerformed(Swift_Events_SendEvent $evt) - { - } -} diff --git a/lib/swiftmailer/swiftmailer/lib/classes/Swift/Plugins/Pop/Pop3Connection.php b/lib/swiftmailer/swiftmailer/lib/classes/Swift/Plugins/Pop/Pop3Connection.php deleted file mode 100644 index fb99e4c94..000000000 --- a/lib/swiftmailer/swiftmailer/lib/classes/Swift/Plugins/Pop/Pop3Connection.php +++ /dev/null @@ -1,31 +0,0 @@ -_host = $host; - $this->_port = $port; - $this->_crypto = $crypto; - } - - /** - * Create a new PopBeforeSmtpPlugin for $host and $port. - * - * @param string $host - * @param int $port - * @param string $crypto as "tls" or "ssl" - * - * @return self - */ - public static function newInstance($host, $port = 110, $crypto = null) - { - return new self($host, $port, $crypto); - } - - /** - * Set a Pop3Connection to delegate to instead of connecting directly. - * - * @param Swift_Plugins_Pop_Pop3Connection $connection - * - * @return $this - */ - public function setConnection(Swift_Plugins_Pop_Pop3Connection $connection) - { - $this->_connection = $connection; - - return $this; - } - - /** - * Bind this plugin to a specific SMTP transport instance. - * - * @param Swift_Transport - */ - public function bindSmtp(Swift_Transport $smtp) - { - $this->_transport = $smtp; - } - - /** - * Set the connection timeout in seconds (default 10). - * - * @param int $timeout - * - * @return $this - */ - public function setTimeout($timeout) - { - $this->_timeout = (int) $timeout; - - return $this; - } - - /** - * Set the username to use when connecting (if needed). - * - * @param string $username - * - * @return $this - */ - public function setUsername($username) - { - $this->_username = $username; - - return $this; - } - - /** - * Set the password to use when connecting (if needed). - * - * @param string $password - * - * @return $this - */ - public function setPassword($password) - { - $this->_password = $password; - - return $this; - } - - /** - * Connect to the POP3 host and authenticate. - * - * @throws Swift_Plugins_Pop_Pop3Exception if connection fails - */ - public function connect() - { - if (isset($this->_connection)) { - $this->_connection->connect(); - } else { - if (!isset($this->_socket)) { - if (!$socket = fsockopen( - $this->_getHostString(), $this->_port, $errno, $errstr, $this->_timeout)) { - throw new Swift_Plugins_Pop_Pop3Exception( - sprintf('Failed to connect to POP3 host [%s]: %s', $this->_host, $errstr) - ); - } - $this->_socket = $socket; - - if (false === $greeting = fgets($this->_socket)) { - throw new Swift_Plugins_Pop_Pop3Exception( - sprintf('Failed to connect to POP3 host [%s]', trim($greeting)) - ); - } - - $this->_assertOk($greeting); - - if ($this->_username) { - $this->_command(sprintf("USER %s\r\n", $this->_username)); - $this->_command(sprintf("PASS %s\r\n", $this->_password)); - } - } - } - } - - /** - * Disconnect from the POP3 host. - */ - public function disconnect() - { - if (isset($this->_connection)) { - $this->_connection->disconnect(); - } else { - $this->_command("QUIT\r\n"); - if (!fclose($this->_socket)) { - throw new Swift_Plugins_Pop_Pop3Exception( - sprintf('POP3 host [%s] connection could not be stopped', $this->_host) - ); - } - $this->_socket = null; - } - } - - /** - * Invoked just before a Transport is started. - * - * @param Swift_Events_TransportChangeEvent $evt - */ - public function beforeTransportStarted(Swift_Events_TransportChangeEvent $evt) - { - if (isset($this->_transport)) { - if ($this->_transport !== $evt->getTransport()) { - return; - } - } - - $this->connect(); - $this->disconnect(); - } - - /** - * Not used. - */ - public function transportStarted(Swift_Events_TransportChangeEvent $evt) - { - } - - /** - * Not used. - */ - public function beforeTransportStopped(Swift_Events_TransportChangeEvent $evt) - { - } - - /** - * Not used. - */ - public function transportStopped(Swift_Events_TransportChangeEvent $evt) - { - } - - private function _command($command) - { - if (!fwrite($this->_socket, $command)) { - throw new Swift_Plugins_Pop_Pop3Exception( - sprintf('Failed to write command [%s] to POP3 host', trim($command)) - ); - } - - if (false === $response = fgets($this->_socket)) { - throw new Swift_Plugins_Pop_Pop3Exception( - sprintf('Failed to read from POP3 host after command [%s]', trim($command)) - ); - } - - $this->_assertOk($response); - - return $response; - } - - private function _assertOk($response) - { - if (substr($response, 0, 3) != '+OK') { - throw new Swift_Plugins_Pop_Pop3Exception( - sprintf('POP3 command failed [%s]', trim($response)) - ); - } - } - - private function _getHostString() - { - $host = $this->_host; - switch (strtolower($this->_crypto)) { - case 'ssl': - $host = 'ssl://'.$host; - break; - - case 'tls': - $host = 'tls://'.$host; - break; - } - - return $host; - } -} diff --git a/lib/swiftmailer/swiftmailer/lib/classes/Swift/Plugins/RedirectingPlugin.php b/lib/swiftmailer/swiftmailer/lib/classes/Swift/Plugins/RedirectingPlugin.php deleted file mode 100644 index c3a1f8685..000000000 --- a/lib/swiftmailer/swiftmailer/lib/classes/Swift/Plugins/RedirectingPlugin.php +++ /dev/null @@ -1,213 +0,0 @@ -_recipient = $recipient; - $this->_whitelist = $whitelist; - } - - /** - * Set the recipient of all messages. - * - * @param mixed $recipient - */ - public function setRecipient($recipient) - { - $this->_recipient = $recipient; - } - - /** - * Get the recipient of all messages. - * - * @return mixed - */ - public function getRecipient() - { - return $this->_recipient; - } - - /** - * Set a list of regular expressions to whitelist certain recipients. - * - * @param array $whitelist - */ - public function setWhitelist(array $whitelist) - { - $this->_whitelist = $whitelist; - } - - /** - * Get the whitelist. - * - * @return array - */ - public function getWhitelist() - { - return $this->_whitelist; - } - - /** - * Invoked immediately before the Message is sent. - * - * @param Swift_Events_SendEvent $evt - */ - public function beforeSendPerformed(Swift_Events_SendEvent $evt) - { - $message = $evt->getMessage(); - $headers = $message->getHeaders(); - - // conditionally save current recipients - - if ($headers->has('to')) { - $headers->addMailboxHeader('X-Swift-To', $message->getTo()); - } - - if ($headers->has('cc')) { - $headers->addMailboxHeader('X-Swift-Cc', $message->getCc()); - } - - if ($headers->has('bcc')) { - $headers->addMailboxHeader('X-Swift-Bcc', $message->getBcc()); - } - - // Filter remaining headers against whitelist - $this->_filterHeaderSet($headers, 'To'); - $this->_filterHeaderSet($headers, 'Cc'); - $this->_filterHeaderSet($headers, 'Bcc'); - - // Add each hard coded recipient - $to = $message->getTo(); - if (null === $to) { - $to = array(); - } - - foreach ((array) $this->_recipient as $recipient) { - if (!array_key_exists($recipient, $to)) { - $message->addTo($recipient); - } - } - } - - /** - * Filter header set against a whitelist of regular expressions. - * - * @param Swift_Mime_HeaderSet $headerSet - * @param string $type - */ - private function _filterHeaderSet(Swift_Mime_HeaderSet $headerSet, $type) - { - foreach ($headerSet->getAll($type) as $headers) { - $headers->setNameAddresses($this->_filterNameAddresses($headers->getNameAddresses())); - } - } - - /** - * Filtered list of addresses => name pairs. - * - * @param array $recipients - * - * @return array - */ - private function _filterNameAddresses(array $recipients) - { - $filtered = array(); - - foreach ($recipients as $address => $name) { - if ($this->_isWhitelisted($address)) { - $filtered[$address] = $name; - } - } - - return $filtered; - } - - /** - * Matches address against whitelist of regular expressions. - * - * @param $recipient - * - * @return bool - */ - protected function _isWhitelisted($recipient) - { - if (in_array($recipient, (array) $this->_recipient)) { - return true; - } - - foreach ($this->_whitelist as $pattern) { - if (preg_match($pattern, $recipient)) { - return true; - } - } - - return false; - } - - /** - * Invoked immediately after the Message is sent. - * - * @param Swift_Events_SendEvent $evt - */ - public function sendPerformed(Swift_Events_SendEvent $evt) - { - $this->_restoreMessage($evt->getMessage()); - } - - private function _restoreMessage(Swift_Mime_Message $message) - { - // restore original headers - $headers = $message->getHeaders(); - - if ($headers->has('X-Swift-To')) { - $message->setTo($headers->get('X-Swift-To')->getNameAddresses()); - $headers->removeAll('X-Swift-To'); - } else { - $message->setTo(null); - } - - if ($headers->has('X-Swift-Cc')) { - $message->setCc($headers->get('X-Swift-Cc')->getNameAddresses()); - $headers->removeAll('X-Swift-Cc'); - } - - if ($headers->has('X-Swift-Bcc')) { - $message->setBcc($headers->get('X-Swift-Bcc')->getNameAddresses()); - $headers->removeAll('X-Swift-Bcc'); - } - } -} diff --git a/lib/swiftmailer/swiftmailer/lib/classes/Swift/Plugins/Reporter.php b/lib/swiftmailer/swiftmailer/lib/classes/Swift/Plugins/Reporter.php deleted file mode 100644 index 0f21b7d60..000000000 --- a/lib/swiftmailer/swiftmailer/lib/classes/Swift/Plugins/Reporter.php +++ /dev/null @@ -1,32 +0,0 @@ -_reporter = $reporter; - } - - /** - * Not used. - */ - public function beforeSendPerformed(Swift_Events_SendEvent $evt) - { - } - - /** - * Invoked immediately after the Message is sent. - * - * @param Swift_Events_SendEvent $evt - */ - public function sendPerformed(Swift_Events_SendEvent $evt) - { - $message = $evt->getMessage(); - $failures = array_flip($evt->getFailedRecipients()); - foreach ((array) $message->getTo() as $address => $null) { - $this->_reporter->notify($message, $address, array_key_exists($address, $failures) ? Swift_Plugins_Reporter::RESULT_FAIL : Swift_Plugins_Reporter::RESULT_PASS); - } - foreach ((array) $message->getCc() as $address => $null) { - $this->_reporter->notify($message, $address, array_key_exists($address, $failures) ? Swift_Plugins_Reporter::RESULT_FAIL : Swift_Plugins_Reporter::RESULT_PASS); - } - foreach ((array) $message->getBcc() as $address => $null) { - $this->_reporter->notify($message, $address, array_key_exists($address, $failures) ? Swift_Plugins_Reporter::RESULT_FAIL : Swift_Plugins_Reporter::RESULT_PASS); - } - } -} diff --git a/lib/swiftmailer/swiftmailer/lib/classes/Swift/Plugins/Reporters/HitReporter.php b/lib/swiftmailer/swiftmailer/lib/classes/Swift/Plugins/Reporters/HitReporter.php deleted file mode 100644 index cad9d168e..000000000 --- a/lib/swiftmailer/swiftmailer/lib/classes/Swift/Plugins/Reporters/HitReporter.php +++ /dev/null @@ -1,59 +0,0 @@ -_failures_cache[$address])) { - $this->_failures[] = $address; - $this->_failures_cache[$address] = true; - } - } - - /** - * Get an array of addresses for which delivery failed. - * - * @return array - */ - public function getFailedRecipients() - { - return $this->_failures; - } - - /** - * Clear the buffer (empty the list). - */ - public function clear() - { - $this->_failures = $this->_failures_cache = array(); - } -} diff --git a/lib/swiftmailer/swiftmailer/lib/classes/Swift/Plugins/Reporters/HtmlReporter.php b/lib/swiftmailer/swiftmailer/lib/classes/Swift/Plugins/Reporters/HtmlReporter.php deleted file mode 100644 index c62593557..000000000 --- a/lib/swiftmailer/swiftmailer/lib/classes/Swift/Plugins/Reporters/HtmlReporter.php +++ /dev/null @@ -1,39 +0,0 @@ -'.PHP_EOL; - echo 'PASS '.$address.PHP_EOL; - echo ''.PHP_EOL; - flush(); - } else { - echo '
'.PHP_EOL; - echo 'FAIL '.$address.PHP_EOL; - echo '
'.PHP_EOL; - flush(); - } - } -} diff --git a/lib/swiftmailer/swiftmailer/lib/classes/Swift/Plugins/Sleeper.php b/lib/swiftmailer/swiftmailer/lib/classes/Swift/Plugins/Sleeper.php deleted file mode 100644 index 595c0f603..000000000 --- a/lib/swiftmailer/swiftmailer/lib/classes/Swift/Plugins/Sleeper.php +++ /dev/null @@ -1,24 +0,0 @@ -_rate = $rate; - $this->_mode = $mode; - $this->_sleeper = $sleeper; - $this->_timer = $timer; - } - - /** - * Invoked immediately before the Message is sent. - * - * @param Swift_Events_SendEvent $evt - */ - public function beforeSendPerformed(Swift_Events_SendEvent $evt) - { - $time = $this->getTimestamp(); - if (!isset($this->_start)) { - $this->_start = $time; - } - $duration = $time - $this->_start; - - switch ($this->_mode) { - case self::BYTES_PER_MINUTE: - $sleep = $this->_throttleBytesPerMinute($duration); - break; - case self::MESSAGES_PER_SECOND: - $sleep = $this->_throttleMessagesPerSecond($duration); - break; - case self::MESSAGES_PER_MINUTE: - $sleep = $this->_throttleMessagesPerMinute($duration); - break; - default: - $sleep = 0; - break; - } - - if ($sleep > 0) { - $this->sleep($sleep); - } - } - - /** - * Invoked when a Message is sent. - * - * @param Swift_Events_SendEvent $evt - */ - public function sendPerformed(Swift_Events_SendEvent $evt) - { - parent::sendPerformed($evt); - ++$this->_messages; - } - - /** - * Sleep for $seconds. - * - * @param int $seconds - */ - public function sleep($seconds) - { - if (isset($this->_sleeper)) { - $this->_sleeper->sleep($seconds); - } else { - sleep($seconds); - } - } - - /** - * Get the current UNIX timestamp. - * - * @return int - */ - public function getTimestamp() - { - if (isset($this->_timer)) { - return $this->_timer->getTimestamp(); - } - - return time(); - } - - /** - * Get a number of seconds to sleep for. - * - * @param int $timePassed - * - * @return int - */ - private function _throttleBytesPerMinute($timePassed) - { - $expectedDuration = $this->getBytesOut() / ($this->_rate / 60); - - return (int) ceil($expectedDuration - $timePassed); - } - - /** - * Get a number of seconds to sleep for. - * - * @param int $timePassed - * - * @return int - */ - private function _throttleMessagesPerSecond($timePassed) - { - $expectedDuration = $this->_messages / ($this->_rate); - - return (int) ceil($expectedDuration - $timePassed); - } - - /** - * Get a number of seconds to sleep for. - * - * @param int $timePassed - * - * @return int - */ - private function _throttleMessagesPerMinute($timePassed) - { - $expectedDuration = $this->_messages / ($this->_rate / 60); - - return (int) ceil($expectedDuration - $timePassed); - } -} diff --git a/lib/swiftmailer/swiftmailer/lib/classes/Swift/Plugins/Timer.php b/lib/swiftmailer/swiftmailer/lib/classes/Swift/Plugins/Timer.php deleted file mode 100644 index 9c8deb38a..000000000 --- a/lib/swiftmailer/swiftmailer/lib/classes/Swift/Plugins/Timer.php +++ /dev/null @@ -1,24 +0,0 @@ -register('properties.charset')->asValue($charset); - - return $this; - } - - /** - * Set the directory where temporary files can be saved. - * - * @param string $dir - * - * @return $this - */ - public function setTempDir($dir) - { - Swift_DependencyContainer::getInstance()->register('tempdir')->asValue($dir); - - return $this; - } - - /** - * Set the type of cache to use (i.e. "disk" or "array"). - * - * @param string $type - * - * @return $this - */ - public function setCacheType($type) - { - Swift_DependencyContainer::getInstance()->register('cache')->asAliasOf(sprintf('cache.%s', $type)); - - return $this; - } - - /** - * Set the QuotedPrintable dot escaper preference. - * - * @param bool $dotEscape - * - * @return $this - */ - public function setQPDotEscape($dotEscape) - { - $dotEscape = !empty($dotEscape); - Swift_DependencyContainer::getInstance() - ->register('mime.qpcontentencoder') - ->asNewInstanceOf('Swift_Mime_ContentEncoder_QpContentEncoder') - ->withDependencies(array('mime.charstream', 'mime.bytecanonicalizer')) - ->addConstructorValue($dotEscape); - - return $this; - } -} diff --git a/lib/swiftmailer/swiftmailer/lib/classes/Swift/ReplacementFilterFactory.php b/lib/swiftmailer/swiftmailer/lib/classes/Swift/ReplacementFilterFactory.php deleted file mode 100644 index 2897474e7..000000000 --- a/lib/swiftmailer/swiftmailer/lib/classes/Swift/ReplacementFilterFactory.php +++ /dev/null @@ -1,27 +0,0 @@ -createDependenciesFor('transport.sendmail') - ); - - $this->setCommand($command); - } - - /** - * Create a new SendmailTransport instance. - * - * @param string $command - * - * @return self - */ - public static function newInstance($command = '/usr/sbin/sendmail -bs') - { - return new self($command); - } -} diff --git a/lib/swiftmailer/swiftmailer/lib/classes/Swift/SignedMessage.php b/lib/swiftmailer/swiftmailer/lib/classes/Swift/SignedMessage.php deleted file mode 100644 index 2e7a8726d..000000000 --- a/lib/swiftmailer/swiftmailer/lib/classes/Swift/SignedMessage.php +++ /dev/null @@ -1,23 +0,0 @@ - - * - * @deprecated - */ -class Swift_SignedMessage extends Swift_Message -{ -} diff --git a/lib/swiftmailer/swiftmailer/lib/classes/Swift/Signer.php b/lib/swiftmailer/swiftmailer/lib/classes/Swift/Signer.php deleted file mode 100644 index 2d8176d90..000000000 --- a/lib/swiftmailer/swiftmailer/lib/classes/Swift/Signer.php +++ /dev/null @@ -1,20 +0,0 @@ - - */ -interface Swift_Signer -{ - public function reset(); -} diff --git a/lib/swiftmailer/swiftmailer/lib/classes/Swift/Signers/BodySigner.php b/lib/swiftmailer/swiftmailer/lib/classes/Swift/Signers/BodySigner.php deleted file mode 100644 index 8e66e18f4..000000000 --- a/lib/swiftmailer/swiftmailer/lib/classes/Swift/Signers/BodySigner.php +++ /dev/null @@ -1,33 +0,0 @@ - - */ -interface Swift_Signers_BodySigner extends Swift_Signer -{ - /** - * Change the Swift_Signed_Message to apply the singing. - * - * @param Swift_Message $message - * - * @return self - */ - public function signMessage(Swift_Message $message); - - /** - * Return the list of header a signer might tamper. - * - * @return array - */ - public function getAlteredHeaders(); -} diff --git a/lib/swiftmailer/swiftmailer/lib/classes/Swift/Signers/DKIMSigner.php b/lib/swiftmailer/swiftmailer/lib/classes/Swift/Signers/DKIMSigner.php deleted file mode 100644 index 454e84b47..000000000 --- a/lib/swiftmailer/swiftmailer/lib/classes/Swift/Signers/DKIMSigner.php +++ /dev/null @@ -1,712 +0,0 @@ - - */ -class Swift_Signers_DKIMSigner implements Swift_Signers_HeaderSigner -{ - /** - * PrivateKey. - * - * @var string - */ - protected $_privateKey; - - /** - * DomainName. - * - * @var string - */ - protected $_domainName; - - /** - * Selector. - * - * @var string - */ - protected $_selector; - - /** - * Hash algorithm used. - * - * @see RFC6376 3.3: Signers MUST implement and SHOULD sign using rsa-sha256. - * - * @var string - */ - protected $_hashAlgorithm = 'rsa-sha256'; - - /** - * Body canon method. - * - * @var string - */ - protected $_bodyCanon = 'simple'; - - /** - * Header canon method. - * - * @var string - */ - protected $_headerCanon = 'simple'; - - /** - * Headers not being signed. - * - * @var array - */ - protected $_ignoredHeaders = array('return-path' => true); - - /** - * Signer identity. - * - * @var string - */ - protected $_signerIdentity; - - /** - * BodyLength. - * - * @var int - */ - protected $_bodyLen = 0; - - /** - * Maximum signedLen. - * - * @var int - */ - protected $_maxLen = PHP_INT_MAX; - - /** - * Embbed bodyLen in signature. - * - * @var bool - */ - protected $_showLen = false; - - /** - * When the signature has been applied (true means time()), false means not embedded. - * - * @var mixed - */ - protected $_signatureTimestamp = true; - - /** - * When will the signature expires false means not embedded, if sigTimestamp is auto - * Expiration is relative, otherwise it's absolute. - * - * @var int - */ - protected $_signatureExpiration = false; - - /** - * Must we embed signed headers? - * - * @var bool - */ - protected $_debugHeaders = false; - - // work variables - /** - * Headers used to generate hash. - * - * @var array - */ - protected $_signedHeaders = array(); - - /** - * If debugHeaders is set store debugData here. - * - * @var string - */ - private $_debugHeadersData = ''; - - /** - * Stores the bodyHash. - * - * @var string - */ - private $_bodyHash = ''; - - /** - * Stores the signature header. - * - * @var Swift_Mime_Headers_ParameterizedHeader - */ - protected $_dkimHeader; - - private $_bodyHashHandler; - - private $_headerHash; - - private $_headerCanonData = ''; - - private $_bodyCanonEmptyCounter = 0; - - private $_bodyCanonIgnoreStart = 2; - - private $_bodyCanonSpace = false; - - private $_bodyCanonLastChar = null; - - private $_bodyCanonLine = ''; - - private $_bound = array(); - - /** - * Constructor. - * - * @param string $privateKey - * @param string $domainName - * @param string $selector - */ - public function __construct($privateKey, $domainName, $selector) - { - $this->_privateKey = $privateKey; - $this->_domainName = $domainName; - $this->_signerIdentity = '@'.$domainName; - $this->_selector = $selector; - - // keep fallback hash algorithm sha1 if php version is lower than 5.4.8 - if (PHP_VERSION_ID < 50408) { - $this->_hashAlgorithm = 'rsa-sha1'; - } - } - - /** - * Instanciate DKIMSigner. - * - * @param string $privateKey - * @param string $domainName - * @param string $selector - * - * @return self - */ - public static function newInstance($privateKey, $domainName, $selector) - { - return new static($privateKey, $domainName, $selector); - } - - /** - * Reset the Signer. - * - * @see Swift_Signer::reset() - */ - public function reset() - { - $this->_headerHash = null; - $this->_signedHeaders = array(); - $this->_bodyHash = null; - $this->_bodyHashHandler = null; - $this->_bodyCanonIgnoreStart = 2; - $this->_bodyCanonEmptyCounter = 0; - $this->_bodyCanonLastChar = null; - $this->_bodyCanonSpace = false; - } - - /** - * Writes $bytes to the end of the stream. - * - * Writing may not happen immediately if the stream chooses to buffer. If - * you want to write these bytes with immediate effect, call {@link commit()} - * after calling write(). - * - * This method returns the sequence ID of the write (i.e. 1 for first, 2 for - * second, etc etc). - * - * @param string $bytes - * - * @throws Swift_IoException - * - * @return int - */ - // TODO fix return - public function write($bytes) - { - $this->_canonicalizeBody($bytes); - foreach ($this->_bound as $is) { - $is->write($bytes); - } - } - - /** - * For any bytes that are currently buffered inside the stream, force them - * off the buffer. - */ - public function commit() - { - // Nothing to do - return; - } - - /** - * Attach $is to this stream. - * The stream acts as an observer, receiving all data that is written. - * All {@link write()} and {@link flushBuffers()} operations will be mirrored. - * - * @param Swift_InputByteStream $is - */ - public function bind(Swift_InputByteStream $is) - { - // Don't have to mirror anything - $this->_bound[] = $is; - - return; - } - - /** - * Remove an already bound stream. - * If $is is not bound, no errors will be raised. - * If the stream currently has any buffered data it will be written to $is - * before unbinding occurs. - * - * @param Swift_InputByteStream $is - */ - public function unbind(Swift_InputByteStream $is) - { - // Don't have to mirror anything - foreach ($this->_bound as $k => $stream) { - if ($stream === $is) { - unset($this->_bound[$k]); - - return; - } - } - } - - /** - * Flush the contents of the stream (empty it) and set the internal pointer - * to the beginning. - * - * @throws Swift_IoException - */ - public function flushBuffers() - { - $this->reset(); - } - - /** - * Set hash_algorithm, must be one of rsa-sha256 | rsa-sha1. - * - * @param string $hash 'rsa-sha1' or 'rsa-sha256' - * - * @throws Swift_SwiftException - * - * @return $this - */ - public function setHashAlgorithm($hash) - { - switch ($hash) { - case 'rsa-sha1': - $this->_hashAlgorithm = 'rsa-sha1'; - break; - case 'rsa-sha256': - $this->_hashAlgorithm = 'rsa-sha256'; - if (!defined('OPENSSL_ALGO_SHA256')) { - throw new Swift_SwiftException('Unable to set sha256 as it is not supported by OpenSSL.'); - } - break; - default: - throw new Swift_SwiftException('Unable to set the hash algorithm, must be one of rsa-sha1 or rsa-sha256 (%s given).', $hash); - } - - return $this; - } - - /** - * Set the body canonicalization algorithm. - * - * @param string $canon - * - * @return $this - */ - public function setBodyCanon($canon) - { - if ($canon == 'relaxed') { - $this->_bodyCanon = 'relaxed'; - } else { - $this->_bodyCanon = 'simple'; - } - - return $this; - } - - /** - * Set the header canonicalization algorithm. - * - * @param string $canon - * - * @return $this - */ - public function setHeaderCanon($canon) - { - if ($canon == 'relaxed') { - $this->_headerCanon = 'relaxed'; - } else { - $this->_headerCanon = 'simple'; - } - - return $this; - } - - /** - * Set the signer identity. - * - * @param string $identity - * - * @return $this - */ - public function setSignerIdentity($identity) - { - $this->_signerIdentity = $identity; - - return $this; - } - - /** - * Set the length of the body to sign. - * - * @param mixed $len (bool or int) - * - * @return $this - */ - public function setBodySignedLen($len) - { - if ($len === true) { - $this->_showLen = true; - $this->_maxLen = PHP_INT_MAX; - } elseif ($len === false) { - $this->_showLen = false; - $this->_maxLen = PHP_INT_MAX; - } else { - $this->_showLen = true; - $this->_maxLen = (int) $len; - } - - return $this; - } - - /** - * Set the signature timestamp. - * - * @param int $time A timestamp - * - * @return $this - */ - public function setSignatureTimestamp($time) - { - $this->_signatureTimestamp = $time; - - return $this; - } - - /** - * Set the signature expiration timestamp. - * - * @param int $time A timestamp - * - * @return $this - */ - public function setSignatureExpiration($time) - { - $this->_signatureExpiration = $time; - - return $this; - } - - /** - * Enable / disable the DebugHeaders. - * - * @param bool $debug - * - * @return Swift_Signers_DKIMSigner - */ - public function setDebugHeaders($debug) - { - $this->_debugHeaders = (bool) $debug; - - return $this; - } - - /** - * Start Body. - */ - public function startBody() - { - // Init - switch ($this->_hashAlgorithm) { - case 'rsa-sha256': - $this->_bodyHashHandler = hash_init('sha256'); - break; - case 'rsa-sha1': - $this->_bodyHashHandler = hash_init('sha1'); - break; - } - $this->_bodyCanonLine = ''; - } - - /** - * End Body. - */ - public function endBody() - { - $this->_endOfBody(); - } - - /** - * Returns the list of Headers Tampered by this plugin. - * - * @return array - */ - public function getAlteredHeaders() - { - if ($this->_debugHeaders) { - return array('DKIM-Signature', 'X-DebugHash'); - } else { - return array('DKIM-Signature'); - } - } - - /** - * Adds an ignored Header. - * - * @param string $header_name - * - * @return Swift_Signers_DKIMSigner - */ - public function ignoreHeader($header_name) - { - $this->_ignoredHeaders[strtolower($header_name)] = true; - - return $this; - } - - /** - * Set the headers to sign. - * - * @param Swift_Mime_HeaderSet $headers - * - * @return Swift_Signers_DKIMSigner - */ - public function setHeaders(Swift_Mime_HeaderSet $headers) - { - $this->_headerCanonData = ''; - // Loop through Headers - $listHeaders = $headers->listAll(); - foreach ($listHeaders as $hName) { - // Check if we need to ignore Header - if (!isset($this->_ignoredHeaders[strtolower($hName)])) { - if ($headers->has($hName)) { - $tmp = $headers->getAll($hName); - foreach ($tmp as $header) { - if ($header->getFieldBody() != '') { - $this->_addHeader($header->toString()); - $this->_signedHeaders[] = $header->getFieldName(); - } - } - } - } - } - - return $this; - } - - /** - * Add the signature to the given Headers. - * - * @param Swift_Mime_HeaderSet $headers - * - * @return Swift_Signers_DKIMSigner - */ - public function addSignature(Swift_Mime_HeaderSet $headers) - { - // Prepare the DKIM-Signature - $params = array('v' => '1', 'a' => $this->_hashAlgorithm, 'bh' => base64_encode($this->_bodyHash), 'd' => $this->_domainName, 'h' => implode(': ', $this->_signedHeaders), 'i' => $this->_signerIdentity, 's' => $this->_selector); - if ($this->_bodyCanon != 'simple') { - $params['c'] = $this->_headerCanon.'/'.$this->_bodyCanon; - } elseif ($this->_headerCanon != 'simple') { - $params['c'] = $this->_headerCanon; - } - if ($this->_showLen) { - $params['l'] = $this->_bodyLen; - } - if ($this->_signatureTimestamp === true) { - $params['t'] = time(); - if ($this->_signatureExpiration !== false) { - $params['x'] = $params['t'] + $this->_signatureExpiration; - } - } else { - if ($this->_signatureTimestamp !== false) { - $params['t'] = $this->_signatureTimestamp; - } - if ($this->_signatureExpiration !== false) { - $params['x'] = $this->_signatureExpiration; - } - } - if ($this->_debugHeaders) { - $params['z'] = implode('|', $this->_debugHeadersData); - } - $string = ''; - foreach ($params as $k => $v) { - $string .= $k.'='.$v.'; '; - } - $string = trim($string); - $headers->addTextHeader('DKIM-Signature', $string); - // Add the last DKIM-Signature - $tmp = $headers->getAll('DKIM-Signature'); - $this->_dkimHeader = end($tmp); - $this->_addHeader(trim($this->_dkimHeader->toString())."\r\n b=", true); - $this->_endOfHeaders(); - if ($this->_debugHeaders) { - $headers->addTextHeader('X-DebugHash', base64_encode($this->_headerHash)); - } - $this->_dkimHeader->setValue($string.' b='.trim(chunk_split(base64_encode($this->_getEncryptedHash()), 73, ' '))); - - return $this; - } - - /* Private helpers */ - - protected function _addHeader($header, $is_sig = false) - { - switch ($this->_headerCanon) { - case 'relaxed': - // Prepare Header and cascade - $exploded = explode(':', $header, 2); - $name = strtolower(trim($exploded[0])); - $value = str_replace("\r\n", '', $exploded[1]); - $value = preg_replace("/[ \t][ \t]+/", ' ', $value); - $header = $name.':'.trim($value).($is_sig ? '' : "\r\n"); - case 'simple': - // Nothing to do - } - $this->_addToHeaderHash($header); - } - - /** - * @deprecated This method is currently useless in this class but it must be - * kept for BC reasons due to its "protected" scope. This method - * might be overridden by custom client code. - */ - protected function _endOfHeaders() - { - } - - protected function _canonicalizeBody($string) - { - $len = strlen($string); - $canon = ''; - $method = ($this->_bodyCanon == 'relaxed'); - for ($i = 0; $i < $len; ++$i) { - if ($this->_bodyCanonIgnoreStart > 0) { - --$this->_bodyCanonIgnoreStart; - continue; - } - switch ($string[$i]) { - case "\r": - $this->_bodyCanonLastChar = "\r"; - break; - case "\n": - if ($this->_bodyCanonLastChar == "\r") { - if ($method) { - $this->_bodyCanonSpace = false; - } - if ($this->_bodyCanonLine == '') { - ++$this->_bodyCanonEmptyCounter; - } else { - $this->_bodyCanonLine = ''; - $canon .= "\r\n"; - } - } else { - // Wooops Error - // todo handle it but should never happen - } - break; - case ' ': - case "\t": - if ($method) { - $this->_bodyCanonSpace = true; - break; - } - default: - if ($this->_bodyCanonEmptyCounter > 0) { - $canon .= str_repeat("\r\n", $this->_bodyCanonEmptyCounter); - $this->_bodyCanonEmptyCounter = 0; - } - if ($this->_bodyCanonSpace) { - $this->_bodyCanonLine .= ' '; - $canon .= ' '; - $this->_bodyCanonSpace = false; - } - $this->_bodyCanonLine .= $string[$i]; - $canon .= $string[$i]; - } - } - $this->_addToBodyHash($canon); - } - - protected function _endOfBody() - { - // Add trailing Line return if last line is non empty - if (strlen($this->_bodyCanonLine) > 0) { - $this->_addToBodyHash("\r\n"); - } - $this->_bodyHash = hash_final($this->_bodyHashHandler, true); - } - - private function _addToBodyHash($string) - { - $len = strlen($string); - if ($len > ($new_len = ($this->_maxLen - $this->_bodyLen))) { - $string = substr($string, 0, $new_len); - $len = $new_len; - } - hash_update($this->_bodyHashHandler, $string); - $this->_bodyLen += $len; - } - - private function _addToHeaderHash($header) - { - if ($this->_debugHeaders) { - $this->_debugHeadersData[] = trim($header); - } - $this->_headerCanonData .= $header; - } - - /** - * @throws Swift_SwiftException - * - * @return string - */ - private function _getEncryptedHash() - { - $signature = ''; - - switch ($this->_hashAlgorithm) { - case 'rsa-sha1': - $algorithm = OPENSSL_ALGO_SHA1; - break; - case 'rsa-sha256': - $algorithm = OPENSSL_ALGO_SHA256; - break; - } - $pkeyId = openssl_get_privatekey($this->_privateKey); - if (!$pkeyId) { - throw new Swift_SwiftException('Unable to load DKIM Private Key ['.openssl_error_string().']'); - } - if (openssl_sign($this->_headerCanonData, $signature, $pkeyId, $algorithm)) { - return $signature; - } - throw new Swift_SwiftException('Unable to sign DKIM Hash ['.openssl_error_string().']'); - } -} diff --git a/lib/swiftmailer/swiftmailer/lib/classes/Swift/Signers/DomainKeySigner.php b/lib/swiftmailer/swiftmailer/lib/classes/Swift/Signers/DomainKeySigner.php deleted file mode 100644 index 0365363c8..000000000 --- a/lib/swiftmailer/swiftmailer/lib/classes/Swift/Signers/DomainKeySigner.php +++ /dev/null @@ -1,524 +0,0 @@ - - */ -class Swift_Signers_DomainKeySigner implements Swift_Signers_HeaderSigner -{ - /** - * PrivateKey. - * - * @var string - */ - protected $_privateKey; - - /** - * DomainName. - * - * @var string - */ - protected $_domainName; - - /** - * Selector. - * - * @var string - */ - protected $_selector; - - /** - * Hash algorithm used. - * - * @var string - */ - protected $_hashAlgorithm = 'rsa-sha1'; - - /** - * Canonisation method. - * - * @var string - */ - protected $_canon = 'simple'; - - /** - * Headers not being signed. - * - * @var array - */ - protected $_ignoredHeaders = array(); - - /** - * Signer identity. - * - * @var string - */ - protected $_signerIdentity; - - /** - * Must we embed signed headers? - * - * @var bool - */ - protected $_debugHeaders = false; - - // work variables - /** - * Headers used to generate hash. - * - * @var array - */ - private $_signedHeaders = array(); - - /** - * Stores the signature header. - * - * @var Swift_Mime_Headers_ParameterizedHeader - */ - protected $_domainKeyHeader; - - /** - * Hash Handler. - * - * @var resource|null - */ - private $_hashHandler; - - private $_hash; - - private $_canonData = ''; - - private $_bodyCanonEmptyCounter = 0; - - private $_bodyCanonIgnoreStart = 2; - - private $_bodyCanonSpace = false; - - private $_bodyCanonLastChar = null; - - private $_bodyCanonLine = ''; - - private $_bound = array(); - - /** - * Constructor. - * - * @param string $privateKey - * @param string $domainName - * @param string $selector - */ - public function __construct($privateKey, $domainName, $selector) - { - $this->_privateKey = $privateKey; - $this->_domainName = $domainName; - $this->_signerIdentity = '@'.$domainName; - $this->_selector = $selector; - } - - /** - * Instanciate DomainKeySigner. - * - * @param string $privateKey - * @param string $domainName - * @param string $selector - * - * @return self - */ - public static function newInstance($privateKey, $domainName, $selector) - { - return new static($privateKey, $domainName, $selector); - } - - /** - * Resets internal states. - * - * @return $this - */ - public function reset() - { - $this->_hash = null; - $this->_hashHandler = null; - $this->_bodyCanonIgnoreStart = 2; - $this->_bodyCanonEmptyCounter = 0; - $this->_bodyCanonLastChar = null; - $this->_bodyCanonSpace = false; - - return $this; - } - - /** - * Writes $bytes to the end of the stream. - * - * Writing may not happen immediately if the stream chooses to buffer. If - * you want to write these bytes with immediate effect, call {@link commit()} - * after calling write(). - * - * This method returns the sequence ID of the write (i.e. 1 for first, 2 for - * second, etc etc). - * - * @param string $bytes - * - * @throws Swift_IoException - * - * @return $this - */ - public function write($bytes) - { - $this->_canonicalizeBody($bytes); - foreach ($this->_bound as $is) { - $is->write($bytes); - } - - return $this; - } - - /** - * For any bytes that are currently buffered inside the stream, force them - * off the buffer. - * - * @throws Swift_IoException - * - * @return $this - */ - public function commit() - { - // Nothing to do - return $this; - } - - /** - * Attach $is to this stream. - * The stream acts as an observer, receiving all data that is written. - * All {@link write()} and {@link flushBuffers()} operations will be mirrored. - * - * @param Swift_InputByteStream $is - * - * @return $this - */ - public function bind(Swift_InputByteStream $is) - { - // Don't have to mirror anything - $this->_bound[] = $is; - - return $this; - } - - /** - * Remove an already bound stream. - * If $is is not bound, no errors will be raised. - * If the stream currently has any buffered data it will be written to $is - * before unbinding occurs. - * - * @param Swift_InputByteStream $is - * - * @return $this - */ - public function unbind(Swift_InputByteStream $is) - { - // Don't have to mirror anything - foreach ($this->_bound as $k => $stream) { - if ($stream === $is) { - unset($this->_bound[$k]); - - break; - } - } - - return $this; - } - - /** - * Flush the contents of the stream (empty it) and set the internal pointer - * to the beginning. - * - * @throws Swift_IoException - * - * @return $this - */ - public function flushBuffers() - { - $this->reset(); - - return $this; - } - - /** - * Set hash_algorithm, must be one of rsa-sha256 | rsa-sha1 defaults to rsa-sha256. - * - * @param string $hash - * - * @return $this - */ - public function setHashAlgorithm($hash) - { - $this->_hashAlgorithm = 'rsa-sha1'; - - return $this; - } - - /** - * Set the canonicalization algorithm. - * - * @param string $canon simple | nofws defaults to simple - * - * @return $this - */ - public function setCanon($canon) - { - if ($canon == 'nofws') { - $this->_canon = 'nofws'; - } else { - $this->_canon = 'simple'; - } - - return $this; - } - - /** - * Set the signer identity. - * - * @param string $identity - * - * @return $this - */ - public function setSignerIdentity($identity) - { - $this->_signerIdentity = $identity; - - return $this; - } - - /** - * Enable / disable the DebugHeaders. - * - * @param bool $debug - * - * @return $this - */ - public function setDebugHeaders($debug) - { - $this->_debugHeaders = (bool) $debug; - - return $this; - } - - /** - * Start Body. - */ - public function startBody() - { - } - - /** - * End Body. - */ - public function endBody() - { - $this->_endOfBody(); - } - - /** - * Returns the list of Headers Tampered by this plugin. - * - * @return array - */ - public function getAlteredHeaders() - { - if ($this->_debugHeaders) { - return array('DomainKey-Signature', 'X-DebugHash'); - } - - return array('DomainKey-Signature'); - } - - /** - * Adds an ignored Header. - * - * @param string $header_name - * - * @return $this - */ - public function ignoreHeader($header_name) - { - $this->_ignoredHeaders[strtolower($header_name)] = true; - - return $this; - } - - /** - * Set the headers to sign. - * - * @param Swift_Mime_HeaderSet $headers - * - * @return $this - */ - public function setHeaders(Swift_Mime_HeaderSet $headers) - { - $this->_startHash(); - $this->_canonData = ''; - // Loop through Headers - $listHeaders = $headers->listAll(); - foreach ($listHeaders as $hName) { - // Check if we need to ignore Header - if (!isset($this->_ignoredHeaders[strtolower($hName)])) { - if ($headers->has($hName)) { - $tmp = $headers->getAll($hName); - foreach ($tmp as $header) { - if ($header->getFieldBody() != '') { - $this->_addHeader($header->toString()); - $this->_signedHeaders[] = $header->getFieldName(); - } - } - } - } - } - $this->_endOfHeaders(); - - return $this; - } - - /** - * Add the signature to the given Headers. - * - * @param Swift_Mime_HeaderSet $headers - * - * @return $this - */ - public function addSignature(Swift_Mime_HeaderSet $headers) - { - // Prepare the DomainKey-Signature Header - $params = array('a' => $this->_hashAlgorithm, 'b' => chunk_split(base64_encode($this->_getEncryptedHash()), 73, ' '), 'c' => $this->_canon, 'd' => $this->_domainName, 'h' => implode(': ', $this->_signedHeaders), 'q' => 'dns', 's' => $this->_selector); - $string = ''; - foreach ($params as $k => $v) { - $string .= $k.'='.$v.'; '; - } - $string = trim($string); - $headers->addTextHeader('DomainKey-Signature', $string); - - return $this; - } - - /* Private helpers */ - - protected function _addHeader($header) - { - switch ($this->_canon) { - case 'nofws': - // Prepare Header and cascade - $exploded = explode(':', $header, 2); - $name = strtolower(trim($exploded[0])); - $value = str_replace("\r\n", '', $exploded[1]); - $value = preg_replace("/[ \t][ \t]+/", ' ', $value); - $header = $name.':'.trim($value)."\r\n"; - case 'simple': - // Nothing to do - } - $this->_addToHash($header); - } - - protected function _endOfHeaders() - { - $this->_bodyCanonEmptyCounter = 1; - } - - protected function _canonicalizeBody($string) - { - $len = strlen($string); - $canon = ''; - $nofws = ($this->_canon == 'nofws'); - for ($i = 0; $i < $len; ++$i) { - if ($this->_bodyCanonIgnoreStart > 0) { - --$this->_bodyCanonIgnoreStart; - continue; - } - switch ($string[$i]) { - case "\r": - $this->_bodyCanonLastChar = "\r"; - break; - case "\n": - if ($this->_bodyCanonLastChar == "\r") { - if ($nofws) { - $this->_bodyCanonSpace = false; - } - if ($this->_bodyCanonLine == '') { - ++$this->_bodyCanonEmptyCounter; - } else { - $this->_bodyCanonLine = ''; - $canon .= "\r\n"; - } - } else { - // Wooops Error - throw new Swift_SwiftException('Invalid new line sequence in mail found \n without preceding \r'); - } - break; - case ' ': - case "\t": - case "\x09": //HTAB - if ($nofws) { - $this->_bodyCanonSpace = true; - break; - } - default: - if ($this->_bodyCanonEmptyCounter > 0) { - $canon .= str_repeat("\r\n", $this->_bodyCanonEmptyCounter); - $this->_bodyCanonEmptyCounter = 0; - } - $this->_bodyCanonLine .= $string[$i]; - $canon .= $string[$i]; - } - } - $this->_addToHash($canon); - } - - protected function _endOfBody() - { - if (strlen($this->_bodyCanonLine) > 0) { - $this->_addToHash("\r\n"); - } - $this->_hash = hash_final($this->_hashHandler, true); - } - - private function _addToHash($string) - { - $this->_canonData .= $string; - hash_update($this->_hashHandler, $string); - } - - private function _startHash() - { - // Init - switch ($this->_hashAlgorithm) { - case 'rsa-sha1': - $this->_hashHandler = hash_init('sha1'); - break; - } - $this->_bodyCanonLine = ''; - } - - /** - * @throws Swift_SwiftException - * - * @return string - */ - private function _getEncryptedHash() - { - $signature = ''; - $pkeyId = openssl_get_privatekey($this->_privateKey); - if (!$pkeyId) { - throw new Swift_SwiftException('Unable to load DomainKey Private Key ['.openssl_error_string().']'); - } - if (openssl_sign($this->_canonData, $signature, $pkeyId, OPENSSL_ALGO_SHA1)) { - return $signature; - } - throw new Swift_SwiftException('Unable to sign DomainKey Hash ['.openssl_error_string().']'); - } -} diff --git a/lib/swiftmailer/swiftmailer/lib/classes/Swift/Signers/HeaderSigner.php b/lib/swiftmailer/swiftmailer/lib/classes/Swift/Signers/HeaderSigner.php deleted file mode 100644 index ef8832fdf..000000000 --- a/lib/swiftmailer/swiftmailer/lib/classes/Swift/Signers/HeaderSigner.php +++ /dev/null @@ -1,65 +0,0 @@ - - */ -interface Swift_Signers_HeaderSigner extends Swift_Signer, Swift_InputByteStream -{ - /** - * Exclude an header from the signed headers. - * - * @param string $header_name - * - * @return self - */ - public function ignoreHeader($header_name); - - /** - * Prepare the Signer to get a new Body. - * - * @return self - */ - public function startBody(); - - /** - * Give the signal that the body has finished streaming. - * - * @return self - */ - public function endBody(); - - /** - * Give the headers already given. - * - * @param Swift_Mime_SimpleHeaderSet $headers - * - * @return self - */ - public function setHeaders(Swift_Mime_HeaderSet $headers); - - /** - * Add the header(s) to the headerSet. - * - * @param Swift_Mime_HeaderSet $headers - * - * @return self - */ - public function addSignature(Swift_Mime_HeaderSet $headers); - - /** - * Return the list of header a signer might tamper. - * - * @return array - */ - public function getAlteredHeaders(); -} diff --git a/lib/swiftmailer/swiftmailer/lib/classes/Swift/Signers/OpenDKIMSigner.php b/lib/swiftmailer/swiftmailer/lib/classes/Swift/Signers/OpenDKIMSigner.php deleted file mode 100644 index 8fdbaa43b..000000000 --- a/lib/swiftmailer/swiftmailer/lib/classes/Swift/Signers/OpenDKIMSigner.php +++ /dev/null @@ -1,190 +0,0 @@ - - */ -class Swift_Signers_OpenDKIMSigner extends Swift_Signers_DKIMSigner -{ - private $_peclLoaded = false; - - private $_dkimHandler = null; - - private $dropFirstLF = true; - - const CANON_RELAXED = 1; - const CANON_SIMPLE = 2; - const SIG_RSA_SHA1 = 3; - const SIG_RSA_SHA256 = 4; - - public function __construct($privateKey, $domainName, $selector) - { - if (!extension_loaded('opendkim')) { - throw new Swift_SwiftException('php-opendkim extension not found'); - } - - $this->_peclLoaded = true; - - parent::__construct($privateKey, $domainName, $selector); - } - - public static function newInstance($privateKey, $domainName, $selector) - { - return new static($privateKey, $domainName, $selector); - } - - public function addSignature(Swift_Mime_HeaderSet $headers) - { - $header = new Swift_Mime_Headers_OpenDKIMHeader('DKIM-Signature'); - $headerVal = $this->_dkimHandler->getSignatureHeader(); - if (!$headerVal) { - throw new Swift_SwiftException('OpenDKIM Error: '.$this->_dkimHandler->getError()); - } - $header->setValue($headerVal); - $headers->set($header); - - return $this; - } - - public function setHeaders(Swift_Mime_HeaderSet $headers) - { - $bodyLen = $this->_bodyLen; - if (is_bool($bodyLen)) { - $bodyLen = -1; - } - $hash = $this->_hashAlgorithm == 'rsa-sha1' ? OpenDKIMSign::ALG_RSASHA1 : OpenDKIMSign::ALG_RSASHA256; - $bodyCanon = $this->_bodyCanon == 'simple' ? OpenDKIMSign::CANON_SIMPLE : OpenDKIMSign::CANON_RELAXED; - $headerCanon = $this->_headerCanon == 'simple' ? OpenDKIMSign::CANON_SIMPLE : OpenDKIMSign::CANON_RELAXED; - $this->_dkimHandler = new OpenDKIMSign($this->_privateKey, $this->_selector, $this->_domainName, $headerCanon, $bodyCanon, $hash, $bodyLen); - // Hardcode signature Margin for now - $this->_dkimHandler->setMargin(78); - - if (!is_numeric($this->_signatureTimestamp)) { - OpenDKIM::setOption(OpenDKIM::OPTS_FIXEDTIME, time()); - } else { - if (!OpenDKIM::setOption(OpenDKIM::OPTS_FIXEDTIME, $this->_signatureTimestamp)) { - throw new Swift_SwiftException('Unable to force signature timestamp ['.openssl_error_string().']'); - } - } - if (isset($this->_signerIdentity)) { - $this->_dkimHandler->setSigner($this->_signerIdentity); - } - $listHeaders = $headers->listAll(); - foreach ($listHeaders as $hName) { - // Check if we need to ignore Header - if (!isset($this->_ignoredHeaders[strtolower($hName)])) { - $tmp = $headers->getAll($hName); - if ($headers->has($hName)) { - foreach ($tmp as $header) { - if ($header->getFieldBody() != '') { - $htosign = $header->toString(); - $this->_dkimHandler->header($htosign); - $this->_signedHeaders[] = $header->getFieldName(); - } - } - } - } - } - - return $this; - } - - public function startBody() - { - if (!$this->_peclLoaded) { - return parent::startBody(); - } - $this->dropFirstLF = true; - $this->_dkimHandler->eoh(); - - return $this; - } - - public function endBody() - { - if (!$this->_peclLoaded) { - return parent::endBody(); - } - $this->_dkimHandler->eom(); - - return $this; - } - - public function reset() - { - $this->_dkimHandler = null; - parent::reset(); - - return $this; - } - - /** - * Set the signature timestamp. - * - * @param int $time - * - * @return $this - */ - public function setSignatureTimestamp($time) - { - $this->_signatureTimestamp = $time; - - return $this; - } - - /** - * Set the signature expiration timestamp. - * - * @param int $time - * - * @return $this - */ - public function setSignatureExpiration($time) - { - $this->_signatureExpiration = $time; - - return $this; - } - - /** - * Enable / disable the DebugHeaders. - * - * @param bool $debug - * - * @return $this - */ - public function setDebugHeaders($debug) - { - $this->_debugHeaders = (bool) $debug; - - return $this; - } - - // Protected - - protected function _canonicalizeBody($string) - { - if (!$this->_peclLoaded) { - return parent::_canonicalizeBody($string); - } - if (false && $this->dropFirstLF === true) { - if ($string[0] == "\r" && $string[1] == "\n") { - $string = substr($string, 2); - } - } - $this->dropFirstLF = false; - if (strlen($string)) { - $this->_dkimHandler->body($string); - } - } -} diff --git a/lib/swiftmailer/swiftmailer/lib/classes/Swift/Signers/SMimeSigner.php b/lib/swiftmailer/swiftmailer/lib/classes/Swift/Signers/SMimeSigner.php deleted file mode 100644 index d13c02e4c..000000000 --- a/lib/swiftmailer/swiftmailer/lib/classes/Swift/Signers/SMimeSigner.php +++ /dev/null @@ -1,436 +0,0 @@ - - */ -class Swift_Signers_SMimeSigner implements Swift_Signers_BodySigner -{ - protected $signCertificate; - protected $signPrivateKey; - protected $encryptCert; - protected $signThenEncrypt = true; - protected $signLevel; - protected $encryptLevel; - protected $signOptions; - protected $encryptOptions; - protected $encryptCipher; - protected $extraCerts = null; - - /** - * @var Swift_StreamFilters_StringReplacementFilterFactory - */ - protected $replacementFactory; - - /** - * @var Swift_Mime_HeaderFactory - */ - protected $headerFactory; - - /** - * Constructor. - * - * @param string|null $signCertificate - * @param string|null $signPrivateKey - * @param string|null $encryptCertificate - */ - public function __construct($signCertificate = null, $signPrivateKey = null, $encryptCertificate = null) - { - if (null !== $signPrivateKey) { - $this->setSignCertificate($signCertificate, $signPrivateKey); - } - - if (null !== $encryptCertificate) { - $this->setEncryptCertificate($encryptCertificate); - } - - $this->replacementFactory = Swift_DependencyContainer::getInstance() - ->lookup('transport.replacementfactory'); - - $this->signOptions = PKCS7_DETACHED; - - // Supported since php5.4 - if (defined('OPENSSL_CIPHER_AES_128_CBC')) { - $this->encryptCipher = OPENSSL_CIPHER_AES_128_CBC; - } else { - $this->encryptCipher = OPENSSL_CIPHER_RC2_128; - } - } - - /** - * Returns an new Swift_Signers_SMimeSigner instance. - * - * @param string $certificate - * @param string $privateKey - * - * @return self - */ - public static function newInstance($certificate = null, $privateKey = null) - { - return new self($certificate, $privateKey); - } - - /** - * Set the certificate location to use for signing. - * - * @see http://www.php.net/manual/en/openssl.pkcs7.flags.php - * - * @param string $certificate - * @param string|array $privateKey If the key needs an passphrase use array('file-location', 'passphrase') instead - * @param int $signOptions Bitwise operator options for openssl_pkcs7_sign() - * @param string $extraCerts A file containing intermediate certificates needed by the signing certificate - * - * @return $this - */ - public function setSignCertificate($certificate, $privateKey = null, $signOptions = PKCS7_DETACHED, $extraCerts = null) - { - $this->signCertificate = 'file://'.str_replace('\\', '/', realpath($certificate)); - - if (null !== $privateKey) { - if (is_array($privateKey)) { - $this->signPrivateKey = $privateKey; - $this->signPrivateKey[0] = 'file://'.str_replace('\\', '/', realpath($privateKey[0])); - } else { - $this->signPrivateKey = 'file://'.str_replace('\\', '/', realpath($privateKey)); - } - } - - $this->signOptions = $signOptions; - if (null !== $extraCerts) { - $this->extraCerts = str_replace('\\', '/', realpath($extraCerts)); - } - - return $this; - } - - /** - * Set the certificate location to use for encryption. - * - * @see http://www.php.net/manual/en/openssl.pkcs7.flags.php - * @see http://nl3.php.net/manual/en/openssl.ciphers.php - * - * @param string|array $recipientCerts Either an single X.509 certificate, or an assoc array of X.509 certificates. - * @param int $cipher - * - * @return $this - */ - public function setEncryptCertificate($recipientCerts, $cipher = null) - { - if (is_array($recipientCerts)) { - $this->encryptCert = array(); - - foreach ($recipientCerts as $cert) { - $this->encryptCert[] = 'file://'.str_replace('\\', '/', realpath($cert)); - } - } else { - $this->encryptCert = 'file://'.str_replace('\\', '/', realpath($recipientCerts)); - } - - if (null !== $cipher) { - $this->encryptCipher = $cipher; - } - - return $this; - } - - /** - * @return string - */ - public function getSignCertificate() - { - return $this->signCertificate; - } - - /** - * @return string - */ - public function getSignPrivateKey() - { - return $this->signPrivateKey; - } - - /** - * Set perform signing before encryption. - * - * The default is to first sign the message and then encrypt. - * But some older mail clients, namely Microsoft Outlook 2000 will work when the message first encrypted. - * As this goes against the official specs, its recommended to only use 'encryption -> signing' when specifically targeting these 'broken' clients. - * - * @param bool $signThenEncrypt - * - * @return $this - */ - public function setSignThenEncrypt($signThenEncrypt = true) - { - $this->signThenEncrypt = $signThenEncrypt; - - return $this; - } - - /** - * @return bool - */ - public function isSignThenEncrypt() - { - return $this->signThenEncrypt; - } - - /** - * Resets internal states. - * - * @return $this - */ - public function reset() - { - return $this; - } - - /** - * Change the Swift_Message to apply the signing. - * - * @param Swift_Message $message - * - * @return $this - */ - public function signMessage(Swift_Message $message) - { - if (null === $this->signCertificate && null === $this->encryptCert) { - return $this; - } - - // Store the message using ByteStream to a file{1} - // Remove all Children - // Sign file{1}, parse the new MIME headers and set them on the primary MimeEntity - // Set the singed-body as the new body (without boundary) - - $messageStream = new Swift_ByteStream_TemporaryFileByteStream(); - $this->toSMimeByteStream($messageStream, $message); - $message->setEncoder(Swift_DependencyContainer::getInstance()->lookup('mime.rawcontentencoder')); - - $message->setChildren(array()); - $this->streamToMime($messageStream, $message); - } - - /** - * Return the list of header a signer might tamper. - * - * @return array - */ - public function getAlteredHeaders() - { - return array('Content-Type', 'Content-Transfer-Encoding', 'Content-Disposition'); - } - - /** - * @param Swift_InputByteStream $inputStream - * @param Swift_Message $mimeEntity - */ - protected function toSMimeByteStream(Swift_InputByteStream $inputStream, Swift_Message $message) - { - $mimeEntity = $this->createMessage($message); - $messageStream = new Swift_ByteStream_TemporaryFileByteStream(); - - $mimeEntity->toByteStream($messageStream); - $messageStream->commit(); - - if (null !== $this->signCertificate && null !== $this->encryptCert) { - $temporaryStream = new Swift_ByteStream_TemporaryFileByteStream(); - - if ($this->signThenEncrypt) { - $this->messageStreamToSignedByteStream($messageStream, $temporaryStream); - $this->messageStreamToEncryptedByteStream($temporaryStream, $inputStream); - } else { - $this->messageStreamToEncryptedByteStream($messageStream, $temporaryStream); - $this->messageStreamToSignedByteStream($temporaryStream, $inputStream); - } - } elseif ($this->signCertificate !== null) { - $this->messageStreamToSignedByteStream($messageStream, $inputStream); - } else { - $this->messageStreamToEncryptedByteStream($messageStream, $inputStream); - } - } - - /** - * @param Swift_Message $message - * - * @return Swift_Message - */ - protected function createMessage(Swift_Message $message) - { - $mimeEntity = new Swift_Message('', $message->getBody(), $message->getContentType(), $message->getCharset()); - $mimeEntity->setChildren($message->getChildren()); - - $messageHeaders = $mimeEntity->getHeaders(); - $messageHeaders->remove('Message-ID'); - $messageHeaders->remove('Date'); - $messageHeaders->remove('Subject'); - $messageHeaders->remove('MIME-Version'); - $messageHeaders->remove('To'); - $messageHeaders->remove('From'); - - return $mimeEntity; - } - - /** - * @param Swift_FileStream $outputStream - * @param Swift_InputByteStream $inputStream - * - * @throws Swift_IoException - */ - protected function messageStreamToSignedByteStream(Swift_FileStream $outputStream, Swift_InputByteStream $inputStream) - { - $signedMessageStream = new Swift_ByteStream_TemporaryFileByteStream(); - - $args = array($outputStream->getPath(), $signedMessageStream->getPath(), $this->signCertificate, $this->signPrivateKey, array(), $this->signOptions); - if (null !== $this->extraCerts) { - $args[] = $this->extraCerts; - } - - if (!call_user_func_array('openssl_pkcs7_sign', $args)) { - throw new Swift_IoException(sprintf('Failed to sign S/Mime message. Error: "%s".', openssl_error_string())); - } - - $this->copyFromOpenSSLOutput($signedMessageStream, $inputStream); - } - - /** - * @param Swift_FileStream $outputStream - * @param Swift_InputByteStream $is - * - * @throws Swift_IoException - */ - protected function messageStreamToEncryptedByteStream(Swift_FileStream $outputStream, Swift_InputByteStream $is) - { - $encryptedMessageStream = new Swift_ByteStream_TemporaryFileByteStream(); - - if (!openssl_pkcs7_encrypt($outputStream->getPath(), $encryptedMessageStream->getPath(), $this->encryptCert, array(), 0, $this->encryptCipher)) { - throw new Swift_IoException(sprintf('Failed to encrypt S/Mime message. Error: "%s".', openssl_error_string())); - } - - $this->copyFromOpenSSLOutput($encryptedMessageStream, $is); - } - - /** - * @param Swift_OutputByteStream $fromStream - * @param Swift_InputByteStream $toStream - */ - protected function copyFromOpenSSLOutput(Swift_OutputByteStream $fromStream, Swift_InputByteStream $toStream) - { - $bufferLength = 4096; - $filteredStream = new Swift_ByteStream_TemporaryFileByteStream(); - $filteredStream->addFilter($this->replacementFactory->createFilter("\r\n", "\n"), 'CRLF to LF'); - $filteredStream->addFilter($this->replacementFactory->createFilter("\n", "\r\n"), 'LF to CRLF'); - - while (false !== ($buffer = $fromStream->read($bufferLength))) { - $filteredStream->write($buffer); - } - - $filteredStream->flushBuffers(); - - while (false !== ($buffer = $filteredStream->read($bufferLength))) { - $toStream->write($buffer); - } - - $toStream->commit(); - } - - /** - * Merges an OutputByteStream to Swift_Message. - * - * @param Swift_OutputByteStream $fromStream - * @param Swift_Message $message - */ - protected function streamToMime(Swift_OutputByteStream $fromStream, Swift_Message $message) - { - $bufferLength = 78; - $headerData = ''; - - $fromStream->setReadPointer(0); - - while (($buffer = $fromStream->read($bufferLength)) !== false) { - $headerData .= $buffer; - - if (false !== strpos($buffer, "\r\n\r\n")) { - break; - } - } - - $headersPosEnd = strpos($headerData, "\r\n\r\n"); - $headerData = trim($headerData); - $headerData = substr($headerData, 0, $headersPosEnd); - $headerLines = explode("\r\n", $headerData); - unset($headerData); - - $headers = array(); - $currentHeaderName = ''; - - foreach ($headerLines as $headerLine) { - // Line separated - if (ctype_space($headerLines[0]) || false === strpos($headerLine, ':')) { - $headers[$currentHeaderName] .= ' '.trim($headerLine); - continue; - } - - $header = explode(':', $headerLine, 2); - $currentHeaderName = strtolower($header[0]); - $headers[$currentHeaderName] = trim($header[1]); - } - - $messageStream = new Swift_ByteStream_TemporaryFileByteStream(); - $messageStream->addFilter($this->replacementFactory->createFilter("\r\n", "\n"), 'CRLF to LF'); - $messageStream->addFilter($this->replacementFactory->createFilter("\n", "\r\n"), 'LF to CRLF'); - - $messageHeaders = $message->getHeaders(); - - // No need to check for 'application/pkcs7-mime', as this is always base64 - if ('multipart/signed;' === substr($headers['content-type'], 0, 17)) { - if (!preg_match('/boundary=("[^"]+"|(?:[^\s]+|$))/is', $headers['content-type'], $contentTypeData)) { - throw new Swift_SwiftException('Failed to find Boundary parameter'); - } - - $boundary = trim($contentTypeData['1'], '"'); - - // Skip the header and CRLF CRLF - $fromStream->setReadPointer($headersPosEnd + 4); - - while (false !== ($buffer = $fromStream->read($bufferLength))) { - $messageStream->write($buffer); - } - - $messageStream->commit(); - - $messageHeaders->remove('Content-Transfer-Encoding'); - $message->setContentType($headers['content-type']); - $message->setBoundary($boundary); - $message->setBody($messageStream); - } else { - $fromStream->setReadPointer($headersPosEnd + 4); - - if (null === $this->headerFactory) { - $this->headerFactory = Swift_DependencyContainer::getInstance()->lookup('mime.headerfactory'); - } - - $message->setContentType($headers['content-type']); - $messageHeaders->set($this->headerFactory->createTextHeader('Content-Transfer-Encoding', $headers['content-transfer-encoding'])); - $messageHeaders->set($this->headerFactory->createTextHeader('Content-Disposition', $headers['content-disposition'])); - - while (false !== ($buffer = $fromStream->read($bufferLength))) { - $messageStream->write($buffer); - } - - $messageStream->commit(); - $message->setBody($messageStream); - } - } -} diff --git a/lib/swiftmailer/swiftmailer/lib/classes/Swift/SmtpTransport.php b/lib/swiftmailer/swiftmailer/lib/classes/Swift/SmtpTransport.php deleted file mode 100644 index b97f01e7c..000000000 --- a/lib/swiftmailer/swiftmailer/lib/classes/Swift/SmtpTransport.php +++ /dev/null @@ -1,58 +0,0 @@ -createDependenciesFor('transport.smtp') - ); - - $this->setHost($host); - $this->setPort($port); - $this->setEncryption($security); - } - - /** - * Create a new SmtpTransport instance. - * - * @param string $host - * @param int $port - * @param string $security - * - * @return self - */ - public static function newInstance($host = 'localhost', $port = 25, $security = null) - { - return new self($host, $port, $security); - } -} diff --git a/lib/swiftmailer/swiftmailer/lib/classes/Swift/Spool.php b/lib/swiftmailer/swiftmailer/lib/classes/Swift/Spool.php deleted file mode 100644 index c16ab4b38..000000000 --- a/lib/swiftmailer/swiftmailer/lib/classes/Swift/Spool.php +++ /dev/null @@ -1,53 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -/** - * Interface for spools. - * - * @author Fabien Potencier - */ -interface Swift_Spool -{ - /** - * Starts this Spool mechanism. - */ - public function start(); - - /** - * Stops this Spool mechanism. - */ - public function stop(); - - /** - * Tests if this Spool mechanism has started. - * - * @return bool - */ - public function isStarted(); - - /** - * Queues a message. - * - * @param Swift_Mime_Message $message The message to store - * - * @return bool Whether the operation has succeeded - */ - public function queueMessage(Swift_Mime_Message $message); - - /** - * Sends messages using the given transport instance. - * - * @param Swift_Transport $transport A transport instance - * @param string[] $failedRecipients An array of failures by-reference - * - * @return int The number of sent emails - */ - public function flushQueue(Swift_Transport $transport, &$failedRecipients = null); -} diff --git a/lib/swiftmailer/swiftmailer/lib/classes/Swift/SpoolTransport.php b/lib/swiftmailer/swiftmailer/lib/classes/Swift/SpoolTransport.php deleted file mode 100644 index 79c9b1f03..000000000 --- a/lib/swiftmailer/swiftmailer/lib/classes/Swift/SpoolTransport.php +++ /dev/null @@ -1,47 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -/** - * Stores Messages in a queue. - * - * @author Fabien Potencier - */ -class Swift_SpoolTransport extends Swift_Transport_SpoolTransport -{ - /** - * Create a new SpoolTransport. - * - * @param Swift_Spool $spool - */ - public function __construct(Swift_Spool $spool) - { - $arguments = Swift_DependencyContainer::getInstance() - ->createDependenciesFor('transport.spool'); - - $arguments[] = $spool; - - call_user_func_array( - array($this, 'Swift_Transport_SpoolTransport::__construct'), - $arguments - ); - } - - /** - * Create a new SpoolTransport instance. - * - * @param Swift_Spool $spool - * - * @return self - */ - public static function newInstance(Swift_Spool $spool) - { - return new self($spool); - } -} diff --git a/lib/swiftmailer/swiftmailer/lib/classes/Swift/StreamFilter.php b/lib/swiftmailer/swiftmailer/lib/classes/Swift/StreamFilter.php deleted file mode 100644 index 362be2e8d..000000000 --- a/lib/swiftmailer/swiftmailer/lib/classes/Swift/StreamFilter.php +++ /dev/null @@ -1,35 +0,0 @@ -_search = $search; - $this->_index = array(); - $this->_tree = array(); - $this->_replace = array(); - $this->_repSize = array(); - - $tree = null; - $i = null; - $last_size = $size = 0; - foreach ($search as $i => $search_element) { - if ($tree !== null) { - $tree[-1] = min(count($replace) - 1, $i - 1); - $tree[-2] = $last_size; - } - $tree = &$this->_tree; - if (is_array($search_element)) { - foreach ($search_element as $k => $char) { - $this->_index[$char] = true; - if (!isset($tree[$char])) { - $tree[$char] = array(); - } - $tree = &$tree[$char]; - } - $last_size = $k + 1; - $size = max($size, $last_size); - } else { - $last_size = 1; - if (!isset($tree[$search_element])) { - $tree[$search_element] = array(); - } - $tree = &$tree[$search_element]; - $size = max($last_size, $size); - $this->_index[$search_element] = true; - } - } - if ($i !== null) { - $tree[-1] = min(count($replace) - 1, $i); - $tree[-2] = $last_size; - $this->_treeMaxLen = $size; - } - foreach ($replace as $rep) { - if (!is_array($rep)) { - $rep = array($rep); - } - $this->_replace[] = $rep; - } - for ($i = count($this->_replace) - 1; $i >= 0; --$i) { - $this->_replace[$i] = $rep = $this->filter($this->_replace[$i], $i); - $this->_repSize[$i] = count($rep); - } - } - - /** - * Returns true if based on the buffer passed more bytes should be buffered. - * - * @param array $buffer - * - * @return bool - */ - public function shouldBuffer($buffer) - { - $endOfBuffer = end($buffer); - - return isset($this->_index[$endOfBuffer]); - } - - /** - * Perform the actual replacements on $buffer and return the result. - * - * @param array $buffer - * @param int $_minReplaces - * - * @return array - */ - public function filter($buffer, $_minReplaces = -1) - { - if ($this->_treeMaxLen == 0) { - return $buffer; - } - - $newBuffer = array(); - $buf_size = count($buffer); - $last_size = 0; - for ($i = 0; $i < $buf_size; ++$i) { - $search_pos = $this->_tree; - $last_found = PHP_INT_MAX; - // We try to find if the next byte is part of a search pattern - for ($j = 0; $j <= $this->_treeMaxLen; ++$j) { - // We have a new byte for a search pattern - if (isset($buffer[$p = $i + $j]) && isset($search_pos[$buffer[$p]])) { - $search_pos = $search_pos[$buffer[$p]]; - // We have a complete pattern, save, in case we don't find a better match later - if (isset($search_pos[-1]) && $search_pos[-1] < $last_found - && $search_pos[-1] > $_minReplaces) { - $last_found = $search_pos[-1]; - $last_size = $search_pos[-2]; - } - } - // We got a complete pattern - elseif ($last_found !== PHP_INT_MAX) { - // Adding replacement datas to output buffer - $rep_size = $this->_repSize[$last_found]; - for ($j = 0; $j < $rep_size; ++$j) { - $newBuffer[] = $this->_replace[$last_found][$j]; - } - // We Move cursor forward - $i += $last_size - 1; - // Edge Case, last position in buffer - if ($i >= $buf_size) { - $newBuffer[] = $buffer[$i]; - } - - // We start the next loop - continue 2; - } else { - // this byte is not in a pattern and we haven't found another pattern - break; - } - } - // Normal byte, move it to output buffer - $newBuffer[] = $buffer[$i]; - } - - return $newBuffer; - } -} diff --git a/lib/swiftmailer/swiftmailer/lib/classes/Swift/StreamFilters/StringReplacementFilter.php b/lib/swiftmailer/swiftmailer/lib/classes/Swift/StreamFilters/StringReplacementFilter.php deleted file mode 100644 index f64144af2..000000000 --- a/lib/swiftmailer/swiftmailer/lib/classes/Swift/StreamFilters/StringReplacementFilter.php +++ /dev/null @@ -1,70 +0,0 @@ -_search = $search; - $this->_replace = $replace; - } - - /** - * Returns true if based on the buffer passed more bytes should be buffered. - * - * @param string $buffer - * - * @return bool - */ - public function shouldBuffer($buffer) - { - if ('' === $buffer) { - return false; - } - - $endOfBuffer = substr($buffer, -1); - foreach ((array) $this->_search as $needle) { - if (false !== strpos($needle, $endOfBuffer)) { - return true; - } - } - - return false; - } - - /** - * Perform the actual replacements on $buffer and return the result. - * - * @param string $buffer - * - * @return string - */ - public function filter($buffer) - { - return str_replace($this->_search, $this->_replace, $buffer); - } -} diff --git a/lib/swiftmailer/swiftmailer/lib/classes/Swift/StreamFilters/StringReplacementFilterFactory.php b/lib/swiftmailer/swiftmailer/lib/classes/Swift/StreamFilters/StringReplacementFilterFactory.php deleted file mode 100644 index e98240b5b..000000000 --- a/lib/swiftmailer/swiftmailer/lib/classes/Swift/StreamFilters/StringReplacementFilterFactory.php +++ /dev/null @@ -1,45 +0,0 @@ -_filters[$search][$replace])) { - if (!isset($this->_filters[$search])) { - $this->_filters[$search] = array(); - } - - if (!isset($this->_filters[$search][$replace])) { - $this->_filters[$search][$replace] = array(); - } - - $this->_filters[$search][$replace] = new Swift_StreamFilters_StringReplacementFilter($search, $replace); - } - - return $this->_filters[$search][$replace]; - } -} diff --git a/lib/swiftmailer/swiftmailer/lib/classes/Swift/SwiftException.php b/lib/swiftmailer/swiftmailer/lib/classes/Swift/SwiftException.php deleted file mode 100644 index db3d31093..000000000 --- a/lib/swiftmailer/swiftmailer/lib/classes/Swift/SwiftException.php +++ /dev/null @@ -1,29 +0,0 @@ -_eventDispatcher = $dispatcher; - $this->_buffer = $buf; - $this->_lookupHostname(); - } - - /** - * Set the name of the local domain which Swift will identify itself as. - * - * This should be a fully-qualified domain name and should be truly the domain - * you're using. - * - * If your server doesn't have a domain name, use the IP in square - * brackets (i.e. [127.0.0.1]). - * - * @param string $domain - * - * @return $this - */ - public function setLocalDomain($domain) - { - $this->_domain = $domain; - - return $this; - } - - /** - * Get the name of the domain Swift will identify as. - * - * @return string - */ - public function getLocalDomain() - { - return $this->_domain; - } - - /** - * Sets the source IP. - * - * @param string $source - */ - public function setSourceIp($source) - { - $this->_sourceIp = $source; - } - - /** - * Returns the IP used to connect to the destination. - * - * @return string - */ - public function getSourceIp() - { - return $this->_sourceIp; - } - - /** - * Start the SMTP connection. - */ - public function start() - { - if (!$this->_started) { - if ($evt = $this->_eventDispatcher->createTransportChangeEvent($this)) { - $this->_eventDispatcher->dispatchEvent($evt, 'beforeTransportStarted'); - if ($evt->bubbleCancelled()) { - return; - } - } - - try { - $this->_buffer->initialize($this->_getBufferParams()); - } catch (Swift_TransportException $e) { - $this->_throwException($e); - } - $this->_readGreeting(); - $this->_doHeloCommand(); - - if ($evt) { - $this->_eventDispatcher->dispatchEvent($evt, 'transportStarted'); - } - - $this->_started = true; - } - } - - /** - * Test if an SMTP connection has been established. - * - * @return bool - */ - public function isStarted() - { - return $this->_started; - } - - /** - * Send the given Message. - * - * Recipient/sender data will be retrieved from the Message API. - * The return value is the number of recipients who were accepted for delivery. - * - * @param Swift_Mime_Message $message - * @param string[] $failedRecipients An array of failures by-reference - * - * @return int - */ - public function send(Swift_Mime_Message $message, &$failedRecipients = null) - { - $sent = 0; - $failedRecipients = (array) $failedRecipients; - - if ($evt = $this->_eventDispatcher->createSendEvent($this, $message)) { - $this->_eventDispatcher->dispatchEvent($evt, 'beforeSendPerformed'); - if ($evt->bubbleCancelled()) { - return 0; - } - } - - if (!$reversePath = $this->_getReversePath($message)) { - $this->_throwException(new Swift_TransportException( - 'Cannot send message without a sender address' - ) - ); - } - - $to = (array) $message->getTo(); - $cc = (array) $message->getCc(); - $tos = array_merge($to, $cc); - $bcc = (array) $message->getBcc(); - - $message->setBcc(array()); - - try { - $sent += $this->_sendTo($message, $reversePath, $tos, $failedRecipients); - $sent += $this->_sendBcc($message, $reversePath, $bcc, $failedRecipients); - } catch (Exception $e) { - $message->setBcc($bcc); - throw $e; - } - - $message->setBcc($bcc); - - if ($evt) { - if ($sent == count($to) + count($cc) + count($bcc)) { - $evt->setResult(Swift_Events_SendEvent::RESULT_SUCCESS); - } elseif ($sent > 0) { - $evt->setResult(Swift_Events_SendEvent::RESULT_TENTATIVE); - } else { - $evt->setResult(Swift_Events_SendEvent::RESULT_FAILED); - } - $evt->setFailedRecipients($failedRecipients); - $this->_eventDispatcher->dispatchEvent($evt, 'sendPerformed'); - } - - $message->generateId(); //Make sure a new Message ID is used - - return $sent; - } - - /** - * Stop the SMTP connection. - */ - public function stop() - { - if ($this->_started) { - if ($evt = $this->_eventDispatcher->createTransportChangeEvent($this)) { - $this->_eventDispatcher->dispatchEvent($evt, 'beforeTransportStopped'); - if ($evt->bubbleCancelled()) { - return; - } - } - - try { - $this->executeCommand("QUIT\r\n", array(221)); - } catch (Swift_TransportException $e) { - } - - try { - $this->_buffer->terminate(); - - if ($evt) { - $this->_eventDispatcher->dispatchEvent($evt, 'transportStopped'); - } - } catch (Swift_TransportException $e) { - $this->_throwException($e); - } - } - $this->_started = false; - } - - /** - * Register a plugin. - * - * @param Swift_Events_EventListener $plugin - */ - public function registerPlugin(Swift_Events_EventListener $plugin) - { - $this->_eventDispatcher->bindEventListener($plugin); - } - - /** - * Reset the current mail transaction. - */ - public function reset() - { - $this->executeCommand("RSET\r\n", array(250)); - } - - /** - * Get the IoBuffer where read/writes are occurring. - * - * @return Swift_Transport_IoBuffer - */ - public function getBuffer() - { - return $this->_buffer; - } - - /** - * Run a command against the buffer, expecting the given response codes. - * - * If no response codes are given, the response will not be validated. - * If codes are given, an exception will be thrown on an invalid response. - * - * @param string $command - * @param int[] $codes - * @param string[] $failures An array of failures by-reference - * - * @return string - */ - public function executeCommand($command, $codes = array(), &$failures = null) - { - $failures = (array) $failures; - $seq = $this->_buffer->write($command); - $response = $this->_getFullResponse($seq); - if ($evt = $this->_eventDispatcher->createCommandEvent($this, $command, $codes)) { - $this->_eventDispatcher->dispatchEvent($evt, 'commandSent'); - } - $this->_assertResponseCode($response, $codes); - - return $response; - } - - /** Read the opening SMTP greeting */ - protected function _readGreeting() - { - $this->_assertResponseCode($this->_getFullResponse(0), array(220)); - } - - /** Send the HELO welcome */ - protected function _doHeloCommand() - { - $this->executeCommand( - sprintf("HELO %s\r\n", $this->_domain), array(250) - ); - } - - /** Send the MAIL FROM command */ - protected function _doMailFromCommand($address) - { - $this->executeCommand( - sprintf("MAIL FROM:<%s>\r\n", $address), array(250) - ); - } - - /** Send the RCPT TO command */ - protected function _doRcptToCommand($address) - { - $this->executeCommand( - sprintf("RCPT TO:<%s>\r\n", $address), array(250, 251, 252) - ); - } - - /** Send the DATA command */ - protected function _doDataCommand() - { - $this->executeCommand("DATA\r\n", array(354)); - } - - /** Stream the contents of the message over the buffer */ - protected function _streamMessage(Swift_Mime_Message $message) - { - $this->_buffer->setWriteTranslations(array("\r\n." => "\r\n..")); - try { - $message->toByteStream($this->_buffer); - $this->_buffer->flushBuffers(); - } catch (Swift_TransportException $e) { - $this->_throwException($e); - } - $this->_buffer->setWriteTranslations(array()); - $this->executeCommand("\r\n.\r\n", array(250)); - } - - /** Determine the best-use reverse path for this message */ - protected function _getReversePath(Swift_Mime_Message $message) - { - $return = $message->getReturnPath(); - $sender = $message->getSender(); - $from = $message->getFrom(); - $path = null; - if (!empty($return)) { - $path = $return; - } elseif (!empty($sender)) { - // Don't use array_keys - reset($sender); // Reset Pointer to first pos - $path = key($sender); // Get key - } elseif (!empty($from)) { - reset($from); // Reset Pointer to first pos - $path = key($from); // Get key - } - - return $path; - } - - /** Throw a TransportException, first sending it to any listeners */ - protected function _throwException(Swift_TransportException $e) - { - if ($evt = $this->_eventDispatcher->createTransportExceptionEvent($this, $e)) { - $this->_eventDispatcher->dispatchEvent($evt, 'exceptionThrown'); - if (!$evt->bubbleCancelled()) { - throw $e; - } - } else { - throw $e; - } - } - - /** Throws an Exception if a response code is incorrect */ - protected function _assertResponseCode($response, $wanted) - { - list($code) = sscanf($response, '%3d'); - $valid = (empty($wanted) || in_array($code, $wanted)); - - if ($evt = $this->_eventDispatcher->createResponseEvent($this, $response, - $valid)) { - $this->_eventDispatcher->dispatchEvent($evt, 'responseReceived'); - } - - if (!$valid) { - $this->_throwException( - new Swift_TransportException( - 'Expected response code '.implode('/', $wanted).' but got code '. - '"'.$code.'", with message "'.$response.'"', - $code) - ); - } - } - - /** Get an entire multi-line response using its sequence number */ - protected function _getFullResponse($seq) - { - $response = ''; - try { - do { - $line = $this->_buffer->readLine($seq); - $response .= $line; - } while (null !== $line && false !== $line && ' ' != $line[3]); - } catch (Swift_TransportException $e) { - $this->_throwException($e); - } catch (Swift_IoException $e) { - $this->_throwException( - new Swift_TransportException( - $e->getMessage()) - ); - } - - return $response; - } - - /** Send an email to the given recipients from the given reverse path */ - private function _doMailTransaction($message, $reversePath, array $recipients, array &$failedRecipients) - { - $sent = 0; - $this->_doMailFromCommand($reversePath); - foreach ($recipients as $forwardPath) { - try { - $this->_doRcptToCommand($forwardPath); - ++$sent; - } catch (Swift_TransportException $e) { - $failedRecipients[] = $forwardPath; - } - } - - if ($sent != 0) { - $this->_doDataCommand(); - $this->_streamMessage($message); - } else { - $this->reset(); - } - - return $sent; - } - - /** Send a message to the given To: recipients */ - private function _sendTo(Swift_Mime_Message $message, $reversePath, array $to, array &$failedRecipients) - { - if (empty($to)) { - return 0; - } - - return $this->_doMailTransaction($message, $reversePath, array_keys($to), - $failedRecipients); - } - - /** Send a message to all Bcc: recipients */ - private function _sendBcc(Swift_Mime_Message $message, $reversePath, array $bcc, array &$failedRecipients) - { - $sent = 0; - foreach ($bcc as $forwardPath => $name) { - $message->setBcc(array($forwardPath => $name)); - $sent += $this->_doMailTransaction( - $message, $reversePath, array($forwardPath), $failedRecipients - ); - } - - return $sent; - } - - /** Try to determine the hostname of the server this is run on */ - private function _lookupHostname() - { - if (!empty($_SERVER['SERVER_NAME']) && $this->_isFqdn($_SERVER['SERVER_NAME'])) { - $this->_domain = $_SERVER['SERVER_NAME']; - } elseif (!empty($_SERVER['SERVER_ADDR'])) { - // Set the address literal tag (See RFC 5321, section: 4.1.3) - if (false === strpos($_SERVER['SERVER_ADDR'], ':')) { - $prefix = ''; // IPv4 addresses are not tagged. - } else { - $prefix = 'IPv6:'; // Adding prefix in case of IPv6. - } - - $this->_domain = sprintf('[%s%s]', $prefix, $_SERVER['SERVER_ADDR']); - } - } - - /** Determine is the $hostname is a fully-qualified name */ - private function _isFqdn($hostname) - { - // We could do a really thorough check, but there's really no point - if (false !== $dotPos = strpos($hostname, '.')) { - return ($dotPos > 0) && ($dotPos != strlen($hostname) - 1); - } - - return false; - } - - /** - * Destructor. - */ - public function __destruct() - { - try { - $this->stop(); - } catch (Exception $e) { - } - } -} diff --git a/lib/swiftmailer/swiftmailer/lib/classes/Swift/Transport/Esmtp/Auth/CramMd5Authenticator.php b/lib/swiftmailer/swiftmailer/lib/classes/Swift/Transport/Esmtp/Auth/CramMd5Authenticator.php deleted file mode 100644 index 53f721d03..000000000 --- a/lib/swiftmailer/swiftmailer/lib/classes/Swift/Transport/Esmtp/Auth/CramMd5Authenticator.php +++ /dev/null @@ -1,81 +0,0 @@ -executeCommand("AUTH CRAM-MD5\r\n", array(334)); - $challenge = base64_decode(substr($challenge, 4)); - $message = base64_encode( - $username.' '.$this->_getResponse($password, $challenge) - ); - $agent->executeCommand(sprintf("%s\r\n", $message), array(235)); - - return true; - } catch (Swift_TransportException $e) { - $agent->executeCommand("RSET\r\n", array(250)); - - return false; - } - } - - /** - * Generate a CRAM-MD5 response from a server challenge. - * - * @param string $secret - * @param string $challenge - * - * @return string - */ - private function _getResponse($secret, $challenge) - { - if (strlen($secret) > 64) { - $secret = pack('H32', md5($secret)); - } - - if (strlen($secret) < 64) { - $secret = str_pad($secret, 64, chr(0)); - } - - $k_ipad = substr($secret, 0, 64) ^ str_repeat(chr(0x36), 64); - $k_opad = substr($secret, 0, 64) ^ str_repeat(chr(0x5C), 64); - - $inner = pack('H32', md5($k_ipad.$challenge)); - $digest = md5($k_opad.$inner); - - return $digest; - } -} diff --git a/lib/swiftmailer/swiftmailer/lib/classes/Swift/Transport/Esmtp/Auth/LoginAuthenticator.php b/lib/swiftmailer/swiftmailer/lib/classes/Swift/Transport/Esmtp/Auth/LoginAuthenticator.php deleted file mode 100644 index 6ab6e3337..000000000 --- a/lib/swiftmailer/swiftmailer/lib/classes/Swift/Transport/Esmtp/Auth/LoginAuthenticator.php +++ /dev/null @@ -1,51 +0,0 @@ -executeCommand("AUTH LOGIN\r\n", array(334)); - $agent->executeCommand(sprintf("%s\r\n", base64_encode($username)), array(334)); - $agent->executeCommand(sprintf("%s\r\n", base64_encode($password)), array(235)); - - return true; - } catch (Swift_TransportException $e) { - $agent->executeCommand("RSET\r\n", array(250)); - - return false; - } - } -} diff --git a/lib/swiftmailer/swiftmailer/lib/classes/Swift/Transport/Esmtp/Auth/NTLMAuthenticator.php b/lib/swiftmailer/swiftmailer/lib/classes/Swift/Transport/Esmtp/Auth/NTLMAuthenticator.php deleted file mode 100644 index 839265857..000000000 --- a/lib/swiftmailer/swiftmailer/lib/classes/Swift/Transport/Esmtp/Auth/NTLMAuthenticator.php +++ /dev/null @@ -1,725 +0,0 @@ - - */ -class Swift_Transport_Esmtp_Auth_NTLMAuthenticator implements Swift_Transport_Esmtp_Authenticator -{ - const NTLMSIG = "NTLMSSP\x00"; - const DESCONST = 'KGS!@#$%'; - - /** - * Get the name of the AUTH mechanism this Authenticator handles. - * - * @return string - */ - public function getAuthKeyword() - { - return 'NTLM'; - } - - /** - * Try to authenticate the user with $username and $password. - * - * @param Swift_Transport_SmtpAgent $agent - * @param string $username - * @param string $password - * - * @return bool - */ - public function authenticate(Swift_Transport_SmtpAgent $agent, $username, $password) - { - if (!function_exists('openssl_random_pseudo_bytes') || !function_exists('openssl_encrypt')) { - throw new LogicException('The OpenSSL extension must be enabled to use the NTLM authenticator.'); - } - - if (!function_exists('bcmul')) { - throw new LogicException('The BCMath functions must be enabled to use the NTLM authenticator.'); - } - - try { - // execute AUTH command and filter out the code at the beginning - // AUTH NTLM xxxx - $response = base64_decode(substr(trim($this->sendMessage1($agent)), 4)); - - // extra parameters for our unit cases - $timestamp = func_num_args() > 3 ? func_get_arg(3) : $this->getCorrectTimestamp(bcmul(microtime(true), '1000')); - $client = func_num_args() > 4 ? func_get_arg(4) : $this->getRandomBytes(8); - - // Message 3 response - $this->sendMessage3($response, $username, $password, $timestamp, $client, $agent); - - return true; - } catch (Swift_TransportException $e) { - $agent->executeCommand("RSET\r\n", array(250)); - - return false; - } - } - - protected function si2bin($si, $bits = 32) - { - $bin = null; - if ($si >= -pow(2, $bits - 1) && ($si <= pow(2, $bits - 1))) { - // positive or zero - if ($si >= 0) { - $bin = base_convert($si, 10, 2); - // pad to $bits bit - $bin_length = strlen($bin); - if ($bin_length < $bits) { - $bin = str_repeat('0', $bits - $bin_length).$bin; - } - } else { - // negative - $si = -$si - pow(2, $bits); - $bin = base_convert($si, 10, 2); - $bin_length = strlen($bin); - if ($bin_length > $bits) { - $bin = str_repeat('1', $bits - $bin_length).$bin; - } - } - } - - return $bin; - } - - /** - * Send our auth message and returns the response. - * - * @param Swift_Transport_SmtpAgent $agent - * - * @return string SMTP Response - */ - protected function sendMessage1(Swift_Transport_SmtpAgent $agent) - { - $message = $this->createMessage1(); - - return $agent->executeCommand(sprintf("AUTH %s %s\r\n", $this->getAuthKeyword(), base64_encode($message)), array(334)); - } - - /** - * Fetch all details of our response (message 2). - * - * @param string $response - * - * @return array our response parsed - */ - protected function parseMessage2($response) - { - $responseHex = bin2hex($response); - $length = floor(hexdec(substr($responseHex, 28, 4)) / 256) * 2; - $offset = floor(hexdec(substr($responseHex, 32, 4)) / 256) * 2; - $challenge = $this->hex2bin(substr($responseHex, 48, 16)); - $context = $this->hex2bin(substr($responseHex, 64, 16)); - $targetInfoH = $this->hex2bin(substr($responseHex, 80, 16)); - $targetName = $this->hex2bin(substr($responseHex, $offset, $length)); - $offset = floor(hexdec(substr($responseHex, 88, 4)) / 256) * 2; - $targetInfoBlock = substr($responseHex, $offset); - list($domainName, $serverName, $DNSDomainName, $DNSServerName, $terminatorByte) = $this->readSubBlock($targetInfoBlock); - - return array( - $challenge, - $context, - $targetInfoH, - $targetName, - $domainName, - $serverName, - $DNSDomainName, - $DNSServerName, - $this->hex2bin($targetInfoBlock), - $terminatorByte, - ); - } - - /** - * Read the blob information in from message2. - * - * @param $block - * - * @return array - */ - protected function readSubBlock($block) - { - // remove terminatorByte cause it's always the same - $block = substr($block, 0, -8); - - $length = strlen($block); - $offset = 0; - $data = array(); - while ($offset < $length) { - $blockLength = hexdec(substr(substr($block, $offset, 8), -4)) / 256; - $offset += 8; - $data[] = $this->hex2bin(substr($block, $offset, $blockLength * 2)); - $offset += $blockLength * 2; - } - - if (count($data) == 3) { - $data[] = $data[2]; - $data[2] = ''; - } - - $data[] = $this->createByte('00'); - - return $data; - } - - /** - * Send our final message with all our data. - * - * @param string $response Message 1 response (message 2) - * @param string $username - * @param string $password - * @param string $timestamp - * @param string $client - * @param Swift_Transport_SmtpAgent $agent - * @param bool $v2 Use version2 of the protocol - * - * @return string - */ - protected function sendMessage3($response, $username, $password, $timestamp, $client, Swift_Transport_SmtpAgent $agent, $v2 = true) - { - list($domain, $username) = $this->getDomainAndUsername($username); - //$challenge, $context, $targetInfoH, $targetName, $domainName, $workstation, $DNSDomainName, $DNSServerName, $blob, $ter - list($challenge, , , , , $workstation, , , $blob) = $this->parseMessage2($response); - - if (!$v2) { - // LMv1 - $lmResponse = $this->createLMPassword($password, $challenge); - // NTLMv1 - $ntlmResponse = $this->createNTLMPassword($password, $challenge); - } else { - // LMv2 - $lmResponse = $this->createLMv2Password($password, $username, $domain, $challenge, $client); - // NTLMv2 - $ntlmResponse = $this->createNTLMv2Hash($password, $username, $domain, $challenge, $blob, $timestamp, $client); - } - - $message = $this->createMessage3($domain, $username, $workstation, $lmResponse, $ntlmResponse); - - return $agent->executeCommand(sprintf("%s\r\n", base64_encode($message)), array(235)); - } - - /** - * Create our message 1. - * - * @return string - */ - protected function createMessage1() - { - return self::NTLMSIG - .$this->createByte('01') // Message 1 -.$this->createByte('0702'); // Flags - } - - /** - * Create our message 3. - * - * @param string $domain - * @param string $username - * @param string $workstation - * @param string $lmResponse - * @param string $ntlmResponse - * - * @return string - */ - protected function createMessage3($domain, $username, $workstation, $lmResponse, $ntlmResponse) - { - // Create security buffers - $domainSec = $this->createSecurityBuffer($domain, 64); - $domainInfo = $this->readSecurityBuffer(bin2hex($domainSec)); - $userSec = $this->createSecurityBuffer($username, ($domainInfo[0] + $domainInfo[1]) / 2); - $userInfo = $this->readSecurityBuffer(bin2hex($userSec)); - $workSec = $this->createSecurityBuffer($workstation, ($userInfo[0] + $userInfo[1]) / 2); - $workInfo = $this->readSecurityBuffer(bin2hex($workSec)); - $lmSec = $this->createSecurityBuffer($lmResponse, ($workInfo[0] + $workInfo[1]) / 2, true); - $lmInfo = $this->readSecurityBuffer(bin2hex($lmSec)); - $ntlmSec = $this->createSecurityBuffer($ntlmResponse, ($lmInfo[0] + $lmInfo[1]) / 2, true); - - return self::NTLMSIG - .$this->createByte('03') // TYPE 3 message -.$lmSec // LM response header -.$ntlmSec // NTLM response header -.$domainSec // Domain header -.$userSec // User header -.$workSec // Workstation header -.$this->createByte('000000009a', 8) // session key header (empty) -.$this->createByte('01020000') // FLAGS -.$this->convertTo16bit($domain) // domain name -.$this->convertTo16bit($username) // username -.$this->convertTo16bit($workstation) // workstation -.$lmResponse - .$ntlmResponse; - } - - /** - * @param string $timestamp Epoch timestamp in microseconds - * @param string $client Random bytes - * @param string $targetInfo - * - * @return string - */ - protected function createBlob($timestamp, $client, $targetInfo) - { - return $this->createByte('0101') - .$this->createByte('00') - .$timestamp - .$client - .$this->createByte('00') - .$targetInfo - .$this->createByte('00'); - } - - /** - * Get domain and username from our username. - * - * @example DOMAIN\username - * - * @param string $name - * - * @return array - */ - protected function getDomainAndUsername($name) - { - if (strpos($name, '\\') !== false) { - return explode('\\', $name); - } - - if (false !== strpos($name, '@')) { - list($user, $domain) = explode('@', $name); - - return array($domain, $user); - } - - // no domain passed - return array('', $name); - } - - /** - * Create LMv1 response. - * - * @param string $password - * @param string $challenge - * - * @return string - */ - protected function createLMPassword($password, $challenge) - { - // FIRST PART - $password = $this->createByte(strtoupper($password), 14, false); - list($key1, $key2) = str_split($password, 7); - - $desKey1 = $this->createDesKey($key1); - $desKey2 = $this->createDesKey($key2); - - $constantDecrypt = $this->createByte($this->desEncrypt(self::DESCONST, $desKey1).$this->desEncrypt(self::DESCONST, $desKey2), 21, false); - - // SECOND PART - list($key1, $key2, $key3) = str_split($constantDecrypt, 7); - - $desKey1 = $this->createDesKey($key1); - $desKey2 = $this->createDesKey($key2); - $desKey3 = $this->createDesKey($key3); - - return $this->desEncrypt($challenge, $desKey1).$this->desEncrypt($challenge, $desKey2).$this->desEncrypt($challenge, $desKey3); - } - - /** - * Create NTLMv1 response. - * - * @param string $password - * @param string $challenge - * - * @return string - */ - protected function createNTLMPassword($password, $challenge) - { - // FIRST PART - $ntlmHash = $this->createByte($this->md4Encrypt($password), 21, false); - list($key1, $key2, $key3) = str_split($ntlmHash, 7); - - $desKey1 = $this->createDesKey($key1); - $desKey2 = $this->createDesKey($key2); - $desKey3 = $this->createDesKey($key3); - - return $this->desEncrypt($challenge, $desKey1).$this->desEncrypt($challenge, $desKey2).$this->desEncrypt($challenge, $desKey3); - } - - /** - * Convert a normal timestamp to a tenth of a microtime epoch time. - * - * @param string $time - * - * @return string - */ - protected function getCorrectTimestamp($time) - { - // Get our timestamp (tricky!) - $time = number_format($time, 0, '.', ''); // save microtime to string - $time = bcadd($time, '11644473600000', 0); // add epoch time - $time = bcmul($time, 10000, 0); // tenths of a microsecond. - - $binary = $this->si2bin($time, 64); // create 64 bit binary string - $timestamp = ''; - for ($i = 0; $i < 8; ++$i) { - $timestamp .= chr(bindec(substr($binary, -(($i + 1) * 8), 8))); - } - - return $timestamp; - } - - /** - * Create LMv2 response. - * - * @param string $password - * @param string $username - * @param string $domain - * @param string $challenge NTLM Challenge - * @param string $client Random string - * - * @return string - */ - protected function createLMv2Password($password, $username, $domain, $challenge, $client) - { - $lmPass = '00'; // by default 00 - // if $password > 15 than we can't use this method - if (strlen($password) <= 15) { - $ntlmHash = $this->md4Encrypt($password); - $ntml2Hash = $this->md5Encrypt($ntlmHash, $this->convertTo16bit(strtoupper($username).$domain)); - - $lmPass = bin2hex($this->md5Encrypt($ntml2Hash, $challenge.$client).$client); - } - - return $this->createByte($lmPass, 24); - } - - /** - * Create NTLMv2 response. - * - * @param string $password - * @param string $username - * @param string $domain - * @param string $challenge Hex values - * @param string $targetInfo Hex values - * @param string $timestamp - * @param string $client Random bytes - * - * @return string - * - * @see http://davenport.sourceforge.net/ntlm.html#theNtlmResponse - */ - protected function createNTLMv2Hash($password, $username, $domain, $challenge, $targetInfo, $timestamp, $client) - { - $ntlmHash = $this->md4Encrypt($password); - $ntml2Hash = $this->md5Encrypt($ntlmHash, $this->convertTo16bit(strtoupper($username).$domain)); - - // create blob - $blob = $this->createBlob($timestamp, $client, $targetInfo); - - $ntlmv2Response = $this->md5Encrypt($ntml2Hash, $challenge.$blob); - - return $ntlmv2Response.$blob; - } - - protected function createDesKey($key) - { - $material = array(bin2hex($key[0])); - $len = strlen($key); - for ($i = 1; $i < $len; ++$i) { - list($high, $low) = str_split(bin2hex($key[$i])); - $v = $this->castToByte(ord($key[$i - 1]) << (7 + 1 - $i) | $this->uRShift(hexdec(dechex(hexdec($high) & 0xf).dechex(hexdec($low) & 0xf)), $i)); - $material[] = str_pad(substr(dechex($v), -2), 2, '0', STR_PAD_LEFT); // cast to byte - } - $material[] = str_pad(substr(dechex($this->castToByte(ord($key[6]) << 1)), -2), 2, '0'); - - // odd parity - foreach ($material as $k => $v) { - $b = $this->castToByte(hexdec($v)); - $needsParity = (($this->uRShift($b, 7) ^ $this->uRShift($b, 6) ^ $this->uRShift($b, 5) - ^ $this->uRShift($b, 4) ^ $this->uRShift($b, 3) ^ $this->uRShift($b, 2) - ^ $this->uRShift($b, 1)) & 0x01) == 0; - - list($high, $low) = str_split($v); - if ($needsParity) { - $material[$k] = dechex(hexdec($high) | 0x0).dechex(hexdec($low) | 0x1); - } else { - $material[$k] = dechex(hexdec($high) & 0xf).dechex(hexdec($low) & 0xe); - } - } - - return $this->hex2bin(implode('', $material)); - } - - /** HELPER FUNCTIONS */ - - /** - * Create our security buffer depending on length and offset. - * - * @param string $value Value we want to put in - * @param int $offset start of value - * @param bool $is16 Do we 16bit string or not? - * - * @return string - */ - protected function createSecurityBuffer($value, $offset, $is16 = false) - { - $length = strlen(bin2hex($value)); - $length = $is16 ? $length / 2 : $length; - $length = $this->createByte(str_pad(dechex($length), 2, '0', STR_PAD_LEFT), 2); - - return $length.$length.$this->createByte(dechex($offset), 4); - } - - /** - * Read our security buffer to fetch length and offset of our value. - * - * @param string $value Securitybuffer in hex - * - * @return array array with length and offset - */ - protected function readSecurityBuffer($value) - { - $length = floor(hexdec(substr($value, 0, 4)) / 256) * 2; - $offset = floor(hexdec(substr($value, 8, 4)) / 256) * 2; - - return array($length, $offset); - } - - /** - * Cast to byte java equivalent to (byte). - * - * @param int $v - * - * @return int - */ - protected function castToByte($v) - { - return (($v + 128) % 256) - 128; - } - - /** - * Java unsigned right bitwise - * $a >>> $b. - * - * @param int $a - * @param int $b - * - * @return int - */ - protected function uRShift($a, $b) - { - if ($b == 0) { - return $a; - } - - return ($a >> $b) & ~(1 << (8 * PHP_INT_SIZE - 1) >> ($b - 1)); - } - - /** - * Right padding with 0 to certain length. - * - * @param string $input - * @param int $bytes Length of bytes - * @param bool $isHex Did we provided hex value - * - * @return string - */ - protected function createByte($input, $bytes = 4, $isHex = true) - { - if ($isHex) { - $byte = $this->hex2bin(str_pad($input, $bytes * 2, '00')); - } else { - $byte = str_pad($input, $bytes, "\x00"); - } - - return $byte; - } - - /** - * Create random bytes. - * - * @param $length - * - * @return string - */ - protected function getRandomBytes($length) - { - $bytes = openssl_random_pseudo_bytes($length, $strong); - - if (false !== $bytes && true === $strong) { - return $bytes; - } - - throw new RuntimeException('OpenSSL did not produce a secure random number.'); - } - - /** ENCRYPTION ALGORITHMS */ - - /** - * DES Encryption. - * - * @param string $value An 8-byte string - * @param string $key - * - * @return string - */ - protected function desEncrypt($value, $key) - { - // 1 == OPENSSL_RAW_DATA - but constant is only available as of PHP 5.4. - return substr(openssl_encrypt($value, 'DES-ECB', $key, 1), 0, 8); - } - - /** - * MD5 Encryption. - * - * @param string $key Encryption key - * @param string $msg Message to encrypt - * - * @return string - */ - protected function md5Encrypt($key, $msg) - { - $blocksize = 64; - if (strlen($key) > $blocksize) { - $key = pack('H*', md5($key)); - } - - $key = str_pad($key, $blocksize, "\0"); - $ipadk = $key ^ str_repeat("\x36", $blocksize); - $opadk = $key ^ str_repeat("\x5c", $blocksize); - - return pack('H*', md5($opadk.pack('H*', md5($ipadk.$msg)))); - } - - /** - * MD4 Encryption. - * - * @param string $input - * - * @return string - * - * @see http://php.net/manual/en/ref.hash.php - */ - protected function md4Encrypt($input) - { - $input = $this->convertTo16bit($input); - - return function_exists('hash') ? $this->hex2bin(hash('md4', $input)) : mhash(MHASH_MD4, $input); - } - - /** - * Convert UTF-8 to UTF-16. - * - * @param string $input - * - * @return string - */ - protected function convertTo16bit($input) - { - return iconv('UTF-8', 'UTF-16LE', $input); - } - - /** - * Hex2bin replacement for < PHP 5.4. - * - * @param string $hex - * - * @return string Binary - */ - protected function hex2bin($hex) - { - if (function_exists('hex2bin')) { - return hex2bin($hex); - } else { - return pack('H*', $hex); - } - } - - /** - * @param string $message - */ - protected function debug($message) - { - $message = bin2hex($message); - $messageId = substr($message, 16, 8); - echo substr($message, 0, 16)." NTLMSSP Signature
\n"; - echo $messageId." Type Indicator
\n"; - - if ($messageId == '02000000') { - $map = array( - 'Challenge', - 'Context', - 'Target Information Security Buffer', - 'Target Name Data', - 'NetBIOS Domain Name', - 'NetBIOS Server Name', - 'DNS Domain Name', - 'DNS Server Name', - 'BLOB', - 'Target Information Terminator', - ); - - $data = $this->parseMessage2($this->hex2bin($message)); - - foreach ($map as $key => $value) { - echo bin2hex($data[$key]).' - '.$data[$key].' ||| '.$value."
\n"; - } - } elseif ($messageId == '03000000') { - $i = 0; - $data[$i++] = substr($message, 24, 16); - list($lmLength, $lmOffset) = $this->readSecurityBuffer($data[$i - 1]); - - $data[$i++] = substr($message, 40, 16); - list($ntmlLength, $ntmlOffset) = $this->readSecurityBuffer($data[$i - 1]); - - $data[$i++] = substr($message, 56, 16); - list($targetLength, $targetOffset) = $this->readSecurityBuffer($data[$i - 1]); - - $data[$i++] = substr($message, 72, 16); - list($userLength, $userOffset) = $this->readSecurityBuffer($data[$i - 1]); - - $data[$i++] = substr($message, 88, 16); - list($workLength, $workOffset) = $this->readSecurityBuffer($data[$i - 1]); - - $data[$i++] = substr($message, 104, 16); - $data[$i++] = substr($message, 120, 8); - $data[$i++] = substr($message, $targetOffset, $targetLength); - $data[$i++] = substr($message, $userOffset, $userLength); - $data[$i++] = substr($message, $workOffset, $workLength); - $data[$i++] = substr($message, $lmOffset, $lmLength); - $data[$i] = substr($message, $ntmlOffset, $ntmlLength); - - $map = array( - 'LM Response Security Buffer', - 'NTLM Response Security Buffer', - 'Target Name Security Buffer', - 'User Name Security Buffer', - 'Workstation Name Security Buffer', - 'Session Key Security Buffer', - 'Flags', - 'Target Name Data', - 'User Name Data', - 'Workstation Name Data', - 'LM Response Data', - 'NTLM Response Data', - ); - - foreach ($map as $key => $value) { - echo $data[$key].' - '.$this->hex2bin($data[$key]).' ||| '.$value."
\n"; - } - } - - echo '

'; - } -} diff --git a/lib/swiftmailer/swiftmailer/lib/classes/Swift/Transport/Esmtp/Auth/PlainAuthenticator.php b/lib/swiftmailer/swiftmailer/lib/classes/Swift/Transport/Esmtp/Auth/PlainAuthenticator.php deleted file mode 100644 index 43219f934..000000000 --- a/lib/swiftmailer/swiftmailer/lib/classes/Swift/Transport/Esmtp/Auth/PlainAuthenticator.php +++ /dev/null @@ -1,50 +0,0 @@ -executeCommand(sprintf("AUTH PLAIN %s\r\n", $message), array(235)); - - return true; - } catch (Swift_TransportException $e) { - $agent->executeCommand("RSET\r\n", array(250)); - - return false; - } - } -} diff --git a/lib/swiftmailer/swiftmailer/lib/classes/Swift/Transport/Esmtp/Auth/XOAuth2Authenticator.php b/lib/swiftmailer/swiftmailer/lib/classes/Swift/Transport/Esmtp/Auth/XOAuth2Authenticator.php deleted file mode 100644 index ca35e7b83..000000000 --- a/lib/swiftmailer/swiftmailer/lib/classes/Swift/Transport/Esmtp/Auth/XOAuth2Authenticator.php +++ /dev/null @@ -1,70 +0,0 @@ - - * $transport = Swift_SmtpTransport::newInstance('smtp.gmail.com', 587, 'tls') - * ->setAuthMode('XOAUTH2') - * ->setUsername('YOUR_EMAIL_ADDRESS') - * ->setPassword('YOUR_ACCESS_TOKEN'); - * - * - * @author xu.li - * - * @see https://developers.google.com/google-apps/gmail/xoauth2_protocol - */ -class Swift_Transport_Esmtp_Auth_XOAuth2Authenticator implements Swift_Transport_Esmtp_Authenticator -{ - /** - * Get the name of the AUTH mechanism this Authenticator handles. - * - * @return string - */ - public function getAuthKeyword() - { - return 'XOAUTH2'; - } - - /** - * Try to authenticate the user with $email and $token. - * - * @param Swift_Transport_SmtpAgent $agent - * @param string $email - * @param string $token - * - * @return bool - */ - public function authenticate(Swift_Transport_SmtpAgent $agent, $email, $token) - { - try { - $param = $this->constructXOAuth2Params($email, $token); - $agent->executeCommand('AUTH XOAUTH2 '.$param."\r\n", array(235)); - - return true; - } catch (Swift_TransportException $e) { - $agent->executeCommand("RSET\r\n", array(250)); - - return false; - } - } - - /** - * Construct the auth parameter. - * - * @see https://developers.google.com/google-apps/gmail/xoauth2_protocol#the_sasl_xoauth2_mechanism - */ - protected function constructXOAuth2Params($email, $token) - { - return base64_encode("user=$email\1auth=Bearer $token\1\1"); - } -} diff --git a/lib/swiftmailer/swiftmailer/lib/classes/Swift/Transport/Esmtp/AuthHandler.php b/lib/swiftmailer/swiftmailer/lib/classes/Swift/Transport/Esmtp/AuthHandler.php deleted file mode 100644 index cb36133c9..000000000 --- a/lib/swiftmailer/swiftmailer/lib/classes/Swift/Transport/Esmtp/AuthHandler.php +++ /dev/null @@ -1,263 +0,0 @@ -setAuthenticators($authenticators); - } - - /** - * Set the Authenticators which can process a login request. - * - * @param Swift_Transport_Esmtp_Authenticator[] $authenticators - */ - public function setAuthenticators(array $authenticators) - { - $this->_authenticators = $authenticators; - } - - /** - * Get the Authenticators which can process a login request. - * - * @return Swift_Transport_Esmtp_Authenticator[] - */ - public function getAuthenticators() - { - return $this->_authenticators; - } - - /** - * Set the username to authenticate with. - * - * @param string $username - */ - public function setUsername($username) - { - $this->_username = $username; - } - - /** - * Get the username to authenticate with. - * - * @return string - */ - public function getUsername() - { - return $this->_username; - } - - /** - * Set the password to authenticate with. - * - * @param string $password - */ - public function setPassword($password) - { - $this->_password = $password; - } - - /** - * Get the password to authenticate with. - * - * @return string - */ - public function getPassword() - { - return $this->_password; - } - - /** - * Set the auth mode to use to authenticate. - * - * @param string $mode - */ - public function setAuthMode($mode) - { - $this->_auth_mode = $mode; - } - - /** - * Get the auth mode to use to authenticate. - * - * @return string - */ - public function getAuthMode() - { - return $this->_auth_mode; - } - - /** - * Get the name of the ESMTP extension this handles. - * - * @return bool - */ - public function getHandledKeyword() - { - return 'AUTH'; - } - - /** - * Set the parameters which the EHLO greeting indicated. - * - * @param string[] $parameters - */ - public function setKeywordParams(array $parameters) - { - $this->_esmtpParams = $parameters; - } - - /** - * Runs immediately after a EHLO has been issued. - * - * @param Swift_Transport_SmtpAgent $agent to read/write - */ - public function afterEhlo(Swift_Transport_SmtpAgent $agent) - { - if ($this->_username) { - $count = 0; - foreach ($this->_getAuthenticatorsForAgent() as $authenticator) { - if (in_array(strtolower($authenticator->getAuthKeyword()), - array_map('strtolower', $this->_esmtpParams))) { - ++$count; - if ($authenticator->authenticate($agent, $this->_username, $this->_password)) { - return; - } - } - } - throw new Swift_TransportException( - 'Failed to authenticate on SMTP server with username "'. - $this->_username.'" using '.$count.' possible authenticators' - ); - } - } - - /** - * Not used. - */ - public function getMailParams() - { - return array(); - } - - /** - * Not used. - */ - public function getRcptParams() - { - return array(); - } - - /** - * Not used. - */ - public function onCommand(Swift_Transport_SmtpAgent $agent, $command, $codes = array(), &$failedRecipients = null, &$stop = false) - { - } - - /** - * Returns +1, -1 or 0 according to the rules for usort(). - * - * This method is called to ensure extensions can be execute in an appropriate order. - * - * @param string $esmtpKeyword to compare with - * - * @return int - */ - public function getPriorityOver($esmtpKeyword) - { - return 0; - } - - /** - * Returns an array of method names which are exposed to the Esmtp class. - * - * @return string[] - */ - public function exposeMixinMethods() - { - return array('setUsername', 'getUsername', 'setPassword', 'getPassword', 'setAuthMode', 'getAuthMode'); - } - - /** - * Not used. - */ - public function resetState() - { - } - - /** - * Returns the authenticator list for the given agent. - * - * @param Swift_Transport_SmtpAgent $agent - * - * @return array - */ - protected function _getAuthenticatorsForAgent() - { - if (!$mode = strtolower($this->_auth_mode)) { - return $this->_authenticators; - } - - foreach ($this->_authenticators as $authenticator) { - if (strtolower($authenticator->getAuthKeyword()) == $mode) { - return array($authenticator); - } - } - - throw new Swift_TransportException('Auth mode '.$mode.' is invalid'); - } -} diff --git a/lib/swiftmailer/swiftmailer/lib/classes/Swift/Transport/Esmtp/Authenticator.php b/lib/swiftmailer/swiftmailer/lib/classes/Swift/Transport/Esmtp/Authenticator.php deleted file mode 100644 index 12a9abf81..000000000 --- a/lib/swiftmailer/swiftmailer/lib/classes/Swift/Transport/Esmtp/Authenticator.php +++ /dev/null @@ -1,35 +0,0 @@ -. - * - * @return string[] - */ - public function getMailParams(); - - /** - * Get params which are appended to RCPT TO:<>. - * - * @return string[] - */ - public function getRcptParams(); - - /** - * Runs when a command is due to be sent. - * - * @param Swift_Transport_SmtpAgent $agent to read/write - * @param string $command to send - * @param int[] $codes expected in response - * @param string[] $failedRecipients to collect failures - * @param bool $stop to be set true by-reference if the command is now sent - */ - public function onCommand(Swift_Transport_SmtpAgent $agent, $command, $codes = array(), &$failedRecipients = null, &$stop = false); - - /** - * Returns +1, -1 or 0 according to the rules for usort(). - * - * This method is called to ensure extensions can be execute in an appropriate order. - * - * @param string $esmtpKeyword to compare with - * - * @return int - */ - public function getPriorityOver($esmtpKeyword); - - /** - * Returns an array of method names which are exposed to the Esmtp class. - * - * @return string[] - */ - public function exposeMixinMethods(); - - /** - * Tells this handler to clear any buffers and reset its state. - */ - public function resetState(); -} diff --git a/lib/swiftmailer/swiftmailer/lib/classes/Swift/Transport/EsmtpTransport.php b/lib/swiftmailer/swiftmailer/lib/classes/Swift/Transport/EsmtpTransport.php deleted file mode 100644 index 156e2cf5b..000000000 --- a/lib/swiftmailer/swiftmailer/lib/classes/Swift/Transport/EsmtpTransport.php +++ /dev/null @@ -1,411 +0,0 @@ - 'tcp', - 'host' => 'localhost', - 'port' => 25, - 'timeout' => 30, - 'blocking' => 1, - 'tls' => false, - 'type' => Swift_Transport_IoBuffer::TYPE_SOCKET, - 'stream_context_options' => array(), - ); - - /** - * Creates a new EsmtpTransport using the given I/O buffer. - * - * @param Swift_Transport_IoBuffer $buf - * @param Swift_Transport_EsmtpHandler[] $extensionHandlers - * @param Swift_Events_EventDispatcher $dispatcher - */ - public function __construct(Swift_Transport_IoBuffer $buf, array $extensionHandlers, Swift_Events_EventDispatcher $dispatcher) - { - parent::__construct($buf, $dispatcher); - $this->setExtensionHandlers($extensionHandlers); - } - - /** - * Set the host to connect to. - * - * @param string $host - * - * @return $this - */ - public function setHost($host) - { - $this->_params['host'] = $host; - - return $this; - } - - /** - * Get the host to connect to. - * - * @return string - */ - public function getHost() - { - return $this->_params['host']; - } - - /** - * Set the port to connect to. - * - * @param int $port - * - * @return $this - */ - public function setPort($port) - { - $this->_params['port'] = (int) $port; - - return $this; - } - - /** - * Get the port to connect to. - * - * @return int - */ - public function getPort() - { - return $this->_params['port']; - } - - /** - * Set the connection timeout. - * - * @param int $timeout seconds - * - * @return $this - */ - public function setTimeout($timeout) - { - $this->_params['timeout'] = (int) $timeout; - $this->_buffer->setParam('timeout', (int) $timeout); - - return $this; - } - - /** - * Get the connection timeout. - * - * @return int - */ - public function getTimeout() - { - return $this->_params['timeout']; - } - - /** - * Set the encryption type (tls or ssl). - * - * @param string $encryption - * - * @return $this - */ - public function setEncryption($encryption) - { - $encryption = strtolower($encryption); - if ('tls' == $encryption) { - $this->_params['protocol'] = 'tcp'; - $this->_params['tls'] = true; - } else { - $this->_params['protocol'] = $encryption; - $this->_params['tls'] = false; - } - - return $this; - } - - /** - * Get the encryption type. - * - * @return string - */ - public function getEncryption() - { - return $this->_params['tls'] ? 'tls' : $this->_params['protocol']; - } - - /** - * Sets the stream context options. - * - * @param array $options - * - * @return $this - */ - public function setStreamOptions($options) - { - $this->_params['stream_context_options'] = $options; - - return $this; - } - - /** - * Returns the stream context options. - * - * @return array - */ - public function getStreamOptions() - { - return $this->_params['stream_context_options']; - } - - /** - * Sets the source IP. - * - * @param string $source - * - * @return $this - */ - public function setSourceIp($source) - { - $this->_params['sourceIp'] = $source; - - return $this; - } - - /** - * Returns the IP used to connect to the destination. - * - * @return string - */ - public function getSourceIp() - { - return isset($this->_params['sourceIp']) ? $this->_params['sourceIp'] : null; - } - - /** - * Set ESMTP extension handlers. - * - * @param Swift_Transport_EsmtpHandler[] $handlers - * - * @return $this - */ - public function setExtensionHandlers(array $handlers) - { - $assoc = array(); - foreach ($handlers as $handler) { - $assoc[$handler->getHandledKeyword()] = $handler; - } - - @uasort($assoc, array($this, '_sortHandlers')); - $this->_handlers = $assoc; - $this->_setHandlerParams(); - - return $this; - } - - /** - * Get ESMTP extension handlers. - * - * @return Swift_Transport_EsmtpHandler[] - */ - public function getExtensionHandlers() - { - return array_values($this->_handlers); - } - - /** - * Run a command against the buffer, expecting the given response codes. - * - * If no response codes are given, the response will not be validated. - * If codes are given, an exception will be thrown on an invalid response. - * - * @param string $command - * @param int[] $codes - * @param string[] $failures An array of failures by-reference - * - * @return string - */ - public function executeCommand($command, $codes = array(), &$failures = null) - { - $failures = (array) $failures; - $stopSignal = false; - $response = null; - foreach ($this->_getActiveHandlers() as $handler) { - $response = $handler->onCommand( - $this, $command, $codes, $failures, $stopSignal - ); - if ($stopSignal) { - return $response; - } - } - - return parent::executeCommand($command, $codes, $failures); - } - - /** Mixin handling method for ESMTP handlers */ - public function __call($method, $args) - { - foreach ($this->_handlers as $handler) { - if (in_array(strtolower($method), - array_map('strtolower', (array) $handler->exposeMixinMethods()) - )) { - $return = call_user_func_array(array($handler, $method), $args); - // Allow fluid method calls - if (null === $return && substr($method, 0, 3) == 'set') { - return $this; - } else { - return $return; - } - } - } - trigger_error('Call to undefined method '.$method, E_USER_ERROR); - } - - /** Get the params to initialize the buffer */ - protected function _getBufferParams() - { - return $this->_params; - } - - /** Overridden to perform EHLO instead */ - protected function _doHeloCommand() - { - try { - $response = $this->executeCommand( - sprintf("EHLO %s\r\n", $this->_domain), array(250) - ); - } catch (Swift_TransportException $e) { - return parent::_doHeloCommand(); - } - - if ($this->_params['tls']) { - try { - $this->executeCommand("STARTTLS\r\n", array(220)); - - if (!$this->_buffer->startTLS()) { - throw new Swift_TransportException('Unable to connect with TLS encryption'); - } - - try { - $response = $this->executeCommand( - sprintf("EHLO %s\r\n", $this->_domain), array(250) - ); - } catch (Swift_TransportException $e) { - return parent::_doHeloCommand(); - } - } catch (Swift_TransportException $e) { - $this->_throwException($e); - } - } - - $this->_capabilities = $this->_getCapabilities($response); - $this->_setHandlerParams(); - foreach ($this->_getActiveHandlers() as $handler) { - $handler->afterEhlo($this); - } - } - - /** Overridden to add Extension support */ - protected function _doMailFromCommand($address) - { - $handlers = $this->_getActiveHandlers(); - $params = array(); - foreach ($handlers as $handler) { - $params = array_merge($params, (array) $handler->getMailParams()); - } - $paramStr = !empty($params) ? ' '.implode(' ', $params) : ''; - $this->executeCommand( - sprintf("MAIL FROM:<%s>%s\r\n", $address, $paramStr), array(250) - ); - } - - /** Overridden to add Extension support */ - protected function _doRcptToCommand($address) - { - $handlers = $this->_getActiveHandlers(); - $params = array(); - foreach ($handlers as $handler) { - $params = array_merge($params, (array) $handler->getRcptParams()); - } - $paramStr = !empty($params) ? ' '.implode(' ', $params) : ''; - $this->executeCommand( - sprintf("RCPT TO:<%s>%s\r\n", $address, $paramStr), array(250, 251, 252) - ); - } - - /** Determine ESMTP capabilities by function group */ - private function _getCapabilities($ehloResponse) - { - $capabilities = array(); - $ehloResponse = trim($ehloResponse); - $lines = explode("\r\n", $ehloResponse); - array_shift($lines); - foreach ($lines as $line) { - if (preg_match('/^[0-9]{3}[ -]([A-Z0-9-]+)((?:[ =].*)?)$/Di', $line, $matches)) { - $keyword = strtoupper($matches[1]); - $paramStr = strtoupper(ltrim($matches[2], ' =')); - $params = !empty($paramStr) ? explode(' ', $paramStr) : array(); - $capabilities[$keyword] = $params; - } - } - - return $capabilities; - } - - /** Set parameters which are used by each extension handler */ - private function _setHandlerParams() - { - foreach ($this->_handlers as $keyword => $handler) { - if (array_key_exists($keyword, $this->_capabilities)) { - $handler->setKeywordParams($this->_capabilities[$keyword]); - } - } - } - - /** Get ESMTP handlers which are currently ok to use */ - private function _getActiveHandlers() - { - $handlers = array(); - foreach ($this->_handlers as $keyword => $handler) { - if (array_key_exists($keyword, $this->_capabilities)) { - $handlers[] = $handler; - } - } - - return $handlers; - } - - /** Custom sort for extension handler ordering */ - private function _sortHandlers($a, $b) - { - return $a->getPriorityOver($b->getHandledKeyword()); - } -} diff --git a/lib/swiftmailer/swiftmailer/lib/classes/Swift/Transport/FailoverTransport.php b/lib/swiftmailer/swiftmailer/lib/classes/Swift/Transport/FailoverTransport.php deleted file mode 100644 index 311a0f2ad..000000000 --- a/lib/swiftmailer/swiftmailer/lib/classes/Swift/Transport/FailoverTransport.php +++ /dev/null @@ -1,88 +0,0 @@ -_transports); - $sent = 0; - $this->_lastUsedTransport = null; - - for ($i = 0; $i < $maxTransports - && $transport = $this->_getNextTransport(); ++$i) { - try { - if (!$transport->isStarted()) { - $transport->start(); - } - - if ($sent = $transport->send($message, $failedRecipients)) { - $this->_lastUsedTransport = $transport; - - return $sent; - } - } catch (Swift_TransportException $e) { - $this->_killCurrentTransport(); - } - } - - if (count($this->_transports) == 0) { - throw new Swift_TransportException( - 'All Transports in FailoverTransport failed, or no Transports available' - ); - } - - return $sent; - } - - protected function _getNextTransport() - { - if (!isset($this->_currentTransport)) { - $this->_currentTransport = parent::_getNextTransport(); - } - - return $this->_currentTransport; - } - - protected function _killCurrentTransport() - { - $this->_currentTransport = null; - parent::_killCurrentTransport(); - } -} diff --git a/lib/swiftmailer/swiftmailer/lib/classes/Swift/Transport/IoBuffer.php b/lib/swiftmailer/swiftmailer/lib/classes/Swift/Transport/IoBuffer.php deleted file mode 100644 index af97adf1f..000000000 --- a/lib/swiftmailer/swiftmailer/lib/classes/Swift/Transport/IoBuffer.php +++ /dev/null @@ -1,67 +0,0 @@ -_transports = $transports; - $this->_deadTransports = array(); - } - - /** - * Get $transports to delegate to. - * - * @return Swift_Transport[] - */ - public function getTransports() - { - return array_merge($this->_transports, $this->_deadTransports); - } - - /** - * Get the Transport used in the last successful send operation. - * - * @return Swift_Transport - */ - public function getLastUsedTransport() - { - return $this->_lastUsedTransport; - } - - /** - * Test if this Transport mechanism has started. - * - * @return bool - */ - public function isStarted() - { - return count($this->_transports) > 0; - } - - /** - * Start this Transport mechanism. - */ - public function start() - { - $this->_transports = array_merge($this->_transports, $this->_deadTransports); - } - - /** - * Stop this Transport mechanism. - */ - public function stop() - { - foreach ($this->_transports as $transport) { - $transport->stop(); - } - } - - /** - * Send the given Message. - * - * Recipient/sender data will be retrieved from the Message API. - * The return value is the number of recipients who were accepted for delivery. - * - * @param Swift_Mime_Message $message - * @param string[] $failedRecipients An array of failures by-reference - * - * @return int - */ - public function send(Swift_Mime_Message $message, &$failedRecipients = null) - { - $maxTransports = count($this->_transports); - $sent = 0; - $this->_lastUsedTransport = null; - - for ($i = 0; $i < $maxTransports - && $transport = $this->_getNextTransport(); ++$i) { - try { - if (!$transport->isStarted()) { - $transport->start(); - } - if ($sent = $transport->send($message, $failedRecipients)) { - $this->_lastUsedTransport = $transport; - break; - } - } catch (Swift_TransportException $e) { - $this->_killCurrentTransport(); - } - } - - if (count($this->_transports) == 0) { - throw new Swift_TransportException( - 'All Transports in LoadBalancedTransport failed, or no Transports available' - ); - } - - return $sent; - } - - /** - * Register a plugin. - * - * @param Swift_Events_EventListener $plugin - */ - public function registerPlugin(Swift_Events_EventListener $plugin) - { - foreach ($this->_transports as $transport) { - $transport->registerPlugin($plugin); - } - } - - /** - * Rotates the transport list around and returns the first instance. - * - * @return Swift_Transport - */ - protected function _getNextTransport() - { - if ($next = array_shift($this->_transports)) { - $this->_transports[] = $next; - } - - return $next; - } - - /** - * Tag the currently used (top of stack) transport as dead/useless. - */ - protected function _killCurrentTransport() - { - if ($transport = array_pop($this->_transports)) { - try { - $transport->stop(); - } catch (Exception $e) { - } - $this->_deadTransports[] = $transport; - } - } -} diff --git a/lib/swiftmailer/swiftmailer/lib/classes/Swift/Transport/MailInvoker.php b/lib/swiftmailer/swiftmailer/lib/classes/Swift/Transport/MailInvoker.php deleted file mode 100644 index 77489cedc..000000000 --- a/lib/swiftmailer/swiftmailer/lib/classes/Swift/Transport/MailInvoker.php +++ /dev/null @@ -1,32 +0,0 @@ -_invoker = $invoker; - $this->_eventDispatcher = $eventDispatcher; - } - - /** - * Not used. - */ - public function isStarted() - { - return false; - } - - /** - * Not used. - */ - public function start() - { - } - - /** - * Not used. - */ - public function stop() - { - } - - /** - * Set the additional parameters used on the mail() function. - * - * This string is formatted for sprintf() where %s is the sender address. - * - * @param string $params - * - * @return $this - */ - public function setExtraParams($params) - { - $this->_extraParams = $params; - - return $this; - } - - /** - * Get the additional parameters used on the mail() function. - * - * This string is formatted for sprintf() where %s is the sender address. - * - * @return string - */ - public function getExtraParams() - { - return $this->_extraParams; - } - - /** - * Send the given Message. - * - * Recipient/sender data will be retrieved from the Message API. - * The return value is the number of recipients who were accepted for delivery. - * - * @param Swift_Mime_Message $message - * @param string[] $failedRecipients An array of failures by-reference - * - * @return int - */ - public function send(Swift_Mime_Message $message, &$failedRecipients = null) - { - $failedRecipients = (array) $failedRecipients; - - if ($evt = $this->_eventDispatcher->createSendEvent($this, $message)) { - $this->_eventDispatcher->dispatchEvent($evt, 'beforeSendPerformed'); - if ($evt->bubbleCancelled()) { - return 0; - } - } - - $count = ( - count((array) $message->getTo()) - + count((array) $message->getCc()) - + count((array) $message->getBcc()) - ); - - $toHeader = $message->getHeaders()->get('To'); - $subjectHeader = $message->getHeaders()->get('Subject'); - - if (0 === $count) { - $this->_throwException(new Swift_TransportException('Cannot send message without a recipient')); - } - $to = $toHeader ? $toHeader->getFieldBody() : ''; - $subject = $subjectHeader ? $subjectHeader->getFieldBody() : ''; - - $reversePath = $this->_getReversePath($message); - - // Remove headers that would otherwise be duplicated - $message->getHeaders()->remove('To'); - $message->getHeaders()->remove('Subject'); - - $messageStr = $message->toString(); - - if ($toHeader) { - $message->getHeaders()->set($toHeader); - } - $message->getHeaders()->set($subjectHeader); - - // Separate headers from body - if (false !== $endHeaders = strpos($messageStr, "\r\n\r\n")) { - $headers = substr($messageStr, 0, $endHeaders)."\r\n"; //Keep last EOL - $body = substr($messageStr, $endHeaders + 4); - } else { - $headers = $messageStr."\r\n"; - $body = ''; - } - - unset($messageStr); - - if ("\r\n" != PHP_EOL) { - // Non-windows (not using SMTP) - $headers = str_replace("\r\n", PHP_EOL, $headers); - $subject = str_replace("\r\n", PHP_EOL, $subject); - $body = str_replace("\r\n", PHP_EOL, $body); - $to = str_replace("\r\n", PHP_EOL, $to); - } else { - // Windows, using SMTP - $headers = str_replace("\r\n.", "\r\n..", $headers); - $subject = str_replace("\r\n.", "\r\n..", $subject); - $body = str_replace("\r\n.", "\r\n..", $body); - $to = str_replace("\r\n.", "\r\n..", $to); - } - - if ($this->_invoker->mail($to, $subject, $body, $headers, $this->_formatExtraParams($this->_extraParams, $reversePath))) { - if ($evt) { - $evt->setResult(Swift_Events_SendEvent::RESULT_SUCCESS); - $evt->setFailedRecipients($failedRecipients); - $this->_eventDispatcher->dispatchEvent($evt, 'sendPerformed'); - } - } else { - $failedRecipients = array_merge( - $failedRecipients, - array_keys((array) $message->getTo()), - array_keys((array) $message->getCc()), - array_keys((array) $message->getBcc()) - ); - - if ($evt) { - $evt->setResult(Swift_Events_SendEvent::RESULT_FAILED); - $evt->setFailedRecipients($failedRecipients); - $this->_eventDispatcher->dispatchEvent($evt, 'sendPerformed'); - } - - $message->generateId(); - - $count = 0; - } - - return $count; - } - - /** - * Register a plugin. - * - * @param Swift_Events_EventListener $plugin - */ - public function registerPlugin(Swift_Events_EventListener $plugin) - { - $this->_eventDispatcher->bindEventListener($plugin); - } - - /** Throw a TransportException, first sending it to any listeners */ - protected function _throwException(Swift_TransportException $e) - { - if ($evt = $this->_eventDispatcher->createTransportExceptionEvent($this, $e)) { - $this->_eventDispatcher->dispatchEvent($evt, 'exceptionThrown'); - if (!$evt->bubbleCancelled()) { - throw $e; - } - } else { - throw $e; - } - } - - /** Determine the best-use reverse path for this message */ - private function _getReversePath(Swift_Mime_Message $message) - { - $return = $message->getReturnPath(); - $sender = $message->getSender(); - $from = $message->getFrom(); - $path = null; - if (!empty($return)) { - $path = $return; - } elseif (!empty($sender)) { - $keys = array_keys($sender); - $path = array_shift($keys); - } elseif (!empty($from)) { - $keys = array_keys($from); - $path = array_shift($keys); - } - - return $path; - } - - /** - * Fix CVE-2016-10074 by disallowing potentially unsafe shell characters. - * - * Note that escapeshellarg and escapeshellcmd are inadequate for our purposes, especially on Windows. - * - * @param string $string The string to be validated - * - * @return bool - */ - private function _isShellSafe($string) - { - // Future-proof - if (escapeshellcmd($string) !== $string || !in_array(escapeshellarg($string), array("'$string'", "\"$string\""))) { - return false; - } - - $length = strlen($string); - for ($i = 0; $i < $length; ++$i) { - $c = $string[$i]; - // All other characters have a special meaning in at least one common shell, including = and +. - // Full stop (.) has a special meaning in cmd.exe, but its impact should be negligible here. - // Note that this does permit non-Latin alphanumeric characters based on the current locale. - if (!ctype_alnum($c) && strpos('@_-.', $c) === false) { - return false; - } - } - - return true; - } - - /** - * Return php mail extra params to use for invoker->mail. - * - * @param $extraParams - * @param $reversePath - * - * @return string|null - */ - private function _formatExtraParams($extraParams, $reversePath) - { - if (false !== strpos($extraParams, '-f%s')) { - if (empty($reversePath) || false === $this->_isShellSafe($reversePath)) { - $extraParams = str_replace('-f%s', '', $extraParams); - } else { - $extraParams = sprintf($extraParams, $reversePath); - } - } - - return !empty($extraParams) ? $extraParams : null; - } -} diff --git a/lib/swiftmailer/swiftmailer/lib/classes/Swift/Transport/NullTransport.php b/lib/swiftmailer/swiftmailer/lib/classes/Swift/Transport/NullTransport.php deleted file mode 100644 index ad20e0e53..000000000 --- a/lib/swiftmailer/swiftmailer/lib/classes/Swift/Transport/NullTransport.php +++ /dev/null @@ -1,93 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -/** - * Pretends messages have been sent, but just ignores them. - * - * @author Fabien Potencier - */ -class Swift_Transport_NullTransport implements Swift_Transport -{ - /** The event dispatcher from the plugin API */ - private $_eventDispatcher; - - /** - * Constructor. - */ - public function __construct(Swift_Events_EventDispatcher $eventDispatcher) - { - $this->_eventDispatcher = $eventDispatcher; - } - - /** - * Tests if this Transport mechanism has started. - * - * @return bool - */ - public function isStarted() - { - return true; - } - - /** - * Starts this Transport mechanism. - */ - public function start() - { - } - - /** - * Stops this Transport mechanism. - */ - public function stop() - { - } - - /** - * 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) - { - if ($evt = $this->_eventDispatcher->createSendEvent($this, $message)) { - $this->_eventDispatcher->dispatchEvent($evt, 'beforeSendPerformed'); - if ($evt->bubbleCancelled()) { - return 0; - } - } - - if ($evt) { - $evt->setResult(Swift_Events_SendEvent::RESULT_SUCCESS); - $this->_eventDispatcher->dispatchEvent($evt, 'sendPerformed'); - } - - $count = ( - count((array) $message->getTo()) - + count((array) $message->getCc()) - + count((array) $message->getBcc()) - ); - - return $count; - } - - /** - * Register a plugin. - * - * @param Swift_Events_EventListener $plugin - */ - public function registerPlugin(Swift_Events_EventListener $plugin) - { - $this->_eventDispatcher->bindEventListener($plugin); - } -} diff --git a/lib/swiftmailer/swiftmailer/lib/classes/Swift/Transport/SendmailTransport.php b/lib/swiftmailer/swiftmailer/lib/classes/Swift/Transport/SendmailTransport.php deleted file mode 100644 index 6430d5f6b..000000000 --- a/lib/swiftmailer/swiftmailer/lib/classes/Swift/Transport/SendmailTransport.php +++ /dev/null @@ -1,160 +0,0 @@ - 30, - 'blocking' => 1, - 'command' => '/usr/sbin/sendmail -bs', - 'type' => Swift_Transport_IoBuffer::TYPE_PROCESS, - ); - - /** - * Create a new SendmailTransport with $buf for I/O. - * - * @param Swift_Transport_IoBuffer $buf - * @param Swift_Events_EventDispatcher $dispatcher - */ - public function __construct(Swift_Transport_IoBuffer $buf, Swift_Events_EventDispatcher $dispatcher) - { - parent::__construct($buf, $dispatcher); - } - - /** - * Start the standalone SMTP session if running in -bs mode. - */ - public function start() - { - if (false !== strpos($this->getCommand(), ' -bs')) { - parent::start(); - } - } - - /** - * Set the command to invoke. - * - * If using -t mode you are strongly advised to include -oi or -i in the flags. - * For example: /usr/sbin/sendmail -oi -t - * Swift will append a -f flag if one is not present. - * - * The recommended mode is "-bs" since it is interactive and failure notifications - * are hence possible. - * - * @param string $command - * - * @return $this - */ - public function setCommand($command) - { - $this->_params['command'] = $command; - - return $this; - } - - /** - * Get the sendmail command which will be invoked. - * - * @return string - */ - public function getCommand() - { - return $this->_params['command']; - } - - /** - * Send the given Message. - * - * Recipient/sender data will be retrieved from the Message API. - * - * The return value is the number of recipients who were accepted for delivery. - * NOTE: If using 'sendmail -t' you will not be aware of any failures until - * they bounce (i.e. send() will always return 100% success). - * - * @param Swift_Mime_Message $message - * @param string[] $failedRecipients An array of failures by-reference - * - * @return int - */ - public function send(Swift_Mime_Message $message, &$failedRecipients = null) - { - $failedRecipients = (array) $failedRecipients; - $command = $this->getCommand(); - $buffer = $this->getBuffer(); - $count = 0; - - if (false !== strpos($command, ' -t')) { - if ($evt = $this->_eventDispatcher->createSendEvent($this, $message)) { - $this->_eventDispatcher->dispatchEvent($evt, 'beforeSendPerformed'); - if ($evt->bubbleCancelled()) { - return 0; - } - } - - if (false === strpos($command, ' -f')) { - $command .= ' -f'.escapeshellarg($this->_getReversePath($message)); - } - - $buffer->initialize(array_merge($this->_params, array('command' => $command))); - - if (false === strpos($command, ' -i') && false === strpos($command, ' -oi')) { - $buffer->setWriteTranslations(array("\r\n" => "\n", "\n." => "\n..")); - } else { - $buffer->setWriteTranslations(array("\r\n" => "\n")); - } - - $count = count((array) $message->getTo()) - + count((array) $message->getCc()) - + count((array) $message->getBcc()) - ; - $message->toByteStream($buffer); - $buffer->flushBuffers(); - $buffer->setWriteTranslations(array()); - $buffer->terminate(); - - if ($evt) { - $evt->setResult(Swift_Events_SendEvent::RESULT_SUCCESS); - $evt->setFailedRecipients($failedRecipients); - $this->_eventDispatcher->dispatchEvent($evt, 'sendPerformed'); - } - - $message->generateId(); - } elseif (false !== strpos($command, ' -bs')) { - $count = parent::send($message, $failedRecipients); - } else { - $this->_throwException(new Swift_TransportException( - 'Unsupported sendmail command flags ['.$command.']. '. - 'Must be one of "-bs" or "-t" but can include additional flags.' - )); - } - - return $count; - } - - /** Get the params to initialize the buffer */ - protected function _getBufferParams() - { - return $this->_params; - } -} diff --git a/lib/swiftmailer/swiftmailer/lib/classes/Swift/Transport/SimpleMailInvoker.php b/lib/swiftmailer/swiftmailer/lib/classes/Swift/Transport/SimpleMailInvoker.php deleted file mode 100644 index 4cab66bd6..000000000 --- a/lib/swiftmailer/swiftmailer/lib/classes/Swift/Transport/SimpleMailInvoker.php +++ /dev/null @@ -1,39 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -/** - * Stores Messages in a queue. - * - * @author Fabien Potencier - */ -class Swift_Transport_SpoolTransport implements Swift_Transport -{ - /** The spool instance */ - private $_spool; - - /** The event dispatcher from the plugin API */ - private $_eventDispatcher; - - /** - * Constructor. - */ - public function __construct(Swift_Events_EventDispatcher $eventDispatcher, Swift_Spool $spool = null) - { - $this->_eventDispatcher = $eventDispatcher; - $this->_spool = $spool; - } - - /** - * Sets the spool object. - * - * @param Swift_Spool $spool - * - * @return $this - */ - public function setSpool(Swift_Spool $spool) - { - $this->_spool = $spool; - - return $this; - } - - /** - * Get the spool object. - * - * @return Swift_Spool - */ - public function getSpool() - { - return $this->_spool; - } - - /** - * Tests if this Transport mechanism has started. - * - * @return bool - */ - public function isStarted() - { - return true; - } - - /** - * Starts this Transport mechanism. - */ - public function start() - { - } - - /** - * Stops this Transport mechanism. - */ - public function stop() - { - } - - /** - * Sends the given message. - * - * @param Swift_Mime_Message $message - * @param string[] $failedRecipients An array of failures by-reference - * - * @return int The number of sent e-mail's - */ - public function send(Swift_Mime_Message $message, &$failedRecipients = null) - { - if ($evt = $this->_eventDispatcher->createSendEvent($this, $message)) { - $this->_eventDispatcher->dispatchEvent($evt, 'beforeSendPerformed'); - if ($evt->bubbleCancelled()) { - return 0; - } - } - - $success = $this->_spool->queueMessage($message); - - if ($evt) { - $evt->setResult($success ? Swift_Events_SendEvent::RESULT_SPOOLED : Swift_Events_SendEvent::RESULT_FAILED); - $this->_eventDispatcher->dispatchEvent($evt, 'sendPerformed'); - } - - return 1; - } - - /** - * Register a plugin. - * - * @param Swift_Events_EventListener $plugin - */ - public function registerPlugin(Swift_Events_EventListener $plugin) - { - $this->_eventDispatcher->bindEventListener($plugin); - } -} diff --git a/lib/swiftmailer/swiftmailer/lib/classes/Swift/Transport/StreamBuffer.php b/lib/swiftmailer/swiftmailer/lib/classes/Swift/Transport/StreamBuffer.php deleted file mode 100644 index 3a9fe76b2..000000000 --- a/lib/swiftmailer/swiftmailer/lib/classes/Swift/Transport/StreamBuffer.php +++ /dev/null @@ -1,334 +0,0 @@ -_replacementFactory = $replacementFactory; - } - - /** - * Perform any initialization needed, using the given $params. - * - * Parameters will vary depending upon the type of IoBuffer used. - * - * @param array $params - */ - public function initialize(array $params) - { - $this->_params = $params; - switch ($params['type']) { - case self::TYPE_PROCESS: - $this->_establishProcessConnection(); - break; - case self::TYPE_SOCKET: - default: - $this->_establishSocketConnection(); - break; - } - } - - /** - * Set an individual param on the buffer (e.g. switching to SSL). - * - * @param string $param - * @param mixed $value - */ - public function setParam($param, $value) - { - if (isset($this->_stream)) { - switch ($param) { - case 'timeout': - if ($this->_stream) { - stream_set_timeout($this->_stream, $value); - } - break; - - case 'blocking': - if ($this->_stream) { - stream_set_blocking($this->_stream, 1); - } - } - } - $this->_params[$param] = $value; - } - - public function startTLS() - { - // STREAM_CRYPTO_METHOD_TLS_CLIENT only allow tls1.0 connections (some php versions) - // To support modern tls we allow explicit tls1.0, tls1.1, tls1.2 - // Ssl3 and older are not allowed because they are vulnerable - // @TODO make tls arguments configurable - $cryptoType = STREAM_CRYPTO_METHOD_TLS_CLIENT; - if (PHP_VERSION_ID >= 50600) { - $cryptoType = STREAM_CRYPTO_METHOD_TLSv1_0_CLIENT | STREAM_CRYPTO_METHOD_TLSv1_1_CLIENT | STREAM_CRYPTO_METHOD_TLSv1_2_CLIENT; - } - - return stream_socket_enable_crypto($this->_stream, true, $cryptoType); - } - - /** - * Perform any shutdown logic needed. - */ - public function terminate() - { - if (isset($this->_stream)) { - switch ($this->_params['type']) { - case self::TYPE_PROCESS: - fclose($this->_in); - fclose($this->_out); - proc_close($this->_stream); - break; - case self::TYPE_SOCKET: - default: - fclose($this->_stream); - break; - } - } - $this->_stream = null; - $this->_out = null; - $this->_in = null; - } - - /** - * Set an array of string replacements which should be made on data written - * to the buffer. - * - * This could replace LF with CRLF for example. - * - * @param string[] $replacements - */ - public function setWriteTranslations(array $replacements) - { - foreach ($this->_translations as $search => $replace) { - if (!isset($replacements[$search])) { - $this->removeFilter($search); - unset($this->_translations[$search]); - } - } - - foreach ($replacements as $search => $replace) { - if (!isset($this->_translations[$search])) { - $this->addFilter( - $this->_replacementFactory->createFilter($search, $replace), $search - ); - $this->_translations[$search] = true; - } - } - } - - /** - * Get a line of output (including any CRLF). - * - * The $sequence number comes from any writes and may or may not be used - * depending upon the implementation. - * - * @param int $sequence of last write to scan from - * - * @throws Swift_IoException - * - * @return string - */ - public function readLine($sequence) - { - if (isset($this->_out) && !feof($this->_out)) { - $line = fgets($this->_out); - if (strlen($line) == 0) { - $metas = stream_get_meta_data($this->_out); - if ($metas['timed_out']) { - throw new Swift_IoException( - 'Connection to '. - $this->_getReadConnectionDescription(). - ' Timed Out' - ); - } - } - - return $line; - } - } - - /** - * Reads $length bytes from the stream into a string and moves the pointer - * through the stream by $length. - * - * If less bytes exist than are requested the remaining bytes are given instead. - * If no bytes are remaining at all, boolean false is returned. - * - * @param int $length - * - * @throws Swift_IoException - * - * @return string|bool - */ - public function read($length) - { - if (isset($this->_out) && !feof($this->_out)) { - $ret = fread($this->_out, $length); - if (strlen($ret) == 0) { - $metas = stream_get_meta_data($this->_out); - if ($metas['timed_out']) { - throw new Swift_IoException( - 'Connection to '. - $this->_getReadConnectionDescription(). - ' Timed Out' - ); - } - } - - return $ret; - } - } - - /** Not implemented */ - public function setReadPointer($byteOffset) - { - } - - /** Flush the stream contents */ - protected function _flush() - { - if (isset($this->_in)) { - fflush($this->_in); - } - } - - /** Write this bytes to the stream */ - protected function _commit($bytes) - { - if (isset($this->_in)) { - $bytesToWrite = strlen($bytes); - $totalBytesWritten = 0; - - while ($totalBytesWritten < $bytesToWrite) { - $bytesWritten = fwrite($this->_in, substr($bytes, $totalBytesWritten)); - if (false === $bytesWritten || 0 === $bytesWritten) { - break; - } - - $totalBytesWritten += $bytesWritten; - } - - if ($totalBytesWritten > 0) { - return ++$this->_sequence; - } - } - } - - /** - * Establishes a connection to a remote server. - */ - private function _establishSocketConnection() - { - $host = $this->_params['host']; - if (!empty($this->_params['protocol'])) { - $host = $this->_params['protocol'].'://'.$host; - } - $timeout = 15; - if (!empty($this->_params['timeout'])) { - $timeout = $this->_params['timeout']; - } - $options = array(); - if (!empty($this->_params['sourceIp'])) { - $options['socket']['bindto'] = $this->_params['sourceIp'].':0'; - } - if (isset($this->_params['stream_context_options'])) { - $options = array_merge($options, $this->_params['stream_context_options']); - } - $streamContext = stream_context_create($options); - $this->_stream = @stream_socket_client($host.':'.$this->_params['port'], $errno, $errstr, $timeout, STREAM_CLIENT_CONNECT, $streamContext); - if (false === $this->_stream) { - throw new Swift_TransportException( - 'Connection could not be established with host '.$this->_params['host']. - ' ['.$errstr.' #'.$errno.']' - ); - } - if (!empty($this->_params['blocking'])) { - stream_set_blocking($this->_stream, 1); - } else { - stream_set_blocking($this->_stream, 0); - } - stream_set_timeout($this->_stream, $timeout); - $this->_in = &$this->_stream; - $this->_out = &$this->_stream; - } - - /** - * Opens a process for input/output. - */ - private function _establishProcessConnection() - { - $command = $this->_params['command']; - $descriptorSpec = array( - 0 => array('pipe', 'r'), - 1 => array('pipe', 'w'), - 2 => array('pipe', 'w'), - ); - $pipes = array(); - $this->_stream = proc_open($command, $descriptorSpec, $pipes); - stream_set_blocking($pipes[2], 0); - if ($err = stream_get_contents($pipes[2])) { - throw new Swift_TransportException( - 'Process could not be started ['.$err.']' - ); - } - $this->_in = &$pipes[0]; - $this->_out = &$pipes[1]; - } - - private function _getReadConnectionDescription() - { - switch ($this->_params['type']) { - case self::TYPE_PROCESS: - return 'Process '.$this->_params['command']; - break; - - case self::TYPE_SOCKET: - default: - $host = $this->_params['host']; - if (!empty($this->_params['protocol'])) { - $host = $this->_params['protocol'].'://'.$host; - } - $host .= ':'.$this->_params['port']; - - return $host; - break; - } - } -} diff --git a/lib/swiftmailer/swiftmailer/lib/classes/Swift/TransportException.php b/lib/swiftmailer/swiftmailer/lib/classes/Swift/TransportException.php deleted file mode 100644 index 4ae2412e6..000000000 --- a/lib/swiftmailer/swiftmailer/lib/classes/Swift/TransportException.php +++ /dev/null @@ -1,29 +0,0 @@ - - */ -class Swift_Validate -{ - /** - * Grammar Object. - * - * @var Swift_Mime_Grammar - */ - private static $grammar = null; - - /** - * Checks if an e-mail address matches the current grammars. - * - * @param string $email - * - * @return bool - */ - public static function email($email) - { - if (self::$grammar === null) { - self::$grammar = Swift_DependencyContainer::getInstance() - ->lookup('mime.grammar'); - } - - return (bool) preg_match( - '/^'.self::$grammar->getDefinition('addr-spec').'$/D', - $email - ); - } -} diff --git a/lib/swiftmailer/swiftmailer/lib/dependency_maps/cache_deps.php b/lib/swiftmailer/swiftmailer/lib/dependency_maps/cache_deps.php deleted file mode 100644 index 6023448e8..000000000 --- a/lib/swiftmailer/swiftmailer/lib/dependency_maps/cache_deps.php +++ /dev/null @@ -1,23 +0,0 @@ -register('cache') - ->asAliasOf('cache.array') - - ->register('tempdir') - ->asValue('/tmp') - - ->register('cache.null') - ->asSharedInstanceOf('Swift_KeyCache_NullKeyCache') - - ->register('cache.array') - ->asSharedInstanceOf('Swift_KeyCache_ArrayKeyCache') - ->withDependencies(array('cache.inputstream')) - - ->register('cache.disk') - ->asSharedInstanceOf('Swift_KeyCache_DiskKeyCache') - ->withDependencies(array('cache.inputstream', 'tempdir')) - - ->register('cache.inputstream') - ->asNewInstanceOf('Swift_KeyCache_SimpleKeyCacheInputStream') -; diff --git a/lib/swiftmailer/swiftmailer/lib/dependency_maps/message_deps.php b/lib/swiftmailer/swiftmailer/lib/dependency_maps/message_deps.php deleted file mode 100644 index 64d69d215..000000000 --- a/lib/swiftmailer/swiftmailer/lib/dependency_maps/message_deps.php +++ /dev/null @@ -1,9 +0,0 @@ -register('message.message') - ->asNewInstanceOf('Swift_Message') - - ->register('message.mimepart') - ->asNewInstanceOf('Swift_MimePart') -; diff --git a/lib/swiftmailer/swiftmailer/lib/dependency_maps/mime_deps.php b/lib/swiftmailer/swiftmailer/lib/dependency_maps/mime_deps.php deleted file mode 100644 index d575e4f2d..000000000 --- a/lib/swiftmailer/swiftmailer/lib/dependency_maps/mime_deps.php +++ /dev/null @@ -1,123 +0,0 @@ -register('properties.charset') - ->asValue('utf-8') - - ->register('mime.grammar') - ->asSharedInstanceOf('Swift_Mime_Grammar') - - ->register('mime.message') - ->asNewInstanceOf('Swift_Mime_SimpleMessage') - ->withDependencies(array( - 'mime.headerset', - 'mime.qpcontentencoder', - 'cache', - 'mime.grammar', - 'properties.charset', - )) - - ->register('mime.part') - ->asNewInstanceOf('Swift_Mime_MimePart') - ->withDependencies(array( - 'mime.headerset', - 'mime.qpcontentencoder', - 'cache', - 'mime.grammar', - 'properties.charset', - )) - - ->register('mime.attachment') - ->asNewInstanceOf('Swift_Mime_Attachment') - ->withDependencies(array( - 'mime.headerset', - 'mime.base64contentencoder', - 'cache', - 'mime.grammar', - )) - ->addConstructorValue($swift_mime_types) - - ->register('mime.embeddedfile') - ->asNewInstanceOf('Swift_Mime_EmbeddedFile') - ->withDependencies(array( - 'mime.headerset', - 'mime.base64contentencoder', - 'cache', - 'mime.grammar', - )) - ->addConstructorValue($swift_mime_types) - - ->register('mime.headerfactory') - ->asNewInstanceOf('Swift_Mime_SimpleHeaderFactory') - ->withDependencies(array( - 'mime.qpheaderencoder', - 'mime.rfc2231encoder', - 'mime.grammar', - 'properties.charset', - )) - - ->register('mime.headerset') - ->asNewInstanceOf('Swift_Mime_SimpleHeaderSet') - ->withDependencies(array('mime.headerfactory', 'properties.charset')) - - ->register('mime.qpheaderencoder') - ->asNewInstanceOf('Swift_Mime_HeaderEncoder_QpHeaderEncoder') - ->withDependencies(array('mime.charstream')) - - ->register('mime.base64headerencoder') - ->asNewInstanceOf('Swift_Mime_HeaderEncoder_Base64HeaderEncoder') - ->withDependencies(array('mime.charstream')) - - ->register('mime.charstream') - ->asNewInstanceOf('Swift_CharacterStream_NgCharacterStream') - ->withDependencies(array('mime.characterreaderfactory', 'properties.charset')) - - ->register('mime.bytecanonicalizer') - ->asSharedInstanceOf('Swift_StreamFilters_ByteArrayReplacementFilter') - ->addConstructorValue(array(array(0x0D, 0x0A), array(0x0D), array(0x0A))) - ->addConstructorValue(array(array(0x0A), array(0x0A), array(0x0D, 0x0A))) - - ->register('mime.characterreaderfactory') - ->asSharedInstanceOf('Swift_CharacterReaderFactory_SimpleCharacterReaderFactory') - - ->register('mime.safeqpcontentencoder') - ->asNewInstanceOf('Swift_Mime_ContentEncoder_QpContentEncoder') - ->withDependencies(array('mime.charstream', 'mime.bytecanonicalizer')) - - ->register('mime.rawcontentencoder') - ->asNewInstanceOf('Swift_Mime_ContentEncoder_RawContentEncoder') - - ->register('mime.nativeqpcontentencoder') - ->withDependencies(array('properties.charset')) - ->asNewInstanceOf('Swift_Mime_ContentEncoder_NativeQpContentEncoder') - - ->register('mime.qpcontentencoderproxy') - ->asNewInstanceOf('Swift_Mime_ContentEncoder_QpContentEncoderProxy') - ->withDependencies(array('mime.safeqpcontentencoder', 'mime.nativeqpcontentencoder', 'properties.charset')) - - ->register('mime.7bitcontentencoder') - ->asNewInstanceOf('Swift_Mime_ContentEncoder_PlainContentEncoder') - ->addConstructorValue('7bit') - ->addConstructorValue(true) - - ->register('mime.8bitcontentencoder') - ->asNewInstanceOf('Swift_Mime_ContentEncoder_PlainContentEncoder') - ->addConstructorValue('8bit') - ->addConstructorValue(true) - - ->register('mime.base64contentencoder') - ->asSharedInstanceOf('Swift_Mime_ContentEncoder_Base64ContentEncoder') - - ->register('mime.rfc2231encoder') - ->asNewInstanceOf('Swift_Encoder_Rfc2231Encoder') - ->withDependencies(array('mime.charstream')) - - // As of PHP 5.4.7, the quoted_printable_encode() function behaves correctly. - // see https://github.com/php/php-src/commit/18bb426587d62f93c54c40bf8535eb8416603629 - ->register('mime.qpcontentencoder') - ->asAliasOf(PHP_VERSION_ID >= 50407 ? 'mime.qpcontentencoderproxy' : 'mime.safeqpcontentencoder') -; - -unset($swift_mime_types); diff --git a/lib/swiftmailer/swiftmailer/lib/dependency_maps/transport_deps.php b/lib/swiftmailer/swiftmailer/lib/dependency_maps/transport_deps.php deleted file mode 100644 index 77e432cfa..000000000 --- a/lib/swiftmailer/swiftmailer/lib/dependency_maps/transport_deps.php +++ /dev/null @@ -1,76 +0,0 @@ -register('transport.smtp') - ->asNewInstanceOf('Swift_Transport_EsmtpTransport') - ->withDependencies(array( - 'transport.buffer', - array('transport.authhandler'), - 'transport.eventdispatcher', - )) - - ->register('transport.sendmail') - ->asNewInstanceOf('Swift_Transport_SendmailTransport') - ->withDependencies(array( - 'transport.buffer', - 'transport.eventdispatcher', - )) - - ->register('transport.mail') - ->asNewInstanceOf('Swift_Transport_MailTransport') - ->withDependencies(array('transport.mailinvoker', 'transport.eventdispatcher')) - - ->register('transport.loadbalanced') - ->asNewInstanceOf('Swift_Transport_LoadBalancedTransport') - - ->register('transport.failover') - ->asNewInstanceOf('Swift_Transport_FailoverTransport') - - ->register('transport.spool') - ->asNewInstanceOf('Swift_Transport_SpoolTransport') - ->withDependencies(array('transport.eventdispatcher')) - - ->register('transport.null') - ->asNewInstanceOf('Swift_Transport_NullTransport') - ->withDependencies(array('transport.eventdispatcher')) - - ->register('transport.mailinvoker') - ->asSharedInstanceOf('Swift_Transport_SimpleMailInvoker') - - ->register('transport.buffer') - ->asNewInstanceOf('Swift_Transport_StreamBuffer') - ->withDependencies(array('transport.replacementfactory')) - - ->register('transport.authhandler') - ->asNewInstanceOf('Swift_Transport_Esmtp_AuthHandler') - ->withDependencies(array( - array( - 'transport.crammd5auth', - 'transport.loginauth', - 'transport.plainauth', - 'transport.ntlmauth', - 'transport.xoauth2auth', - ), - )) - - ->register('transport.crammd5auth') - ->asNewInstanceOf('Swift_Transport_Esmtp_Auth_CramMd5Authenticator') - - ->register('transport.loginauth') - ->asNewInstanceOf('Swift_Transport_Esmtp_Auth_LoginAuthenticator') - - ->register('transport.plainauth') - ->asNewInstanceOf('Swift_Transport_Esmtp_Auth_PlainAuthenticator') - - ->register('transport.xoauth2auth') - ->asNewInstanceOf('Swift_Transport_Esmtp_Auth_XOAuth2Authenticator') - - ->register('transport.ntlmauth') - ->asNewInstanceOf('Swift_Transport_Esmtp_Auth_NTLMAuthenticator') - - ->register('transport.eventdispatcher') - ->asNewInstanceOf('Swift_Events_SimpleEventDispatcher') - - ->register('transport.replacementfactory') - ->asSharedInstanceOf('Swift_StreamFilters_StringReplacementFilterFactory') -; diff --git a/lib/swiftmailer/swiftmailer/lib/mime_types.php b/lib/swiftmailer/swiftmailer/lib/mime_types.php deleted file mode 100644 index b42c1cc1a..000000000 --- a/lib/swiftmailer/swiftmailer/lib/mime_types.php +++ /dev/null @@ -1,1007 +0,0 @@ - 'text/vnd.in3d.3dml', - '3ds' => 'image/x-3ds', - '3g2' => 'video/3gpp2', - '3gp' => 'video/3gpp', - '7z' => 'application/x-7z-compressed', - 'aab' => 'application/x-authorware-bin', - 'aac' => 'audio/x-aac', - 'aam' => 'application/x-authorware-map', - 'aas' => 'application/x-authorware-seg', - 'abw' => 'application/x-abiword', - 'ac' => 'application/pkix-attr-cert', - 'acc' => 'application/vnd.americandynamics.acc', - 'ace' => 'application/x-ace-compressed', - 'acu' => 'application/vnd.acucobol', - 'acutc' => 'application/vnd.acucorp', - 'adp' => 'audio/adpcm', - 'aep' => 'application/vnd.audiograph', - 'afm' => 'application/x-font-type1', - 'afp' => 'application/vnd.ibm.modcap', - 'ahead' => 'application/vnd.ahead.space', - 'ai' => 'application/postscript', - 'aif' => 'audio/x-aiff', - 'aifc' => 'audio/x-aiff', - 'aiff' => 'audio/x-aiff', - 'air' => 'application/vnd.adobe.air-application-installer-package+zip', - 'ait' => 'application/vnd.dvb.ait', - 'ami' => 'application/vnd.amiga.ami', - 'apk' => 'application/vnd.android.package-archive', - 'appcache' => 'text/cache-manifest', - 'apr' => 'application/vnd.lotus-approach', - 'aps' => 'application/postscript', - 'arc' => 'application/x-freearc', - 'asc' => 'application/pgp-signature', - 'asf' => 'video/x-ms-asf', - 'asm' => 'text/x-asm', - 'aso' => 'application/vnd.accpac.simply.aso', - 'asx' => 'video/x-ms-asf', - 'atc' => 'application/vnd.acucorp', - 'atom' => 'application/atom+xml', - 'atomcat' => 'application/atomcat+xml', - 'atomsvc' => 'application/atomsvc+xml', - 'atx' => 'application/vnd.antix.game-component', - 'au' => 'audio/basic', - 'avi' => 'video/x-msvideo', - 'aw' => 'application/applixware', - 'azf' => 'application/vnd.airzip.filesecure.azf', - 'azs' => 'application/vnd.airzip.filesecure.azs', - 'azw' => 'application/vnd.amazon.ebook', - 'bat' => 'application/x-msdownload', - 'bcpio' => 'application/x-bcpio', - 'bdf' => 'application/x-font-bdf', - 'bdm' => 'application/vnd.syncml.dm+wbxml', - 'bed' => 'application/vnd.realvnc.bed', - 'bh2' => 'application/vnd.fujitsu.oasysprs', - 'bin' => 'application/octet-stream', - 'blb' => 'application/x-blorb', - 'blorb' => 'application/x-blorb', - 'bmi' => 'application/vnd.bmi', - 'bmp' => 'image/bmp', - 'book' => 'application/vnd.framemaker', - 'box' => 'application/vnd.previewsystems.box', - 'boz' => 'application/x-bzip2', - 'bpk' => 'application/octet-stream', - 'btif' => 'image/prs.btif', - 'bz' => 'application/x-bzip', - 'bz2' => 'application/x-bzip2', - 'c' => 'text/x-c', - 'c11amc' => 'application/vnd.cluetrust.cartomobile-config', - 'c11amz' => 'application/vnd.cluetrust.cartomobile-config-pkg', - 'c4d' => 'application/vnd.clonk.c4group', - 'c4f' => 'application/vnd.clonk.c4group', - 'c4g' => 'application/vnd.clonk.c4group', - 'c4p' => 'application/vnd.clonk.c4group', - 'c4u' => 'application/vnd.clonk.c4group', - 'cab' => 'application/vnd.ms-cab-compressed', - 'caf' => 'audio/x-caf', - 'cap' => 'application/vnd.tcpdump.pcap', - 'car' => 'application/vnd.curl.car', - 'cat' => 'application/vnd.ms-pki.seccat', - 'cb7' => 'application/x-cbr', - 'cba' => 'application/x-cbr', - 'cbr' => 'application/x-cbr', - 'cbt' => 'application/x-cbr', - 'cbz' => 'application/x-cbr', - 'cc' => 'text/x-c', - 'cct' => 'application/x-director', - 'ccxml' => 'application/ccxml+xml', - 'cdbcmsg' => 'application/vnd.contact.cmsg', - 'cdf' => 'application/x-netcdf', - 'cdkey' => 'application/vnd.mediastation.cdkey', - 'cdmia' => 'application/cdmi-capability', - 'cdmic' => 'application/cdmi-container', - 'cdmid' => 'application/cdmi-domain', - 'cdmio' => 'application/cdmi-object', - 'cdmiq' => 'application/cdmi-queue', - 'cdx' => 'chemical/x-cdx', - 'cdxml' => 'application/vnd.chemdraw+xml', - 'cdy' => 'application/vnd.cinderella', - 'cer' => 'application/pkix-cert', - 'cfs' => 'application/x-cfs-compressed', - 'cgm' => 'image/cgm', - 'chat' => 'application/x-chat', - 'chm' => 'application/vnd.ms-htmlhelp', - 'chrt' => 'application/vnd.kde.kchart', - 'cif' => 'chemical/x-cif', - 'cii' => 'application/vnd.anser-web-certificate-issue-initiation', - 'cil' => 'application/vnd.ms-artgalry', - 'cla' => 'application/vnd.claymore', - 'class' => 'application/java-vm', - 'clkk' => 'application/vnd.crick.clicker.keyboard', - 'clkp' => 'application/vnd.crick.clicker.palette', - 'clkt' => 'application/vnd.crick.clicker.template', - 'clkw' => 'application/vnd.crick.clicker.wordbank', - 'clkx' => 'application/vnd.crick.clicker', - 'clp' => 'application/x-msclip', - 'cmc' => 'application/vnd.cosmocaller', - 'cmdf' => 'chemical/x-cmdf', - 'cml' => 'chemical/x-cml', - 'cmp' => 'application/vnd.yellowriver-custom-menu', - 'cmx' => 'image/x-cmx', - 'cod' => 'application/vnd.rim.cod', - 'com' => 'application/x-msdownload', - 'conf' => 'text/plain', - 'cpio' => 'application/x-cpio', - 'cpp' => 'text/x-c', - 'cpt' => 'application/mac-compactpro', - 'crd' => 'application/x-mscardfile', - 'crl' => 'application/pkix-crl', - 'crt' => 'application/x-x509-ca-cert', - 'csh' => 'application/x-csh', - 'csml' => 'chemical/x-csml', - 'csp' => 'application/vnd.commonspace', - 'css' => 'text/css', - 'cst' => 'application/x-director', - 'csv' => 'text/csv', - 'cu' => 'application/cu-seeme', - 'curl' => 'text/vnd.curl', - 'cww' => 'application/prs.cww', - 'cxt' => 'application/x-director', - 'cxx' => 'text/x-c', - 'dae' => 'model/vnd.collada+xml', - 'daf' => 'application/vnd.mobius.daf', - 'dart' => 'application/vnd.dart', - 'dataless' => 'application/vnd.fdsn.seed', - 'davmount' => 'application/davmount+xml', - 'dbk' => 'application/docbook+xml', - 'dcr' => 'application/x-director', - 'dcurl' => 'text/vnd.curl.dcurl', - 'dd2' => 'application/vnd.oma.dd2+xml', - 'ddd' => 'application/vnd.fujixerox.ddd', - 'deb' => 'application/x-debian-package', - 'def' => 'text/plain', - 'deploy' => 'application/octet-stream', - 'der' => 'application/x-x509-ca-cert', - 'dfac' => 'application/vnd.dreamfactory', - 'dgc' => 'application/x-dgc-compressed', - 'dic' => 'text/x-c', - 'dir' => 'application/x-director', - 'dis' => 'application/vnd.mobius.dis', - 'dist' => 'application/octet-stream', - 'distz' => 'application/octet-stream', - 'djv' => 'image/vnd.djvu', - 'djvu' => 'image/vnd.djvu', - 'dll' => 'application/x-msdownload', - 'dmg' => 'application/x-apple-diskimage', - 'dmp' => 'application/vnd.tcpdump.pcap', - 'dms' => 'application/octet-stream', - 'dna' => 'application/vnd.dna', - 'doc' => 'application/msword', - 'docm' => 'application/vnd.ms-word.document.macroenabled.12', - 'docx' => 'application/vnd.openxmlformats-officedocument.wordprocessingml.document', - 'dot' => 'application/msword', - 'dotm' => 'application/vnd.ms-word.template.macroenabled.12', - 'dotx' => 'application/vnd.openxmlformats-officedocument.wordprocessingml.template', - 'dp' => 'application/vnd.osgi.dp', - 'dpg' => 'application/vnd.dpgraph', - 'dra' => 'audio/vnd.dra', - 'dsc' => 'text/prs.lines.tag', - 'dssc' => 'application/dssc+der', - 'dtb' => 'application/x-dtbook+xml', - 'dtd' => 'application/xml-dtd', - 'dts' => 'audio/vnd.dts', - 'dtshd' => 'audio/vnd.dts.hd', - 'dump' => 'application/octet-stream', - 'dvb' => 'video/vnd.dvb.file', - 'dvi' => 'application/x-dvi', - 'dwf' => 'model/vnd.dwf', - 'dwg' => 'image/vnd.dwg', - 'dxf' => 'image/vnd.dxf', - 'dxp' => 'application/vnd.spotfire.dxp', - 'dxr' => 'application/x-director', - 'ecelp4800' => 'audio/vnd.nuera.ecelp4800', - 'ecelp7470' => 'audio/vnd.nuera.ecelp7470', - 'ecelp9600' => 'audio/vnd.nuera.ecelp9600', - 'ecma' => 'application/ecmascript', - 'edm' => 'application/vnd.novadigm.edm', - 'edx' => 'application/vnd.novadigm.edx', - 'efif' => 'application/vnd.picsel', - 'ei6' => 'application/vnd.pg.osasli', - 'elc' => 'application/octet-stream', - 'emf' => 'application/x-msmetafile', - 'eml' => 'message/rfc822', - 'emma' => 'application/emma+xml', - 'emz' => 'application/x-msmetafile', - 'eol' => 'audio/vnd.digital-winds', - 'eot' => 'application/vnd.ms-fontobject', - 'eps' => 'application/postscript', - 'epub' => 'application/epub+zip', - 'es3' => 'application/vnd.eszigno3+xml', - 'esa' => 'application/vnd.osgi.subsystem', - 'esf' => 'application/vnd.epson.esf', - 'et3' => 'application/vnd.eszigno3+xml', - 'etx' => 'text/x-setext', - 'eva' => 'application/x-eva', - 'evy' => 'application/x-envoy', - 'exe' => 'application/x-msdownload', - 'exi' => 'application/exi', - 'ext' => 'application/vnd.novadigm.ext', - 'ez' => 'application/andrew-inset', - 'ez2' => 'application/vnd.ezpix-album', - 'ez3' => 'application/vnd.ezpix-package', - 'f' => 'text/x-fortran', - 'f4v' => 'video/x-f4v', - 'f77' => 'text/x-fortran', - 'f90' => 'text/x-fortran', - 'fbs' => 'image/vnd.fastbidsheet', - 'fcdt' => 'application/vnd.adobe.formscentral.fcdt', - 'fcs' => 'application/vnd.isac.fcs', - 'fdf' => 'application/vnd.fdf', - 'fe_launch' => 'application/vnd.denovo.fcselayout-link', - 'fg5' => 'application/vnd.fujitsu.oasysgp', - 'fgd' => 'application/x-director', - 'fh' => 'image/x-freehand', - 'fh4' => 'image/x-freehand', - 'fh5' => 'image/x-freehand', - 'fh7' => 'image/x-freehand', - 'fhc' => 'image/x-freehand', - 'fig' => 'application/x-xfig', - 'flac' => 'audio/x-flac', - 'fli' => 'video/x-fli', - 'flo' => 'application/vnd.micrografx.flo', - 'flv' => 'video/x-flv', - 'flw' => 'application/vnd.kde.kivio', - 'flx' => 'text/vnd.fmi.flexstor', - 'fly' => 'text/vnd.fly', - 'fm' => 'application/vnd.framemaker', - 'fnc' => 'application/vnd.frogans.fnc', - 'for' => 'text/x-fortran', - 'fpx' => 'image/vnd.fpx', - 'frame' => 'application/vnd.framemaker', - 'fsc' => 'application/vnd.fsc.weblaunch', - 'fst' => 'image/vnd.fst', - 'ftc' => 'application/vnd.fluxtime.clip', - 'fti' => 'application/vnd.anser-web-funds-transfer-initiation', - 'fvt' => 'video/vnd.fvt', - 'fxp' => 'application/vnd.adobe.fxp', - 'fxpl' => 'application/vnd.adobe.fxp', - 'fzs' => 'application/vnd.fuzzysheet', - 'g2w' => 'application/vnd.geoplan', - 'g3' => 'image/g3fax', - 'g3w' => 'application/vnd.geospace', - 'gac' => 'application/vnd.groove-account', - 'gam' => 'application/x-tads', - 'gbr' => 'application/rpki-ghostbusters', - 'gca' => 'application/x-gca-compressed', - 'gdl' => 'model/vnd.gdl', - 'geo' => 'application/vnd.dynageo', - 'gex' => 'application/vnd.geometry-explorer', - 'ggb' => 'application/vnd.geogebra.file', - 'ggt' => 'application/vnd.geogebra.tool', - 'ghf' => 'application/vnd.groove-help', - 'gif' => 'image/gif', - 'gim' => 'application/vnd.groove-identity-message', - 'gml' => 'application/gml+xml', - 'gmx' => 'application/vnd.gmx', - 'gnumeric' => 'application/x-gnumeric', - 'gph' => 'application/vnd.flographit', - 'gpx' => 'application/gpx+xml', - 'gqf' => 'application/vnd.grafeq', - 'gqs' => 'application/vnd.grafeq', - 'gram' => 'application/srgs', - 'gramps' => 'application/x-gramps-xml', - 'gre' => 'application/vnd.geometry-explorer', - 'grv' => 'application/vnd.groove-injector', - 'grxml' => 'application/srgs+xml', - 'gsf' => 'application/x-font-ghostscript', - 'gtar' => 'application/x-gtar', - 'gtm' => 'application/vnd.groove-tool-message', - 'gtw' => 'model/vnd.gtw', - 'gv' => 'text/vnd.graphviz', - 'gxf' => 'application/gxf', - 'gxt' => 'application/vnd.geonext', - 'gz' => 'application/x-gzip', - 'h' => 'text/x-c', - 'h261' => 'video/h261', - 'h263' => 'video/h263', - 'h264' => 'video/h264', - 'hal' => 'application/vnd.hal+xml', - 'hbci' => 'application/vnd.hbci', - 'hdf' => 'application/x-hdf', - 'hh' => 'text/x-c', - 'hlp' => 'application/winhlp', - 'hpgl' => 'application/vnd.hp-hpgl', - 'hpid' => 'application/vnd.hp-hpid', - 'hps' => 'application/vnd.hp-hps', - 'hqx' => 'application/mac-binhex40', - 'htke' => 'application/vnd.kenameaapp', - 'htm' => 'text/html', - 'html' => 'text/html', - 'hvd' => 'application/vnd.yamaha.hv-dic', - 'hvp' => 'application/vnd.yamaha.hv-voice', - 'hvs' => 'application/vnd.yamaha.hv-script', - 'i2g' => 'application/vnd.intergeo', - 'icc' => 'application/vnd.iccprofile', - 'ice' => 'x-conference/x-cooltalk', - 'icm' => 'application/vnd.iccprofile', - 'ico' => 'image/x-icon', - 'ics' => 'text/calendar', - 'ief' => 'image/ief', - 'ifb' => 'text/calendar', - 'ifm' => 'application/vnd.shana.informed.formdata', - 'iges' => 'model/iges', - 'igl' => 'application/vnd.igloader', - 'igm' => 'application/vnd.insors.igm', - 'igs' => 'model/iges', - 'igx' => 'application/vnd.micrografx.igx', - 'iif' => 'application/vnd.shana.informed.interchange', - 'imp' => 'application/vnd.accpac.simply.imp', - 'ims' => 'application/vnd.ms-ims', - 'in' => 'text/plain', - 'ink' => 'application/inkml+xml', - 'inkml' => 'application/inkml+xml', - 'install' => 'application/x-install-instructions', - 'iota' => 'application/vnd.astraea-software.iota', - 'ipfix' => 'application/ipfix', - 'ipk' => 'application/vnd.shana.informed.package', - 'irm' => 'application/vnd.ibm.rights-management', - 'irp' => 'application/vnd.irepository.package+xml', - 'iso' => 'application/x-iso9660-image', - 'itp' => 'application/vnd.shana.informed.formtemplate', - 'ivp' => 'application/vnd.immervision-ivp', - 'ivu' => 'application/vnd.immervision-ivu', - 'jad' => 'text/vnd.sun.j2me.app-descriptor', - 'jam' => 'application/vnd.jam', - 'jar' => 'application/java-archive', - 'java' => 'text/x-java-source', - 'jisp' => 'application/vnd.jisp', - 'jlt' => 'application/vnd.hp-jlyt', - 'jnlp' => 'application/x-java-jnlp-file', - 'joda' => 'application/vnd.joost.joda-archive', - 'jpe' => 'image/jpeg', - 'jpeg' => 'image/jpeg', - 'jpg' => 'image/jpeg', - 'jpgm' => 'video/jpm', - 'jpgv' => 'video/jpeg', - 'jpm' => 'video/jpm', - 'js' => 'application/javascript', - 'json' => 'application/json', - 'jsonml' => 'application/jsonml+json', - 'kar' => 'audio/midi', - 'karbon' => 'application/vnd.kde.karbon', - 'kfo' => 'application/vnd.kde.kformula', - 'kia' => 'application/vnd.kidspiration', - 'kml' => 'application/vnd.google-earth.kml+xml', - 'kmz' => 'application/vnd.google-earth.kmz', - 'kne' => 'application/vnd.kinar', - 'knp' => 'application/vnd.kinar', - 'kon' => 'application/vnd.kde.kontour', - 'kpr' => 'application/vnd.kde.kpresenter', - 'kpt' => 'application/vnd.kde.kpresenter', - 'kpxx' => 'application/vnd.ds-keypoint', - 'ksp' => 'application/vnd.kde.kspread', - 'ktr' => 'application/vnd.kahootz', - 'ktx' => 'image/ktx', - 'ktz' => 'application/vnd.kahootz', - 'kwd' => 'application/vnd.kde.kword', - 'kwt' => 'application/vnd.kde.kword', - 'lasxml' => 'application/vnd.las.las+xml', - 'latex' => 'application/x-latex', - 'lbd' => 'application/vnd.llamagraphics.life-balance.desktop', - 'lbe' => 'application/vnd.llamagraphics.life-balance.exchange+xml', - 'les' => 'application/vnd.hhe.lesson-player', - 'lha' => 'application/x-lzh-compressed', - 'link66' => 'application/vnd.route66.link66+xml', - 'list' => 'text/plain', - 'list3820' => 'application/vnd.ibm.modcap', - 'listafp' => 'application/vnd.ibm.modcap', - 'lnk' => 'application/x-ms-shortcut', - 'log' => 'text/plain', - 'lostxml' => 'application/lost+xml', - 'lrf' => 'application/octet-stream', - 'lrm' => 'application/vnd.ms-lrm', - 'ltf' => 'application/vnd.frogans.ltf', - 'lvp' => 'audio/vnd.lucent.voice', - 'lwp' => 'application/vnd.lotus-wordpro', - 'lzh' => 'application/x-lzh-compressed', - 'm13' => 'application/x-msmediaview', - 'm14' => 'application/x-msmediaview', - 'm1v' => 'video/mpeg', - 'm21' => 'application/mp21', - 'm2a' => 'audio/mpeg', - 'm2v' => 'video/mpeg', - 'm3a' => 'audio/mpeg', - 'm3u' => 'audio/x-mpegurl', - 'm3u8' => 'application/vnd.apple.mpegurl', - 'm4a' => 'audio/mp4', - 'm4u' => 'video/vnd.mpegurl', - 'm4v' => 'video/x-m4v', - 'ma' => 'application/mathematica', - 'mads' => 'application/mads+xml', - 'mag' => 'application/vnd.ecowin.chart', - 'maker' => 'application/vnd.framemaker', - 'man' => 'text/troff', - 'mar' => 'application/octet-stream', - 'mathml' => 'application/mathml+xml', - 'mb' => 'application/mathematica', - 'mbk' => 'application/vnd.mobius.mbk', - 'mbox' => 'application/mbox', - 'mc1' => 'application/vnd.medcalcdata', - 'mcd' => 'application/vnd.mcd', - 'mcurl' => 'text/vnd.curl.mcurl', - 'mdb' => 'application/x-msaccess', - 'mdi' => 'image/vnd.ms-modi', - 'me' => 'text/troff', - 'mesh' => 'model/mesh', - 'meta4' => 'application/metalink4+xml', - 'metalink' => 'application/metalink+xml', - 'mets' => 'application/mets+xml', - 'mfm' => 'application/vnd.mfmp', - 'mft' => 'application/rpki-manifest', - 'mgp' => 'application/vnd.osgeo.mapguide.package', - 'mgz' => 'application/vnd.proteus.magazine', - 'mid' => 'audio/midi', - 'midi' => 'audio/midi', - 'mie' => 'application/x-mie', - 'mif' => 'application/vnd.mif', - 'mime' => 'message/rfc822', - 'mj2' => 'video/mj2', - 'mjp2' => 'video/mj2', - 'mk3d' => 'video/x-matroska', - 'mka' => 'audio/x-matroska', - 'mks' => 'video/x-matroska', - 'mkv' => 'video/x-matroska', - 'mlp' => 'application/vnd.dolby.mlp', - 'mmd' => 'application/vnd.chipnuts.karaoke-mmd', - 'mmf' => 'application/vnd.smaf', - 'mmr' => 'image/vnd.fujixerox.edmics-mmr', - 'mng' => 'video/x-mng', - 'mny' => 'application/x-msmoney', - 'mobi' => 'application/x-mobipocket-ebook', - 'mods' => 'application/mods+xml', - 'mov' => 'video/quicktime', - 'movie' => 'video/x-sgi-movie', - 'mp2' => 'audio/mpeg', - 'mp21' => 'application/mp21', - 'mp2a' => 'audio/mpeg', - 'mp3' => 'audio/mpeg', - 'mp4' => 'video/mp4', - 'mp4a' => 'audio/mp4', - 'mp4s' => 'application/mp4', - 'mp4v' => 'video/mp4', - 'mpc' => 'application/vnd.mophun.certificate', - 'mpe' => 'video/mpeg', - 'mpeg' => 'video/mpeg', - 'mpg' => 'video/mpeg', - 'mpg4' => 'video/mp4', - 'mpga' => 'audio/mpeg', - 'mpkg' => 'application/vnd.apple.installer+xml', - 'mpm' => 'application/vnd.blueice.multipass', - 'mpn' => 'application/vnd.mophun.application', - 'mpp' => 'application/vnd.ms-project', - 'mpt' => 'application/vnd.ms-project', - 'mpy' => 'application/vnd.ibm.minipay', - 'mqy' => 'application/vnd.mobius.mqy', - 'mrc' => 'application/marc', - 'mrcx' => 'application/marcxml+xml', - 'ms' => 'text/troff', - 'mscml' => 'application/mediaservercontrol+xml', - 'mseed' => 'application/vnd.fdsn.mseed', - 'mseq' => 'application/vnd.mseq', - 'msf' => 'application/vnd.epson.msf', - 'msh' => 'model/mesh', - 'msi' => 'application/x-msdownload', - 'msl' => 'application/vnd.mobius.msl', - 'msty' => 'application/vnd.muvee.style', - 'mts' => 'model/vnd.mts', - 'mus' => 'application/vnd.musician', - 'musicxml' => 'application/vnd.recordare.musicxml+xml', - 'mvb' => 'application/x-msmediaview', - 'mwf' => 'application/vnd.mfer', - 'mxf' => 'application/mxf', - 'mxl' => 'application/vnd.recordare.musicxml', - 'mxml' => 'application/xv+xml', - 'mxs' => 'application/vnd.triscape.mxs', - 'mxu' => 'video/vnd.mpegurl', - 'n-gage' => 'application/vnd.nokia.n-gage.symbian.install', - 'n3' => 'text/n3', - 'nb' => 'application/mathematica', - 'nbp' => 'application/vnd.wolfram.player', - 'nc' => 'application/x-netcdf', - 'ncx' => 'application/x-dtbncx+xml', - 'nfo' => 'text/x-nfo', - 'ngdat' => 'application/vnd.nokia.n-gage.data', - 'nitf' => 'application/vnd.nitf', - 'nlu' => 'application/vnd.neurolanguage.nlu', - 'nml' => 'application/vnd.enliven', - 'nnd' => 'application/vnd.noblenet-directory', - 'nns' => 'application/vnd.noblenet-sealer', - 'nnw' => 'application/vnd.noblenet-web', - 'npx' => 'image/vnd.net-fpx', - 'nsc' => 'application/x-conference', - 'nsf' => 'application/vnd.lotus-notes', - 'ntf' => 'application/vnd.nitf', - 'nzb' => 'application/x-nzb', - 'oa2' => 'application/vnd.fujitsu.oasys2', - 'oa3' => 'application/vnd.fujitsu.oasys3', - 'oas' => 'application/vnd.fujitsu.oasys', - 'obd' => 'application/x-msbinder', - 'obj' => 'application/x-tgif', - 'oda' => 'application/oda', - 'odb' => 'application/vnd.oasis.opendocument.database', - 'odc' => 'application/vnd.oasis.opendocument.chart', - 'odf' => 'application/vnd.oasis.opendocument.formula', - 'odft' => 'application/vnd.oasis.opendocument.formula-template', - 'odg' => 'application/vnd.oasis.opendocument.graphics', - 'odi' => 'application/vnd.oasis.opendocument.image', - 'odm' => 'application/vnd.oasis.opendocument.text-master', - 'odp' => 'application/vnd.oasis.opendocument.presentation', - 'ods' => 'application/vnd.oasis.opendocument.spreadsheet', - 'odt' => 'application/vnd.oasis.opendocument.text', - 'oga' => 'audio/ogg', - 'ogg' => 'audio/ogg', - 'ogv' => 'video/ogg', - 'ogx' => 'application/ogg', - 'omdoc' => 'application/omdoc+xml', - 'onepkg' => 'application/onenote', - 'onetmp' => 'application/onenote', - 'onetoc' => 'application/onenote', - 'onetoc2' => 'application/onenote', - 'opf' => 'application/oebps-package+xml', - 'opml' => 'text/x-opml', - 'oprc' => 'application/vnd.palm', - 'org' => 'application/vnd.lotus-organizer', - 'osf' => 'application/vnd.yamaha.openscoreformat', - 'osfpvg' => 'application/vnd.yamaha.openscoreformat.osfpvg+xml', - 'otc' => 'application/vnd.oasis.opendocument.chart-template', - 'otf' => 'application/x-font-otf', - 'otg' => 'application/vnd.oasis.opendocument.graphics-template', - 'oth' => 'application/vnd.oasis.opendocument.text-web', - 'oti' => 'application/vnd.oasis.opendocument.image-template', - 'otp' => 'application/vnd.oasis.opendocument.presentation-template', - 'ots' => 'application/vnd.oasis.opendocument.spreadsheet-template', - 'ott' => 'application/vnd.oasis.opendocument.text-template', - 'oxps' => 'application/oxps', - 'oxt' => 'application/vnd.openofficeorg.extension', - 'p' => 'text/x-pascal', - 'p10' => 'application/pkcs10', - 'p12' => 'application/x-pkcs12', - 'p7b' => 'application/x-pkcs7-certificates', - 'p7c' => 'application/pkcs7-mime', - 'p7m' => 'application/pkcs7-mime', - 'p7r' => 'application/x-pkcs7-certreqresp', - 'p7s' => 'application/pkcs7-signature', - 'p8' => 'application/pkcs8', - 'pas' => 'text/x-pascal', - 'paw' => 'application/vnd.pawaafile', - 'pbd' => 'application/vnd.powerbuilder6', - 'pbm' => 'image/x-portable-bitmap', - 'pcap' => 'application/vnd.tcpdump.pcap', - 'pcf' => 'application/x-font-pcf', - 'pcl' => 'application/vnd.hp-pcl', - 'pclxl' => 'application/vnd.hp-pclxl', - 'pct' => 'image/x-pict', - 'pcurl' => 'application/vnd.curl.pcurl', - 'pcx' => 'image/x-pcx', - 'pdb' => 'application/vnd.palm', - 'pdf' => 'application/pdf', - 'pfa' => 'application/x-font-type1', - 'pfb' => 'application/x-font-type1', - 'pfm' => 'application/x-font-type1', - 'pfr' => 'application/font-tdpfr', - 'pfx' => 'application/x-pkcs12', - 'pgm' => 'image/x-portable-graymap', - 'pgn' => 'application/x-chess-pgn', - 'pgp' => 'application/pgp-encrypted', - 'php' => 'application/x-php', - 'php3' => 'application/x-php', - 'php4' => 'application/x-php', - 'php5' => 'application/x-php', - 'pic' => 'image/x-pict', - 'pkg' => 'application/octet-stream', - 'pki' => 'application/pkixcmp', - 'pkipath' => 'application/pkix-pkipath', - 'plb' => 'application/vnd.3gpp.pic-bw-large', - 'plc' => 'application/vnd.mobius.plc', - 'plf' => 'application/vnd.pocketlearn', - 'pls' => 'application/pls+xml', - 'pml' => 'application/vnd.ctc-posml', - 'png' => 'image/png', - 'pnm' => 'image/x-portable-anymap', - 'portpkg' => 'application/vnd.macports.portpkg', - 'pot' => 'application/vnd.ms-powerpoint', - 'potm' => 'application/vnd.ms-powerpoint.template.macroenabled.12', - 'potx' => 'application/vnd.openxmlformats-officedocument.presentationml.template', - 'ppam' => 'application/vnd.ms-powerpoint.addin.macroenabled.12', - 'ppd' => 'application/vnd.cups-ppd', - 'ppm' => 'image/x-portable-pixmap', - 'pps' => 'application/vnd.ms-powerpoint', - 'ppsm' => 'application/vnd.ms-powerpoint.slideshow.macroenabled.12', - 'ppsx' => 'application/vnd.openxmlformats-officedocument.presentationml.slideshow', - 'ppt' => 'application/vnd.ms-powerpoint', - 'pptm' => 'application/vnd.ms-powerpoint.presentation.macroenabled.12', - 'pptx' => 'application/vnd.openxmlformats-officedocument.presentationml.presentation', - 'pqa' => 'application/vnd.palm', - 'prc' => 'application/x-mobipocket-ebook', - 'pre' => 'application/vnd.lotus-freelance', - 'prf' => 'application/pics-rules', - 'ps' => 'application/postscript', - 'psb' => 'application/vnd.3gpp.pic-bw-small', - 'psd' => 'image/vnd.adobe.photoshop', - 'psf' => 'application/x-font-linux-psf', - 'pskcxml' => 'application/pskc+xml', - 'ptid' => 'application/vnd.pvi.ptid1', - 'pub' => 'application/x-mspublisher', - 'pvb' => 'application/vnd.3gpp.pic-bw-var', - 'pwn' => 'application/vnd.3m.post-it-notes', - 'pya' => 'audio/vnd.ms-playready.media.pya', - 'pyv' => 'video/vnd.ms-playready.media.pyv', - 'qam' => 'application/vnd.epson.quickanime', - 'qbo' => 'application/vnd.intu.qbo', - 'qfx' => 'application/vnd.intu.qfx', - 'qps' => 'application/vnd.publishare-delta-tree', - 'qt' => 'video/quicktime', - 'qwd' => 'application/vnd.quark.quarkxpress', - 'qwt' => 'application/vnd.quark.quarkxpress', - 'qxb' => 'application/vnd.quark.quarkxpress', - 'qxd' => 'application/vnd.quark.quarkxpress', - 'qxl' => 'application/vnd.quark.quarkxpress', - 'qxt' => 'application/vnd.quark.quarkxpress', - 'ra' => 'audio/x-pn-realaudio', - 'ram' => 'audio/x-pn-realaudio', - 'rar' => 'application/x-rar-compressed', - 'ras' => 'image/x-cmu-raster', - 'rcprofile' => 'application/vnd.ipunplugged.rcprofile', - 'rdf' => 'application/rdf+xml', - 'rdz' => 'application/vnd.data-vision.rdz', - 'rep' => 'application/vnd.businessobjects', - 'res' => 'application/x-dtbresource+xml', - 'rgb' => 'image/x-rgb', - 'rif' => 'application/reginfo+xml', - 'rip' => 'audio/vnd.rip', - 'ris' => 'application/x-research-info-systems', - 'rl' => 'application/resource-lists+xml', - 'rlc' => 'image/vnd.fujixerox.edmics-rlc', - 'rld' => 'application/resource-lists-diff+xml', - 'rm' => 'application/vnd.rn-realmedia', - 'rmi' => 'audio/midi', - 'rmp' => 'audio/x-pn-realaudio-plugin', - 'rms' => 'application/vnd.jcp.javame.midlet-rms', - 'rmvb' => 'application/vnd.rn-realmedia-vbr', - 'rnc' => 'application/relax-ng-compact-syntax', - 'roa' => 'application/rpki-roa', - 'roff' => 'text/troff', - 'rp9' => 'application/vnd.cloanto.rp9', - 'rpss' => 'application/vnd.nokia.radio-presets', - 'rpst' => 'application/vnd.nokia.radio-preset', - 'rq' => 'application/sparql-query', - 'rs' => 'application/rls-services+xml', - 'rsd' => 'application/rsd+xml', - 'rss' => 'application/rss+xml', - 'rtf' => 'application/rtf', - 'rtx' => 'text/richtext', - 's' => 'text/x-asm', - 's3m' => 'audio/s3m', - 'saf' => 'application/vnd.yamaha.smaf-audio', - 'sbml' => 'application/sbml+xml', - 'sc' => 'application/vnd.ibm.secure-container', - 'scd' => 'application/x-msschedule', - 'scm' => 'application/vnd.lotus-screencam', - 'scq' => 'application/scvp-cv-request', - 'scs' => 'application/scvp-cv-response', - 'scurl' => 'text/vnd.curl.scurl', - 'sda' => 'application/vnd.stardivision.draw', - 'sdc' => 'application/vnd.stardivision.calc', - 'sdd' => 'application/vnd.stardivision.impress', - 'sdkd' => 'application/vnd.solent.sdkm+xml', - 'sdkm' => 'application/vnd.solent.sdkm+xml', - 'sdp' => 'application/sdp', - 'sdw' => 'application/vnd.stardivision.writer', - 'see' => 'application/vnd.seemail', - 'seed' => 'application/vnd.fdsn.seed', - 'sema' => 'application/vnd.sema', - 'semd' => 'application/vnd.semd', - 'semf' => 'application/vnd.semf', - 'ser' => 'application/java-serialized-object', - 'setpay' => 'application/set-payment-initiation', - 'setreg' => 'application/set-registration-initiation', - 'sfd-hdstx' => 'application/vnd.hydrostatix.sof-data', - 'sfs' => 'application/vnd.spotfire.sfs', - 'sfv' => 'text/x-sfv', - 'sgi' => 'image/sgi', - 'sgl' => 'application/vnd.stardivision.writer-global', - 'sgm' => 'text/sgml', - 'sgml' => 'text/sgml', - 'sh' => 'application/x-sh', - 'shar' => 'application/x-shar', - 'shf' => 'application/shf+xml', - 'sid' => 'image/x-mrsid-image', - 'sig' => 'application/pgp-signature', - 'sil' => 'audio/silk', - 'silo' => 'model/mesh', - 'sis' => 'application/vnd.symbian.install', - 'sisx' => 'application/vnd.symbian.install', - 'sit' => 'application/x-stuffit', - 'sitx' => 'application/x-stuffitx', - 'skd' => 'application/vnd.koan', - 'skm' => 'application/vnd.koan', - 'skp' => 'application/vnd.koan', - 'skt' => 'application/vnd.koan', - 'sldm' => 'application/vnd.ms-powerpoint.slide.macroenabled.12', - 'sldx' => 'application/vnd.openxmlformats-officedocument.presentationml.slide', - 'slt' => 'application/vnd.epson.salt', - 'sm' => 'application/vnd.stepmania.stepchart', - 'smf' => 'application/vnd.stardivision.math', - 'smi' => 'application/smil+xml', - 'smil' => 'application/smil+xml', - 'smv' => 'video/x-smv', - 'smzip' => 'application/vnd.stepmania.package', - 'snd' => 'audio/basic', - 'snf' => 'application/x-font-snf', - 'so' => 'application/octet-stream', - 'spc' => 'application/x-pkcs7-certificates', - 'spf' => 'application/vnd.yamaha.smaf-phrase', - 'spl' => 'application/x-futuresplash', - 'spot' => 'text/vnd.in3d.spot', - 'spp' => 'application/scvp-vp-response', - 'spq' => 'application/scvp-vp-request', - 'spx' => 'audio/ogg', - 'sql' => 'application/x-sql', - 'src' => 'application/x-wais-source', - 'srt' => 'application/x-subrip', - 'sru' => 'application/sru+xml', - 'srx' => 'application/sparql-results+xml', - 'ssdl' => 'application/ssdl+xml', - 'sse' => 'application/vnd.kodak-descriptor', - 'ssf' => 'application/vnd.epson.ssf', - 'ssml' => 'application/ssml+xml', - 'st' => 'application/vnd.sailingtracker.track', - 'stc' => 'application/vnd.sun.xml.calc.template', - 'std' => 'application/vnd.sun.xml.draw.template', - 'stf' => 'application/vnd.wt.stf', - 'sti' => 'application/vnd.sun.xml.impress.template', - 'stk' => 'application/hyperstudio', - 'stl' => 'application/vnd.ms-pki.stl', - 'str' => 'application/vnd.pg.format', - 'stw' => 'application/vnd.sun.xml.writer.template', - 'sub' => 'text/vnd.dvb.subtitle', - 'sus' => 'application/vnd.sus-calendar', - 'susp' => 'application/vnd.sus-calendar', - 'sv4cpio' => 'application/x-sv4cpio', - 'sv4crc' => 'application/x-sv4crc', - 'svc' => 'application/vnd.dvb.service', - 'svd' => 'application/vnd.svd', - 'svg' => 'image/svg+xml', - 'svgz' => 'image/svg+xml', - 'swa' => 'application/x-director', - 'swf' => 'application/x-shockwave-flash', - 'swi' => 'application/vnd.aristanetworks.swi', - 'sxc' => 'application/vnd.sun.xml.calc', - 'sxd' => 'application/vnd.sun.xml.draw', - 'sxg' => 'application/vnd.sun.xml.writer.global', - 'sxi' => 'application/vnd.sun.xml.impress', - 'sxm' => 'application/vnd.sun.xml.math', - 'sxw' => 'application/vnd.sun.xml.writer', - 't' => 'text/troff', - 't3' => 'application/x-t3vm-image', - 'taglet' => 'application/vnd.mynfc', - 'tao' => 'application/vnd.tao.intent-module-archive', - 'tar' => 'application/x-tar', - 'tcap' => 'application/vnd.3gpp2.tcap', - 'tcl' => 'application/x-tcl', - 'teacher' => 'application/vnd.smart.teacher', - 'tei' => 'application/tei+xml', - 'teicorpus' => 'application/tei+xml', - 'tex' => 'application/x-tex', - 'texi' => 'application/x-texinfo', - 'texinfo' => 'application/x-texinfo', - 'text' => 'text/plain', - 'tfi' => 'application/thraud+xml', - 'tfm' => 'application/x-tex-tfm', - 'tga' => 'image/x-tga', - 'thmx' => 'application/vnd.ms-officetheme', - 'tif' => 'image/tiff', - 'tiff' => 'image/tiff', - 'tmo' => 'application/vnd.tmobile-livetv', - 'torrent' => 'application/x-bittorrent', - 'tpl' => 'application/vnd.groove-tool-template', - 'tpt' => 'application/vnd.trid.tpt', - 'tr' => 'text/troff', - 'tra' => 'application/vnd.trueapp', - 'trm' => 'application/x-msterminal', - 'tsd' => 'application/timestamped-data', - 'tsv' => 'text/tab-separated-values', - 'ttc' => 'application/x-font-ttf', - 'ttf' => 'application/x-font-ttf', - 'ttl' => 'text/turtle', - 'twd' => 'application/vnd.simtech-mindmapper', - 'twds' => 'application/vnd.simtech-mindmapper', - 'txd' => 'application/vnd.genomatix.tuxedo', - 'txf' => 'application/vnd.mobius.txf', - 'txt' => 'text/plain', - 'u32' => 'application/x-authorware-bin', - 'udeb' => 'application/x-debian-package', - 'ufd' => 'application/vnd.ufdl', - 'ufdl' => 'application/vnd.ufdl', - 'ulx' => 'application/x-glulx', - 'umj' => 'application/vnd.umajin', - 'unityweb' => 'application/vnd.unity', - 'uoml' => 'application/vnd.uoml+xml', - 'uri' => 'text/uri-list', - 'uris' => 'text/uri-list', - 'urls' => 'text/uri-list', - 'ustar' => 'application/x-ustar', - 'utz' => 'application/vnd.uiq.theme', - 'uu' => 'text/x-uuencode', - 'uva' => 'audio/vnd.dece.audio', - 'uvd' => 'application/vnd.dece.data', - 'uvf' => 'application/vnd.dece.data', - 'uvg' => 'image/vnd.dece.graphic', - 'uvh' => 'video/vnd.dece.hd', - 'uvi' => 'image/vnd.dece.graphic', - 'uvm' => 'video/vnd.dece.mobile', - 'uvp' => 'video/vnd.dece.pd', - 'uvs' => 'video/vnd.dece.sd', - 'uvt' => 'application/vnd.dece.ttml+xml', - 'uvu' => 'video/vnd.uvvu.mp4', - 'uvv' => 'video/vnd.dece.video', - 'uvva' => 'audio/vnd.dece.audio', - 'uvvd' => 'application/vnd.dece.data', - 'uvvf' => 'application/vnd.dece.data', - 'uvvg' => 'image/vnd.dece.graphic', - 'uvvh' => 'video/vnd.dece.hd', - 'uvvi' => 'image/vnd.dece.graphic', - 'uvvm' => 'video/vnd.dece.mobile', - 'uvvp' => 'video/vnd.dece.pd', - 'uvvs' => 'video/vnd.dece.sd', - 'uvvt' => 'application/vnd.dece.ttml+xml', - 'uvvu' => 'video/vnd.uvvu.mp4', - 'uvvv' => 'video/vnd.dece.video', - 'uvvx' => 'application/vnd.dece.unspecified', - 'uvvz' => 'application/vnd.dece.zip', - 'uvx' => 'application/vnd.dece.unspecified', - 'uvz' => 'application/vnd.dece.zip', - 'vcard' => 'text/vcard', - 'vcd' => 'application/x-cdlink', - 'vcf' => 'text/x-vcard', - 'vcg' => 'application/vnd.groove-vcard', - 'vcs' => 'text/x-vcalendar', - 'vcx' => 'application/vnd.vcx', - 'vis' => 'application/vnd.visionary', - 'viv' => 'video/vnd.vivo', - 'vob' => 'video/x-ms-vob', - 'vor' => 'application/vnd.stardivision.writer', - 'vox' => 'application/x-authorware-bin', - 'vrml' => 'model/vrml', - 'vsd' => 'application/vnd.visio', - 'vsf' => 'application/vnd.vsf', - 'vss' => 'application/vnd.visio', - 'vst' => 'application/vnd.visio', - 'vsw' => 'application/vnd.visio', - 'vtu' => 'model/vnd.vtu', - 'vxml' => 'application/voicexml+xml', - 'w3d' => 'application/x-director', - 'wad' => 'application/x-doom', - 'wav' => 'audio/x-wav', - 'wax' => 'audio/x-ms-wax', - 'wbmp' => 'image/vnd.wap.wbmp', - 'wbs' => 'application/vnd.criticaltools.wbs+xml', - 'wbxml' => 'application/vnd.wap.wbxml', - 'wcm' => 'application/vnd.ms-works', - 'wdb' => 'application/vnd.ms-works', - 'wdp' => 'image/vnd.ms-photo', - 'weba' => 'audio/webm', - 'webm' => 'video/webm', - 'webp' => 'image/webp', - 'wg' => 'application/vnd.pmi.widget', - 'wgt' => 'application/widget', - 'wks' => 'application/vnd.ms-works', - 'wm' => 'video/x-ms-wm', - 'wma' => 'audio/x-ms-wma', - 'wmd' => 'application/x-ms-wmd', - 'wmf' => 'application/x-msmetafile', - 'wml' => 'text/vnd.wap.wml', - 'wmlc' => 'application/vnd.wap.wmlc', - 'wmls' => 'text/vnd.wap.wmlscript', - 'wmlsc' => 'application/vnd.wap.wmlscriptc', - 'wmv' => 'video/x-ms-wmv', - 'wmx' => 'video/x-ms-wmx', - 'wmz' => 'application/x-msmetafile', - 'woff' => 'application/font-woff', - 'wpd' => 'application/vnd.wordperfect', - 'wpl' => 'application/vnd.ms-wpl', - 'wps' => 'application/vnd.ms-works', - 'wqd' => 'application/vnd.wqd', - 'wri' => 'application/x-mswrite', - 'wrl' => 'model/vrml', - 'wsdl' => 'application/wsdl+xml', - 'wspolicy' => 'application/wspolicy+xml', - 'wtb' => 'application/vnd.webturbo', - 'wvx' => 'video/x-ms-wvx', - 'x32' => 'application/x-authorware-bin', - 'x3d' => 'model/x3d+xml', - 'x3db' => 'model/x3d+binary', - 'x3dbz' => 'model/x3d+binary', - 'x3dv' => 'model/x3d+vrml', - 'x3dvz' => 'model/x3d+vrml', - 'x3dz' => 'model/x3d+xml', - 'xaml' => 'application/xaml+xml', - 'xap' => 'application/x-silverlight-app', - 'xar' => 'application/vnd.xara', - 'xbap' => 'application/x-ms-xbap', - 'xbd' => 'application/vnd.fujixerox.docuworks.binder', - 'xbm' => 'image/x-xbitmap', - 'xdf' => 'application/xcap-diff+xml', - 'xdm' => 'application/vnd.syncml.dm+xml', - 'xdp' => 'application/vnd.adobe.xdp+xml', - 'xdssc' => 'application/dssc+xml', - 'xdw' => 'application/vnd.fujixerox.docuworks', - 'xenc' => 'application/xenc+xml', - 'xer' => 'application/patch-ops-error+xml', - 'xfdf' => 'application/vnd.adobe.xfdf', - 'xfdl' => 'application/vnd.xfdl', - 'xht' => 'application/xhtml+xml', - 'xhtml' => 'application/xhtml+xml', - 'xhvml' => 'application/xv+xml', - 'xif' => 'image/vnd.xiff', - 'xla' => 'application/vnd.ms-excel', - 'xlam' => 'application/vnd.ms-excel.addin.macroenabled.12', - 'xlc' => 'application/vnd.ms-excel', - 'xlf' => 'application/x-xliff+xml', - 'xlm' => 'application/vnd.ms-excel', - 'xls' => 'application/vnd.ms-excel', - 'xlsb' => 'application/vnd.ms-excel.sheet.binary.macroenabled.12', - 'xlsm' => 'application/vnd.ms-excel.sheet.macroenabled.12', - 'xlsx' => 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet', - 'xlt' => 'application/vnd.ms-excel', - 'xltm' => 'application/vnd.ms-excel.template.macroenabled.12', - 'xltx' => 'application/vnd.openxmlformats-officedocument.spreadsheetml.template', - 'xlw' => 'application/vnd.ms-excel', - 'xm' => 'audio/xm', - 'xml' => 'application/xml', - 'xo' => 'application/vnd.olpc-sugar', - 'xop' => 'application/xop+xml', - 'xpi' => 'application/x-xpinstall', - 'xpl' => 'application/xproc+xml', - 'xpm' => 'image/x-xpixmap', - 'xpr' => 'application/vnd.is-xpr', - 'xps' => 'application/vnd.ms-xpsdocument', - 'xpw' => 'application/vnd.intercon.formnet', - 'xpx' => 'application/vnd.intercon.formnet', - 'xsl' => 'application/xml', - 'xslt' => 'application/xslt+xml', - 'xsm' => 'application/vnd.syncml+xml', - 'xspf' => 'application/xspf+xml', - 'xul' => 'application/vnd.mozilla.xul+xml', - 'xvm' => 'application/xv+xml', - 'xvml' => 'application/xv+xml', - 'xwd' => 'image/x-xwindowdump', - 'xyz' => 'chemical/x-xyz', - 'xz' => 'application/x-xz', - 'yang' => 'application/yang', - 'yin' => 'application/yin+xml', - 'z1' => 'application/x-zmachine', - 'z2' => 'application/x-zmachine', - 'z3' => 'application/x-zmachine', - 'z4' => 'application/x-zmachine', - 'z5' => 'application/x-zmachine', - 'z6' => 'application/x-zmachine', - 'z7' => 'application/x-zmachine', - 'z8' => 'application/x-zmachine', - 'zaz' => 'application/vnd.zzazz.deck+xml', - 'zip' => 'application/zip', - 'zir' => 'application/vnd.zul', - 'zirz' => 'application/vnd.zul', - 'zmm' => 'application/vnd.handheld-entertainment+xml', - '123' => 'application/vnd.lotus-1-2-3', -); diff --git a/lib/swiftmailer/swiftmailer/lib/preferences.php b/lib/swiftmailer/swiftmailer/lib/preferences.php deleted file mode 100644 index 0b430e67d..000000000 --- a/lib/swiftmailer/swiftmailer/lib/preferences.php +++ /dev/null @@ -1,25 +0,0 @@ -setCharset('utf-8'); - -// Without these lines the default caching mechanism is "array" but this uses a lot of memory. -// If possible, use a disk cache to enable attaching large attachments etc. -// You can override the default temporary directory by setting the TMPDIR environment variable. -if (@is_writable($tmpDir = sys_get_temp_dir())) { - $preferences->setTempDir($tmpDir)->setCacheType('disk'); -} - -// this should only be done when Swiftmailer won't use the native QP content encoder -// see mime_deps.php -if (PHP_VERSION_ID < 50407) { - $preferences->setQPDotEscape(false); -} diff --git a/lib/swiftmailer/swiftmailer/lib/swift_init.php b/lib/swiftmailer/swiftmailer/lib/swift_init.php deleted file mode 100644 index ff7196344..000000000 --- a/lib/swiftmailer/swiftmailer/lib/swift_init.php +++ /dev/null @@ -1,28 +0,0 @@ - 'application/x-php', - 'php3' => 'application/x-php', - 'php4' => 'application/x-php', - 'php5' => 'application/x-php', - 'zip' => 'application/zip', - 'gif' => 'image/gif', - 'png' => 'image/png', - 'css' => 'text/css', - 'js' => 'text/javascript', - 'txt' => 'text/plain', - 'aif' => 'audio/x-aiff', - 'aiff' => 'audio/x-aiff', - 'avi' => 'video/avi', - 'bmp' => 'image/bmp', - 'bz2' => 'application/x-bz2', - 'csv' => 'text/csv', - 'dmg' => 'application/x-apple-diskimage', - 'doc' => 'application/msword', - 'docx' => 'application/vnd.openxmlformats-officedocument.wordprocessingml.document', - 'eml' => 'message/rfc822', - 'aps' => 'application/postscript', - 'exe' => 'application/x-ms-dos-executable', - 'flv' => 'video/x-flv', - 'gz' => 'application/x-gzip', - 'hqx' => 'application/stuffit', - 'htm' => 'text/html', - 'html' => 'text/html', - 'jar' => 'application/x-java-archive', - 'jpeg' => 'image/jpeg', - 'jpg' => 'image/jpeg', - 'm3u' => 'audio/x-mpegurl', - 'm4a' => 'audio/mp4', - 'mdb' => 'application/x-msaccess', - 'mid' => 'audio/midi', - 'midi' => 'audio/midi', - 'mov' => 'video/quicktime', - 'mp3' => 'audio/mpeg', - 'mp4' => 'video/mp4', - 'mpeg' => 'video/mpeg', - 'mpg' => 'video/mpeg', - 'odg' => 'vnd.oasis.opendocument.graphics', - 'odp' => 'vnd.oasis.opendocument.presentation', - 'odt' => 'vnd.oasis.opendocument.text', - 'ods' => 'vnd.oasis.opendocument.spreadsheet', - 'ogg' => 'audio/ogg', - 'pdf' => 'application/pdf', - 'ppt' => 'application/vnd.ms-powerpoint', - 'pptx' => 'application/vnd.openxmlformats-officedocument.presentationml.presentation', - 'ps' => 'application/postscript', - 'rar' => 'application/x-rar-compressed', - 'rtf' => 'application/rtf', - 'tar' => 'application/x-tar', - 'sit' => 'application/x-stuffit', - 'svg' => 'image/svg+xml', - 'tif' => 'image/tiff', - 'tiff' => 'image/tiff', - 'ttf' => 'application/x-font-truetype', - 'vcf' => 'text/x-vcard', - 'wav' => 'audio/wav', - 'wma' => 'audio/x-ms-wma', - 'wmv' => 'audio/x-ms-wmv', - 'xls' => 'application/vnd.ms-excel', - 'xlsx' => 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet', - 'xml' => 'application/xml', - ); - - // wrap array for generating file - foreach ($valid_mime_types_preset as $extension => $mime_type) { - // generate array for mimetype to extension resolver (only first match) - $valid_mime_types[$extension] = "'{$extension}' => '{$mime_type}'"; - } - - // collect extensions - $valid_extensions = array(); - - // all extensions from second match - foreach ($matches[2] as $i => $extensions) { - // explode multiple extensions from string - $extensions = explode(' ', strtolower($extensions)); - - // force array for foreach - if (!is_array($extensions)) { - $extensions = array($extensions); - } - - foreach ($extensions as $extension) { - // get mime type - $mime_type = $matches[1][$i]; - - // check if string length lower than 10 - if (strlen($extension) < 10) { - // add extension - $valid_extensions[] = $extension; - - if (!isset($valid_mime_types[$mime_type])) { - // generate array for mimetype to extension resolver (only first match) - $valid_mime_types[$extension] = "'{$extension}' => '{$mime_type}'"; - } - } - } - } - } - - $xml = simplexml_load_string($mime_xml); - - foreach ($xml as $node) { - // check if there is no pattern - if (!isset($node->glob['pattern'])) { - continue; - } - - // get all matching extensions from match - foreach ((array) $node->glob['pattern'] as $extension) { - // skip none glob extensions - if (strpos($extension, '.') === false) { - continue; - } - - // remove get only last part - $extension = explode('.', strtolower($extension)); - $extension = end($extension); - - // maximum length in database column - if (strlen($extension) <= 9) { - $valid_extensions[] = $extension; - } - } - - if (isset($node->glob['pattern'][0])) { - // mime type - $mime_type = strtolower((string) $node['type']); - - // get first extension - $extension = strtolower(trim($node->glob['ddpattern'][0], '*.')); - - // skip none glob extensions and check if string length between 1 and 10 - if (strpos($extension, '.') !== false || strlen($extension) < 1 || strlen($extension) > 9) { - continue; - } - - // check if string length lower than 10 - if (!isset($valid_mime_types[$mime_type])) { - // generate array for mimetype to extension resolver (only first match) - $valid_mime_types[$extension] = "'{$extension}' => '{$mime_type}'"; - } - } - } - - // full list of valid extensions only - $valid_mime_types = array_unique($valid_mime_types); - ksort($valid_mime_types); - - // combine mime types and extensions array - $output = "$preamble\$swift_mime_types = array(\n ".implode($valid_mime_types, ",\n ")."\n);"; - - // write mime_types.php config file - @file_put_contents('./mime_types.php', $output); -} - -generateUpToDateMimeArray(); diff --git a/lib/swiftmailer/swiftmailer/phpunit.xml.dist b/lib/swiftmailer/swiftmailer/phpunit.xml.dist deleted file mode 100644 index 606c5b449..000000000 --- a/lib/swiftmailer/swiftmailer/phpunit.xml.dist +++ /dev/null @@ -1,39 +0,0 @@ - - - - - - - - - - - - tests/unit - - - tests/acceptance - - - tests/bug - - - tests/smoke - - - - - - - -