mirror of
https://github.com/egulias/EmailValidator.git
synced 2026-08-18 16:10:46 +00:00
Message-id validator (#290)
* scafolding for MessageID validation * Improve domain valid tokens * Improved EmailParser to remove leaked logic. User of lexer recorder within parsers. * MessageIDParser passing tests. * change left for right, which is the right one * psaml errors * Better naming * comments are not allowed in IDLeft for message-id * Suppress psalm inheritance over tokens and dependencies * Update src/Parser.php Co-authored-by: Alexander M. Turek <me@derrabus.de> * Update src/Parser.php Co-authored-by: Alexander M. Turek <me@derrabus.de> * improve parser from comments Co-authored-by: Alexander M. Turek <me@derrabus.de>
This commit is contained in:
committed by
GitHub
parent
451b438902
commit
8e526a57c1
Generated
+99
-98
@@ -88,16 +88,16 @@
|
||||
},
|
||||
{
|
||||
"name": "symfony/polyfill-intl-idn",
|
||||
"version": "v1.22.0",
|
||||
"version": "v1.22.1",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/polyfill-intl-idn.git",
|
||||
"reference": "0eb8293dbbcd6ef6bf81404c9ce7d95bcdf34f44"
|
||||
"reference": "2d63434d922daf7da8dd863e7907e67ee3031483"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/polyfill-intl-idn/zipball/0eb8293dbbcd6ef6bf81404c9ce7d95bcdf34f44",
|
||||
"reference": "0eb8293dbbcd6ef6bf81404c9ce7d95bcdf34f44",
|
||||
"url": "https://api.github.com/repos/symfony/polyfill-intl-idn/zipball/2d63434d922daf7da8dd863e7907e67ee3031483",
|
||||
"reference": "2d63434d922daf7da8dd863e7907e67ee3031483",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -155,7 +155,7 @@
|
||||
"shim"
|
||||
],
|
||||
"support": {
|
||||
"source": "https://github.com/symfony/polyfill-intl-idn/tree/v1.22.0"
|
||||
"source": "https://github.com/symfony/polyfill-intl-idn/tree/v1.22.1"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
@@ -171,20 +171,20 @@
|
||||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2021-01-07T16:49:33+00:00"
|
||||
"time": "2021-01-22T09:19:47+00:00"
|
||||
},
|
||||
{
|
||||
"name": "symfony/polyfill-intl-normalizer",
|
||||
"version": "v1.22.0",
|
||||
"version": "v1.22.1",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/polyfill-intl-normalizer.git",
|
||||
"reference": "6e971c891537eb617a00bb07a43d182a6915faba"
|
||||
"reference": "43a0283138253ed1d48d352ab6d0bdb3f809f248"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/polyfill-intl-normalizer/zipball/6e971c891537eb617a00bb07a43d182a6915faba",
|
||||
"reference": "6e971c891537eb617a00bb07a43d182a6915faba",
|
||||
"url": "https://api.github.com/repos/symfony/polyfill-intl-normalizer/zipball/43a0283138253ed1d48d352ab6d0bdb3f809f248",
|
||||
"reference": "43a0283138253ed1d48d352ab6d0bdb3f809f248",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -239,7 +239,7 @@
|
||||
"shim"
|
||||
],
|
||||
"support": {
|
||||
"source": "https://github.com/symfony/polyfill-intl-normalizer/tree/v1.22.0"
|
||||
"source": "https://github.com/symfony/polyfill-intl-normalizer/tree/v1.22.1"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
@@ -255,11 +255,11 @@
|
||||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2021-01-07T17:09:11+00:00"
|
||||
"time": "2021-01-22T09:19:47+00:00"
|
||||
},
|
||||
{
|
||||
"name": "symfony/polyfill-php72",
|
||||
"version": "v1.22.0",
|
||||
"version": "v1.22.1",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/polyfill-php72.git",
|
||||
@@ -315,7 +315,7 @@
|
||||
"shim"
|
||||
],
|
||||
"support": {
|
||||
"source": "https://github.com/symfony/polyfill-php72/tree/v1.22.0"
|
||||
"source": "https://github.com/symfony/polyfill-php72/tree/v1.22.1"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
@@ -865,16 +865,16 @@
|
||||
},
|
||||
{
|
||||
"name": "felixfbecker/language-server-protocol",
|
||||
"version": "v1.5.0",
|
||||
"version": "1.5.1",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/felixfbecker/php-language-server-protocol.git",
|
||||
"reference": "85e83cacd2ed573238678c6875f8f0d7ec699541"
|
||||
"reference": "9d846d1f5cf101deee7a61c8ba7caa0a975cd730"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/felixfbecker/php-language-server-protocol/zipball/85e83cacd2ed573238678c6875f8f0d7ec699541",
|
||||
"reference": "85e83cacd2ed573238678c6875f8f0d7ec699541",
|
||||
"url": "https://api.github.com/repos/felixfbecker/php-language-server-protocol/zipball/9d846d1f5cf101deee7a61c8ba7caa0a975cd730",
|
||||
"reference": "9d846d1f5cf101deee7a61c8ba7caa0a975cd730",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -915,9 +915,9 @@
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/felixfbecker/php-language-server-protocol/issues",
|
||||
"source": "https://github.com/felixfbecker/php-language-server-protocol/tree/v1.5.0"
|
||||
"source": "https://github.com/felixfbecker/php-language-server-protocol/tree/1.5.1"
|
||||
},
|
||||
"time": "2020-10-23T13:55:30+00:00"
|
||||
"time": "2021-02-22T14:02:09+00:00"
|
||||
},
|
||||
{
|
||||
"name": "guzzlehttp/guzzle",
|
||||
@@ -1431,16 +1431,16 @@
|
||||
},
|
||||
{
|
||||
"name": "phar-io/version",
|
||||
"version": "3.0.4",
|
||||
"version": "3.1.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/phar-io/version.git",
|
||||
"reference": "e4782611070e50613683d2b9a57730e9a3ba5451"
|
||||
"reference": "bae7c545bef187884426f042434e561ab1ddb182"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/phar-io/version/zipball/e4782611070e50613683d2b9a57730e9a3ba5451",
|
||||
"reference": "e4782611070e50613683d2b9a57730e9a3ba5451",
|
||||
"url": "https://api.github.com/repos/phar-io/version/zipball/bae7c545bef187884426f042434e561ab1ddb182",
|
||||
"reference": "bae7c545bef187884426f042434e561ab1ddb182",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -1476,9 +1476,9 @@
|
||||
"description": "Library for handling version information and constraints",
|
||||
"support": {
|
||||
"issues": "https://github.com/phar-io/version/issues",
|
||||
"source": "https://github.com/phar-io/version/tree/3.0.4"
|
||||
"source": "https://github.com/phar-io/version/tree/3.1.0"
|
||||
},
|
||||
"time": "2020-12-13T23:18:30+00:00"
|
||||
"time": "2021-02-23T14:00:09+00:00"
|
||||
},
|
||||
{
|
||||
"name": "php-coveralls/php-coveralls",
|
||||
@@ -3165,16 +3165,16 @@
|
||||
},
|
||||
{
|
||||
"name": "symfony/config",
|
||||
"version": "v5.2.1",
|
||||
"version": "v5.2.3",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/config.git",
|
||||
"reference": "d0a82d965296083fe463d655a3644cbe49cbaa80"
|
||||
"reference": "50e0e1314a3b2609d32b6a5a0d0fb5342494c4ab"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/config/zipball/d0a82d965296083fe463d655a3644cbe49cbaa80",
|
||||
"reference": "d0a82d965296083fe463d655a3644cbe49cbaa80",
|
||||
"url": "https://api.github.com/repos/symfony/config/zipball/50e0e1314a3b2609d32b6a5a0d0fb5342494c4ab",
|
||||
"reference": "50e0e1314a3b2609d32b6a5a0d0fb5342494c4ab",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -3220,10 +3220,10 @@
|
||||
"homepage": "https://symfony.com/contributors"
|
||||
}
|
||||
],
|
||||
"description": "Symfony Config Component",
|
||||
"description": "Helps you find, load, combine, autofill and validate configuration values of any kind",
|
||||
"homepage": "https://symfony.com",
|
||||
"support": {
|
||||
"source": "https://github.com/symfony/config/tree/v5.2.1"
|
||||
"source": "https://github.com/symfony/config/tree/v5.2.3"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
@@ -3239,20 +3239,20 @@
|
||||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2020-12-09T18:54:12+00:00"
|
||||
"time": "2021-01-27T10:15:41+00:00"
|
||||
},
|
||||
{
|
||||
"name": "symfony/console",
|
||||
"version": "v5.2.1",
|
||||
"version": "v5.2.3",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/console.git",
|
||||
"reference": "47c02526c532fb381374dab26df05e7313978976"
|
||||
"reference": "89d4b176d12a2946a1ae4e34906a025b7b6b135a"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/console/zipball/47c02526c532fb381374dab26df05e7313978976",
|
||||
"reference": "47c02526c532fb381374dab26df05e7313978976",
|
||||
"url": "https://api.github.com/repos/symfony/console/zipball/89d4b176d12a2946a1ae4e34906a025b7b6b135a",
|
||||
"reference": "89d4b176d12a2946a1ae4e34906a025b7b6b135a",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -3311,7 +3311,7 @@
|
||||
"homepage": "https://symfony.com/contributors"
|
||||
}
|
||||
],
|
||||
"description": "Symfony Console Component",
|
||||
"description": "Eases the creation of beautiful and testable command line interfaces",
|
||||
"homepage": "https://symfony.com",
|
||||
"keywords": [
|
||||
"cli",
|
||||
@@ -3320,7 +3320,7 @@
|
||||
"terminal"
|
||||
],
|
||||
"support": {
|
||||
"source": "https://github.com/symfony/console/tree/v5.2.1"
|
||||
"source": "https://github.com/symfony/console/tree/v5.2.3"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
@@ -3336,7 +3336,7 @@
|
||||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2020-12-18T08:03:05+00:00"
|
||||
"time": "2021-01-28T22:06:19+00:00"
|
||||
},
|
||||
{
|
||||
"name": "symfony/deprecation-contracts",
|
||||
@@ -3407,16 +3407,16 @@
|
||||
},
|
||||
{
|
||||
"name": "symfony/filesystem",
|
||||
"version": "v5.2.1",
|
||||
"version": "v5.2.3",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/filesystem.git",
|
||||
"reference": "fa8f8cab6b65e2d99a118e082935344c5ba8c60d"
|
||||
"reference": "262d033b57c73e8b59cd6e68a45c528318b15038"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/filesystem/zipball/fa8f8cab6b65e2d99a118e082935344c5ba8c60d",
|
||||
"reference": "fa8f8cab6b65e2d99a118e082935344c5ba8c60d",
|
||||
"url": "https://api.github.com/repos/symfony/filesystem/zipball/262d033b57c73e8b59cd6e68a45c528318b15038",
|
||||
"reference": "262d033b57c73e8b59cd6e68a45c528318b15038",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -3446,10 +3446,10 @@
|
||||
"homepage": "https://symfony.com/contributors"
|
||||
}
|
||||
],
|
||||
"description": "Symfony Filesystem Component",
|
||||
"description": "Provides basic utilities for the filesystem",
|
||||
"homepage": "https://symfony.com",
|
||||
"support": {
|
||||
"source": "https://github.com/symfony/filesystem/tree/v5.2.1"
|
||||
"source": "https://github.com/symfony/filesystem/tree/v5.2.3"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
@@ -3465,11 +3465,11 @@
|
||||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2020-11-30T17:05:38+00:00"
|
||||
"time": "2021-01-27T10:01:46+00:00"
|
||||
},
|
||||
{
|
||||
"name": "symfony/polyfill-ctype",
|
||||
"version": "v1.22.0",
|
||||
"version": "v1.22.1",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/polyfill-ctype.git",
|
||||
@@ -3528,7 +3528,7 @@
|
||||
"portable"
|
||||
],
|
||||
"support": {
|
||||
"source": "https://github.com/symfony/polyfill-ctype/tree/v1.22.0"
|
||||
"source": "https://github.com/symfony/polyfill-ctype/tree/v1.22.1"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
@@ -3548,16 +3548,16 @@
|
||||
},
|
||||
{
|
||||
"name": "symfony/polyfill-intl-grapheme",
|
||||
"version": "v1.22.0",
|
||||
"version": "v1.22.1",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/polyfill-intl-grapheme.git",
|
||||
"reference": "267a9adeb8ecb8071040a740930e077cdfb987af"
|
||||
"reference": "5601e09b69f26c1828b13b6bb87cb07cddba3170"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/polyfill-intl-grapheme/zipball/267a9adeb8ecb8071040a740930e077cdfb987af",
|
||||
"reference": "267a9adeb8ecb8071040a740930e077cdfb987af",
|
||||
"url": "https://api.github.com/repos/symfony/polyfill-intl-grapheme/zipball/5601e09b69f26c1828b13b6bb87cb07cddba3170",
|
||||
"reference": "5601e09b69f26c1828b13b6bb87cb07cddba3170",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -3609,7 +3609,7 @@
|
||||
"shim"
|
||||
],
|
||||
"support": {
|
||||
"source": "https://github.com/symfony/polyfill-intl-grapheme/tree/v1.22.0"
|
||||
"source": "https://github.com/symfony/polyfill-intl-grapheme/tree/v1.22.1"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
@@ -3625,20 +3625,20 @@
|
||||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2021-01-07T16:49:33+00:00"
|
||||
"time": "2021-01-22T09:19:47+00:00"
|
||||
},
|
||||
{
|
||||
"name": "symfony/polyfill-mbstring",
|
||||
"version": "v1.22.0",
|
||||
"version": "v1.22.1",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/polyfill-mbstring.git",
|
||||
"reference": "f377a3dd1fde44d37b9831d68dc8dea3ffd28e13"
|
||||
"reference": "5232de97ee3b75b0360528dae24e73db49566ab1"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/f377a3dd1fde44d37b9831d68dc8dea3ffd28e13",
|
||||
"reference": "f377a3dd1fde44d37b9831d68dc8dea3ffd28e13",
|
||||
"url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/5232de97ee3b75b0360528dae24e73db49566ab1",
|
||||
"reference": "5232de97ee3b75b0360528dae24e73db49566ab1",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -3689,7 +3689,7 @@
|
||||
"shim"
|
||||
],
|
||||
"support": {
|
||||
"source": "https://github.com/symfony/polyfill-mbstring/tree/v1.22.0"
|
||||
"source": "https://github.com/symfony/polyfill-mbstring/tree/v1.22.1"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
@@ -3705,11 +3705,11 @@
|
||||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2021-01-07T16:49:33+00:00"
|
||||
"time": "2021-01-22T09:19:47+00:00"
|
||||
},
|
||||
{
|
||||
"name": "symfony/polyfill-php73",
|
||||
"version": "v1.22.0",
|
||||
"version": "v1.22.1",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/polyfill-php73.git",
|
||||
@@ -3768,7 +3768,7 @@
|
||||
"shim"
|
||||
],
|
||||
"support": {
|
||||
"source": "https://github.com/symfony/polyfill-php73/tree/v1.22.0"
|
||||
"source": "https://github.com/symfony/polyfill-php73/tree/v1.22.1"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
@@ -3788,7 +3788,7 @@
|
||||
},
|
||||
{
|
||||
"name": "symfony/polyfill-php80",
|
||||
"version": "v1.22.0",
|
||||
"version": "v1.22.1",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/polyfill-php80.git",
|
||||
@@ -3851,7 +3851,7 @@
|
||||
"shim"
|
||||
],
|
||||
"support": {
|
||||
"source": "https://github.com/symfony/polyfill-php80/tree/v1.22.0"
|
||||
"source": "https://github.com/symfony/polyfill-php80/tree/v1.22.1"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
@@ -3950,16 +3950,16 @@
|
||||
},
|
||||
{
|
||||
"name": "symfony/stopwatch",
|
||||
"version": "v5.2.1",
|
||||
"version": "v5.2.3",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/stopwatch.git",
|
||||
"reference": "2b105c0354f39a63038a1d8bf776ee92852813af"
|
||||
"reference": "b12274acfab9d9850c52583d136a24398cdf1a0c"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/stopwatch/zipball/2b105c0354f39a63038a1d8bf776ee92852813af",
|
||||
"reference": "2b105c0354f39a63038a1d8bf776ee92852813af",
|
||||
"url": "https://api.github.com/repos/symfony/stopwatch/zipball/b12274acfab9d9850c52583d136a24398cdf1a0c",
|
||||
"reference": "b12274acfab9d9850c52583d136a24398cdf1a0c",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -3989,10 +3989,10 @@
|
||||
"homepage": "https://symfony.com/contributors"
|
||||
}
|
||||
],
|
||||
"description": "Symfony Stopwatch Component",
|
||||
"description": "Provides a way to profile code",
|
||||
"homepage": "https://symfony.com",
|
||||
"support": {
|
||||
"source": "https://github.com/symfony/stopwatch/tree/v5.2.1"
|
||||
"source": "https://github.com/symfony/stopwatch/tree/v5.2.3"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
@@ -4008,20 +4008,20 @@
|
||||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2020-11-01T16:14:45+00:00"
|
||||
"time": "2021-01-27T10:15:41+00:00"
|
||||
},
|
||||
{
|
||||
"name": "symfony/string",
|
||||
"version": "v5.2.1",
|
||||
"version": "v5.2.3",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/string.git",
|
||||
"reference": "5bd67751d2e3f7d6f770c9154b8fbcb2aa05f7ed"
|
||||
"reference": "c95468897f408dd0aca2ff582074423dd0455122"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/string/zipball/5bd67751d2e3f7d6f770c9154b8fbcb2aa05f7ed",
|
||||
"reference": "5bd67751d2e3f7d6f770c9154b8fbcb2aa05f7ed",
|
||||
"url": "https://api.github.com/repos/symfony/string/zipball/c95468897f408dd0aca2ff582074423dd0455122",
|
||||
"reference": "c95468897f408dd0aca2ff582074423dd0455122",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -4064,7 +4064,7 @@
|
||||
"homepage": "https://symfony.com/contributors"
|
||||
}
|
||||
],
|
||||
"description": "Symfony String component",
|
||||
"description": "Provides an object-oriented API to strings and deals with bytes, UTF-8 code points and grapheme clusters in a unified way",
|
||||
"homepage": "https://symfony.com",
|
||||
"keywords": [
|
||||
"grapheme",
|
||||
@@ -4075,7 +4075,7 @@
|
||||
"utf8"
|
||||
],
|
||||
"support": {
|
||||
"source": "https://github.com/symfony/string/tree/v5.2.1"
|
||||
"source": "https://github.com/symfony/string/tree/v5.2.3"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
@@ -4091,20 +4091,20 @@
|
||||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2020-12-05T07:33:16+00:00"
|
||||
"time": "2021-01-25T15:14:59+00:00"
|
||||
},
|
||||
{
|
||||
"name": "symfony/yaml",
|
||||
"version": "v5.2.1",
|
||||
"version": "v5.2.3",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/yaml.git",
|
||||
"reference": "290ea5e03b8cf9b42c783163123f54441fb06939"
|
||||
"reference": "338cddc6d74929f6adf19ca5682ac4b8e109cdb0"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/yaml/zipball/290ea5e03b8cf9b42c783163123f54441fb06939",
|
||||
"reference": "290ea5e03b8cf9b42c783163123f54441fb06939",
|
||||
"url": "https://api.github.com/repos/symfony/yaml/zipball/338cddc6d74929f6adf19ca5682ac4b8e109cdb0",
|
||||
"reference": "338cddc6d74929f6adf19ca5682ac4b8e109cdb0",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -4147,10 +4147,10 @@
|
||||
"homepage": "https://symfony.com/contributors"
|
||||
}
|
||||
],
|
||||
"description": "Symfony Yaml Component",
|
||||
"description": "Loads and dumps YAML files",
|
||||
"homepage": "https://symfony.com",
|
||||
"support": {
|
||||
"source": "https://github.com/symfony/yaml/tree/v5.2.1"
|
||||
"source": "https://github.com/symfony/yaml/tree/v5.2.3"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
@@ -4166,7 +4166,7 @@
|
||||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2020-12-08T17:02:38+00:00"
|
||||
"time": "2021-02-03T04:42:09+00:00"
|
||||
},
|
||||
{
|
||||
"name": "theseer/tokenizer",
|
||||
@@ -4220,16 +4220,16 @@
|
||||
},
|
||||
{
|
||||
"name": "vimeo/psalm",
|
||||
"version": "4.4.1",
|
||||
"version": "4.6.2",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/vimeo/psalm.git",
|
||||
"reference": "9fd7a7d885b3a216cff8dec9d8c21a132f275224"
|
||||
"reference": "bca09d74adc704c4eaee36a3c3e9d379e290fc3b"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/vimeo/psalm/zipball/9fd7a7d885b3a216cff8dec9d8c21a132f275224",
|
||||
"reference": "9fd7a7d885b3a216cff8dec9d8c21a132f275224",
|
||||
"url": "https://api.github.com/repos/vimeo/psalm/zipball/bca09d74adc704c4eaee36a3c3e9d379e290fc3b",
|
||||
"reference": "bca09d74adc704c4eaee36a3c3e9d379e290fc3b",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -4246,8 +4246,8 @@
|
||||
"ext-simplexml": "*",
|
||||
"ext-tokenizer": "*",
|
||||
"felixfbecker/advanced-json-rpc": "^3.0.3",
|
||||
"felixfbecker/language-server-protocol": "^1.4",
|
||||
"netresearch/jsonmapper": "^1.0 || ^2.0 || ^3.0",
|
||||
"felixfbecker/language-server-protocol": "^1.5",
|
||||
"netresearch/jsonmapper": "^1.0 || ^2.0 || ^3.0 || ^4.0",
|
||||
"nikic/php-parser": "^4.10.1",
|
||||
"openlss/lib-array2xml": "^1.0",
|
||||
"php": "^7.1|^8",
|
||||
@@ -4263,6 +4263,7 @@
|
||||
"bamarni/composer-bin-plugin": "^1.2",
|
||||
"brianium/paratest": "^4.0||^6.0",
|
||||
"ext-curl": "*",
|
||||
"php-parallel-lint/php-parallel-lint": "^1.2",
|
||||
"phpdocumentor/reflection-docblock": "^5",
|
||||
"phpmyadmin/sql-parser": "5.1.0||dev-master",
|
||||
"phpspec/prophecy": ">=1.9.0",
|
||||
@@ -4318,21 +4319,21 @@
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/vimeo/psalm/issues",
|
||||
"source": "https://github.com/vimeo/psalm/tree/4.4.1"
|
||||
"source": "https://github.com/vimeo/psalm/tree/4.6.2"
|
||||
},
|
||||
"time": "2021-01-14T21:44:29+00:00"
|
||||
"time": "2021-02-26T02:24:18+00:00"
|
||||
},
|
||||
{
|
||||
"name": "webmozart/assert",
|
||||
"version": "1.9.1",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/webmozart/assert.git",
|
||||
"url": "https://github.com/webmozarts/assert.git",
|
||||
"reference": "bafc69caeb4d49c39fd0779086c03a3738cbb389"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/webmozart/assert/zipball/bafc69caeb4d49c39fd0779086c03a3738cbb389",
|
||||
"url": "https://api.github.com/repos/webmozarts/assert/zipball/bafc69caeb4d49c39fd0779086c03a3738cbb389",
|
||||
"reference": "bafc69caeb4d49c39fd0779086c03a3738cbb389",
|
||||
"shasum": ""
|
||||
},
|
||||
@@ -4370,8 +4371,8 @@
|
||||
"validate"
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/webmozart/assert/issues",
|
||||
"source": "https://github.com/webmozart/assert/tree/master"
|
||||
"issues": "https://github.com/webmozarts/assert/issues",
|
||||
"source": "https://github.com/webmozarts/assert/tree/1.9.1"
|
||||
},
|
||||
"time": "2020-07-08T17:02:28+00:00"
|
||||
},
|
||||
|
||||
@@ -124,6 +124,7 @@ class EmailLexer extends AbstractLexer
|
||||
*
|
||||
* @var array
|
||||
*
|
||||
* @psalm-suppress NonInvariantDocblockPropertyType
|
||||
* @psalm-var array{value:string, type:null|int, position:int}
|
||||
* @psalm-suppress NonInvariantDocblockPropertyType
|
||||
*/
|
||||
|
||||
+23
-74
@@ -9,18 +9,12 @@ use Egulias\EmailValidator\Parser\DomainPart;
|
||||
use Egulias\EmailValidator\Result\ValidEmail;
|
||||
use Egulias\EmailValidator\Result\InvalidEmail;
|
||||
use Egulias\EmailValidator\Warning\EmailTooLong;
|
||||
use Egulias\EmailValidator\Result\Reason\ExpectingATEXT;
|
||||
use Egulias\EmailValidator\Result\Reason\NoLocalPart;
|
||||
|
||||
class EmailParser
|
||||
class EmailParser extends Parser
|
||||
{
|
||||
const EMAIL_MAX_LENGTH = 254;
|
||||
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
protected $warnings = [];
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
@@ -30,52 +24,39 @@ class EmailParser
|
||||
* @var string
|
||||
*/
|
||||
protected $localPart = '';
|
||||
/**
|
||||
* @var EmailLexer
|
||||
*/
|
||||
protected $lexer;
|
||||
|
||||
public function __construct(EmailLexer $lexer)
|
||||
{
|
||||
$this->lexer = $lexer;
|
||||
}
|
||||
|
||||
public function parse(string $str) : Result
|
||||
{
|
||||
$this->lexer->setInput($str);
|
||||
|
||||
if (!$this->hasAtToken()) {
|
||||
return new InvalidEmail(new NoLocalPart(), $this->lexer->token["value"]);
|
||||
}
|
||||
|
||||
$localPartResult = $this->processLocalPart();
|
||||
|
||||
if ($localPartResult->isInvalid()) {
|
||||
return $localPartResult;
|
||||
}
|
||||
|
||||
$domainPartResult = $this->processDomainPart();
|
||||
|
||||
if ($domainPartResult->isInvalid()) {
|
||||
return $domainPartResult;
|
||||
}
|
||||
|
||||
if ($this->lexer->hasInvalidTokens()) {
|
||||
return new InvalidEmail(new ExpectingATEXT("Invalid tokens found"), $this->lexer->token["value"]);
|
||||
}
|
||||
$result = parent::parse($str);
|
||||
|
||||
$this->addLongEmailWarning($this->localPart, $this->domainPart);
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
protected function preLeftParsing(): Result
|
||||
{
|
||||
if (!$this->hasAtToken()) {
|
||||
return new InvalidEmail(new NoLocalPart(), $this->lexer->token["value"]);
|
||||
}
|
||||
return new ValidEmail();
|
||||
}
|
||||
|
||||
protected function parseLeftFromAt(): Result
|
||||
{
|
||||
return $this->processLocalPart();
|
||||
}
|
||||
|
||||
protected function parseRightFromAt(): Result
|
||||
{
|
||||
return $this->processDomainPart();
|
||||
}
|
||||
|
||||
private function processLocalPart() : Result
|
||||
{
|
||||
$this->lexer->startRecording();
|
||||
$localPartParser = new LocalPart($this->lexer);
|
||||
$localPartResult = $localPartParser->parse();
|
||||
$this->lexer->stopRecording();
|
||||
$this->localPart = rtrim($this->lexer->getAccumulatedValues(), '@');
|
||||
$this->localPart = $localPartParser->localPart();
|
||||
$this->warnings = array_merge($localPartParser->getWarnings(), $this->warnings);
|
||||
|
||||
return $localPartResult;
|
||||
@@ -83,28 +64,14 @@ class EmailParser
|
||||
|
||||
private function processDomainPart() : Result
|
||||
{
|
||||
$this->lexer->clearRecorded();
|
||||
$this->lexer->startRecording();
|
||||
$domainPartParser = new DomainPart($this->lexer);
|
||||
$domainPartResult = $domainPartParser->parse();
|
||||
$this->lexer->stopRecording();
|
||||
$this->domainPart = $this->lexer->getAccumulatedValues();
|
||||
$this->domainPart = $domainPartParser->domainPart();
|
||||
$this->warnings = array_merge($domainPartParser->getWarnings(), $this->warnings);
|
||||
|
||||
return $domainPartResult;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Warning\Warning[]
|
||||
*/
|
||||
public function getWarnings() : array
|
||||
{
|
||||
return $this->warnings;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getDomainPart() : string
|
||||
{
|
||||
return $this->domainPart;
|
||||
@@ -115,25 +82,7 @@ class EmailParser
|
||||
return $this->localPart;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
*/
|
||||
protected function hasAtToken() : bool
|
||||
{
|
||||
$this->lexer->moveNext();
|
||||
$this->lexer->moveNext();
|
||||
if ($this->lexer->token['type'] === EmailLexer::S_AT) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $localPart
|
||||
* @param string $parsedDomainPart
|
||||
*/
|
||||
protected function addLongEmailWarning($localPart, $parsedDomainPart) : void
|
||||
private function addLongEmailWarning(string $localPart, string $parsedDomainPart) : void
|
||||
{
|
||||
if (strlen($localPart . '@' . $parsedDomainPart) > self::EMAIL_MAX_LENGTH) {
|
||||
$this->warnings[EmailTooLong::CODE] = new EmailTooLong();
|
||||
|
||||
@@ -0,0 +1,93 @@
|
||||
<?php
|
||||
|
||||
namespace Egulias\EmailValidator;
|
||||
|
||||
use Egulias\EmailValidator\Parser;
|
||||
use Egulias\EmailValidator\EmailLexer;
|
||||
use Egulias\EmailValidator\Result\Result;
|
||||
use Egulias\EmailValidator\Parser\IDLeftPart;
|
||||
use Egulias\EmailValidator\Parser\IDRightPart;
|
||||
use Egulias\EmailValidator\Result\ValidEmail;
|
||||
use Egulias\EmailValidator\Result\InvalidEmail;
|
||||
use Egulias\EmailValidator\Warning\EmailTooLong;
|
||||
use Egulias\EmailValidator\Result\Reason\NoLocalPart;
|
||||
|
||||
class MessageIDParser extends Parser
|
||||
{
|
||||
|
||||
const EMAILID_MAX_LENGTH = 254;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
protected $idLeft = '';
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
protected $idRight = '';
|
||||
|
||||
public function parse(string $str) : Result
|
||||
{
|
||||
$result = parent::parse($str);
|
||||
|
||||
$this->addLongEmailWarning($this->idLeft, $this->idRight);
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
protected function preLeftParsing(): Result
|
||||
{
|
||||
if (!$this->hasAtToken()) {
|
||||
return new InvalidEmail(new NoLocalPart(), $this->lexer->token["value"]);
|
||||
}
|
||||
return new ValidEmail();
|
||||
}
|
||||
|
||||
protected function parseLeftFromAt(): Result
|
||||
{
|
||||
return $this->processIDLeft();
|
||||
}
|
||||
|
||||
protected function parseRightFromAt(): Result
|
||||
{
|
||||
return $this->processIDRight();
|
||||
}
|
||||
|
||||
private function processIDLeft() : Result
|
||||
{
|
||||
$localPartParser = new IDLeftPart($this->lexer);
|
||||
$localPartResult = $localPartParser->parse();
|
||||
$this->idLeft = $localPartParser->localPart();
|
||||
$this->warnings = array_merge($localPartParser->getWarnings(), $this->warnings);
|
||||
|
||||
return $localPartResult;
|
||||
}
|
||||
|
||||
private function processIDRight() : Result
|
||||
{
|
||||
$domainPartParser = new IDRightPart($this->lexer);
|
||||
$domainPartResult = $domainPartParser->parse();
|
||||
$this->idRight = $domainPartParser->domainPart();
|
||||
$this->warnings = array_merge($domainPartParser->getWarnings(), $this->warnings);
|
||||
|
||||
return $domainPartResult;
|
||||
}
|
||||
|
||||
public function getLeftPart() : string
|
||||
{
|
||||
return $this->idLeft;
|
||||
}
|
||||
|
||||
public function getRightPart() : string
|
||||
{
|
||||
return $this->idRight;
|
||||
}
|
||||
|
||||
private function addLongEmailWarning(string $localPart, string $parsedDomainPart) : void
|
||||
{
|
||||
if (strlen($localPart . '@' . $parsedDomainPart) > self::EMAILID_MAX_LENGTH) {
|
||||
$this->warnings[EmailTooLong::CODE] = new EmailTooLong();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,78 @@
|
||||
<?php
|
||||
|
||||
namespace Egulias\EmailValidator;
|
||||
|
||||
use Egulias\EmailValidator\Result\Result;
|
||||
use Egulias\EmailValidator\Result\ValidEmail;
|
||||
use Egulias\EmailValidator\Result\InvalidEmail;
|
||||
use Egulias\EmailValidator\Result\Reason\ExpectingATEXT;
|
||||
|
||||
abstract class Parser
|
||||
{
|
||||
/**
|
||||
* @var Warning\Warning[]
|
||||
*/
|
||||
protected $warnings = [];
|
||||
|
||||
/**
|
||||
* @var EmailLexer
|
||||
*/
|
||||
protected $lexer;
|
||||
|
||||
/**
|
||||
* id-left "@" id-right
|
||||
*/
|
||||
abstract protected function parseRightFromAt() : Result;
|
||||
abstract protected function parseLeftFromAt() : Result;
|
||||
abstract protected function preLeftParsing() : Result;
|
||||
|
||||
|
||||
public function __construct(EmailLexer $lexer)
|
||||
{
|
||||
$this->lexer = $lexer;
|
||||
}
|
||||
|
||||
public function parse(string $str) : Result
|
||||
{
|
||||
$this->lexer->setInput($str);
|
||||
|
||||
if ($this->lexer->hasInvalidTokens()) {
|
||||
return new InvalidEmail(new ExpectingATEXT("Invalid tokens found"), $this->lexer->token["value"]);
|
||||
}
|
||||
|
||||
$preParsingResult = $this->preLeftParsing();
|
||||
if ($preParsingResult->isInvalid()) {
|
||||
return $preParsingResult;
|
||||
}
|
||||
|
||||
$localPartResult = $this->parseLeftFromAt();
|
||||
|
||||
if ($localPartResult->isInvalid()) {
|
||||
return $localPartResult;
|
||||
}
|
||||
|
||||
$domainPartResult = $this->parseRightFromAt();
|
||||
|
||||
if ($domainPartResult->isInvalid()) {
|
||||
return $domainPartResult;
|
||||
}
|
||||
|
||||
return new ValidEmail();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Warning\Warning[]
|
||||
*/
|
||||
public function getWarnings() : array
|
||||
{
|
||||
return $this->warnings;
|
||||
}
|
||||
|
||||
protected function hasAtToken() : bool
|
||||
{
|
||||
$this->lexer->moveNext();
|
||||
$this->lexer->moveNext();
|
||||
|
||||
return $this->lexer->token['type'] !== EmailLexer::S_AT;
|
||||
}
|
||||
}
|
||||
@@ -11,7 +11,7 @@ use Egulias\EmailValidator\Result\Reason\UnclosedComment;
|
||||
use Egulias\EmailValidator\Result\Reason\UnOpenedComment;
|
||||
use Egulias\EmailValidator\Warning\Comment as WarningComment;
|
||||
|
||||
class Comment extends Parser
|
||||
class Comment extends PartParser
|
||||
{
|
||||
/**
|
||||
* @var int
|
||||
|
||||
@@ -20,7 +20,7 @@ use Egulias\EmailValidator\Result\Reason\ExpectingDTEXT;
|
||||
use Egulias\EmailValidator\Result\Reason\UnusualElements;
|
||||
use Egulias\EmailValidator\Warning\DomainLiteral as WarningDomainLiteral;
|
||||
|
||||
class DomainLiteral extends Parser
|
||||
class DomainLiteral extends PartParser
|
||||
{
|
||||
public function parse() : Result
|
||||
{
|
||||
|
||||
+33
-31
@@ -22,7 +22,7 @@ use Egulias\EmailValidator\Parser\CommentStrategy\DomainComment;
|
||||
use Egulias\EmailValidator\Result\Reason\ExpectingDomainLiteralClose;
|
||||
use Egulias\EmailValidator\Parser\DomainLiteral as DomainLiteralParser;
|
||||
|
||||
class DomainPart extends Parser
|
||||
class DomainPart extends PartParser
|
||||
{
|
||||
const DOMAIN_MAX_LENGTH = 253;
|
||||
const LABEL_MAX_LENGTH = 63;
|
||||
@@ -39,6 +39,9 @@ class DomainPart extends Parser
|
||||
|
||||
public function parse() : Result
|
||||
{
|
||||
$this->lexer->clearRecorded();
|
||||
$this->lexer->startRecording();
|
||||
|
||||
$this->lexer->moveNext();
|
||||
|
||||
$domainChecks = $this->performDomainStartChecks();
|
||||
@@ -49,20 +52,22 @@ class DomainPart extends Parser
|
||||
if ($this->lexer->token['type'] === EmailLexer::S_AT) {
|
||||
return new InvalidEmail(new ConsecutiveAt(), $this->lexer->token['value']);
|
||||
}
|
||||
$domain = $this->doParseDomainPart();
|
||||
if ($domain->isInvalid()) {
|
||||
return $domain;
|
||||
}
|
||||
|
||||
$length = strlen($this->domainPart);
|
||||
$result = $this->doParseDomainPart();
|
||||
if ($result->isInvalid()) {
|
||||
return $result;
|
||||
}
|
||||
|
||||
$end = $this->checkEndOfDomain();
|
||||
if ($end->isInvalid()) {
|
||||
return $end;
|
||||
}
|
||||
|
||||
$this->lexer->stopRecording();
|
||||
$this->domainPart = $this->lexer->getAccumulatedValues();
|
||||
|
||||
$length = strlen($this->domainPart);
|
||||
if ($length > self::DOMAIN_MAX_LENGTH) {
|
||||
//$this->warnings[DomainTooLong::CODE] = new DomainTooLong();
|
||||
return new InvalidEmail(new DomainTooLong(), $this->lexer->token['value']);
|
||||
}
|
||||
|
||||
@@ -128,14 +133,6 @@ class DomainPart extends Parser
|
||||
return new ValidEmail();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getDomainPart()
|
||||
{
|
||||
return $this->domainPart;
|
||||
}
|
||||
|
||||
protected function parseComments(): Result
|
||||
{
|
||||
$commentParser = new Comment($this->lexer, new DomainComment());
|
||||
@@ -229,7 +226,6 @@ class DomainPart extends Parser
|
||||
*/
|
||||
protected function parseDomainLiteral() : Result
|
||||
{
|
||||
|
||||
try {
|
||||
$this->lexer->find(EmailLexer::S_CLOSEBRACKET);
|
||||
} catch (\RuntimeException $e) {
|
||||
@@ -242,22 +238,8 @@ class DomainPart extends Parser
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return InvalidEmail|ValidEmail
|
||||
*/
|
||||
protected function checkDomainPartExceptions(array $prev, bool $hasComments) : Result
|
||||
{
|
||||
$validDomainTokens = array(
|
||||
EmailLexer::GENERIC => true,
|
||||
EmailLexer::S_HYPHEN => true,
|
||||
EmailLexer::S_DOT => true,
|
||||
);
|
||||
|
||||
if ($hasComments) {
|
||||
$validDomainTokens[EmailLexer::S_OPENPARENTHESIS] = true;
|
||||
$validDomainTokens[EmailLexer::S_CLOSEPARENTHESIS] = true;
|
||||
}
|
||||
|
||||
if ($this->lexer->token['type'] === EmailLexer::S_OPENBRACKET && $prev['type'] !== EmailLexer::S_AT) {
|
||||
return new InvalidEmail(new ExpectingATEXT('OPENBRACKET not after AT'), $this->lexer->token['value']);
|
||||
}
|
||||
@@ -271,6 +253,22 @@ class DomainPart extends Parser
|
||||
return new InvalidEmail(new ExpectingATEXT('Escaping following "ATOM"'), $this->lexer->token['value']);
|
||||
}
|
||||
|
||||
return $this->validateTokens($hasComments);
|
||||
}
|
||||
|
||||
protected function validateTokens(bool $hasComments) : Result
|
||||
{
|
||||
$validDomainTokens = array(
|
||||
EmailLexer::GENERIC => true,
|
||||
EmailLexer::S_HYPHEN => true,
|
||||
EmailLexer::S_DOT => true,
|
||||
);
|
||||
|
||||
if ($hasComments) {
|
||||
$validDomainTokens[EmailLexer::S_OPENPARENTHESIS] = true;
|
||||
$validDomainTokens[EmailLexer::S_CLOSEPARENTHESIS] = true;
|
||||
}
|
||||
|
||||
if (!isset($validDomainTokens[$this->lexer->token['type']])) {
|
||||
return new InvalidEmail(new ExpectingATEXT('Invalid token in domain: ' . $this->lexer->token['value']), $this->lexer->token['value']);
|
||||
}
|
||||
@@ -278,7 +276,6 @@ class DomainPart extends Parser
|
||||
return new ValidEmail();
|
||||
}
|
||||
|
||||
|
||||
private function checkLabelLength(bool $isEndOfDomain = false) : Result
|
||||
{
|
||||
if ($this->lexer->token['type'] === EmailLexer::S_DOT || $isEndOfDomain) {
|
||||
@@ -307,4 +304,9 @@ class DomainPart extends Parser
|
||||
$this->warnings[TLD::CODE] = new TLD();
|
||||
}
|
||||
}
|
||||
|
||||
public function domainPart() : string
|
||||
{
|
||||
return $this->domainPart;
|
||||
}
|
||||
}
|
||||
@@ -11,7 +11,7 @@ use Egulias\EmailValidator\Result\Reason\ExpectingATEXT;
|
||||
use Egulias\EmailValidator\Result\Reason\UnclosedQuotedString;
|
||||
use Egulias\EmailValidator\Result\Result;
|
||||
|
||||
class DoubleQuote extends Parser
|
||||
class DoubleQuote extends PartParser
|
||||
{
|
||||
public function parse() : Result
|
||||
{
|
||||
|
||||
@@ -13,7 +13,7 @@ use Egulias\EmailValidator\Result\Reason\ExpectingCTEXT;
|
||||
use Egulias\EmailValidator\Result\Result;
|
||||
use Egulias\EmailValidator\Result\ValidEmail;
|
||||
|
||||
class FoldingWhiteSpace extends Parser
|
||||
class FoldingWhiteSpace extends PartParser
|
||||
{
|
||||
public function parse() : Result
|
||||
{
|
||||
@@ -23,7 +23,10 @@ class FoldingWhiteSpace extends Parser
|
||||
|
||||
$previous = $this->lexer->getPrevious();
|
||||
|
||||
$this->checkCRLFInFWS();
|
||||
$resultCRLF = $this->checkCRLFInFWS();
|
||||
if ($resultCRLF->isInvalid()) {
|
||||
return $resultCRLF;
|
||||
}
|
||||
|
||||
if ($this->lexer->token['type'] === EmailLexer::S_CR) {
|
||||
return new InvalidEmail(new CRNoLF(), $this->lexer->token['value']);
|
||||
@@ -46,10 +49,7 @@ class FoldingWhiteSpace extends Parser
|
||||
return new ValidEmail();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return InvalidEmail|ValidEmail|null
|
||||
*/
|
||||
protected function checkCRLFInFWS()
|
||||
protected function checkCRLFInFWS() : Result
|
||||
{
|
||||
if ($this->lexer->token['type'] !== EmailLexer::CRLF) {
|
||||
return new ValidEmail();
|
||||
@@ -63,12 +63,11 @@ class FoldingWhiteSpace extends Parser
|
||||
if (!$this->lexer->isNextTokenAny(array(EmailLexer::S_SP, EmailLexer::S_HTAB))) {
|
||||
return new InvalidEmail(new CRLFAtTheEnd(), $this->lexer->token['value']);
|
||||
}
|
||||
|
||||
return new ValidEmail();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
*/
|
||||
protected function isFWS()
|
||||
protected function isFWS() : bool
|
||||
{
|
||||
if ($this->escaped()) {
|
||||
return false;
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
<?php
|
||||
|
||||
namespace Egulias\EmailValidator\Parser;
|
||||
|
||||
use Egulias\EmailValidator\Result\Result;
|
||||
use Egulias\EmailValidator\Parser\LocalPart;
|
||||
use Egulias\EmailValidator\Result\InvalidEmail;
|
||||
use Egulias\EmailValidator\Result\Reason\CommentsInIDRight;
|
||||
|
||||
class IDLeftPart extends LocalPart
|
||||
{
|
||||
protected function parseComments(): Result
|
||||
{
|
||||
return new InvalidEmail(new CommentsInIDRight(), $this->lexer->token['value']);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
<?php
|
||||
|
||||
namespace Egulias\EmailValidator\Parser;
|
||||
|
||||
use Egulias\EmailValidator\EmailLexer;
|
||||
use Egulias\EmailValidator\Result\Result;
|
||||
use Egulias\EmailValidator\Result\ValidEmail;
|
||||
use Egulias\EmailValidator\Result\InvalidEmail;
|
||||
use Egulias\EmailValidator\Result\Reason\ExpectingATEXT;
|
||||
|
||||
class IDRightPart extends DomainPart
|
||||
{
|
||||
protected function validateTokens(bool $hasComments) : Result
|
||||
{
|
||||
$invalidDomainTokens = array(
|
||||
EmailLexer::S_DQUOTE => true,
|
||||
EmailLexer::S_SQUOTE => true,
|
||||
EmailLexer::S_BACKTICK => true,
|
||||
EmailLexer::S_SEMICOLON => true,
|
||||
EmailLexer::S_GREATERTHAN => true,
|
||||
EmailLexer::S_LOWERTHAN => true,
|
||||
);
|
||||
|
||||
if (isset($invalidDomainTokens[$this->lexer->token['type']])) {
|
||||
return new InvalidEmail(new ExpectingATEXT('Invalid token in domain: ' . $this->lexer->token['value']), $this->lexer->token['value']);
|
||||
}
|
||||
return new ValidEmail();
|
||||
}
|
||||
}
|
||||
+35
-20
@@ -13,27 +13,17 @@ use Egulias\EmailValidator\Result\Reason\ConsecutiveDot;
|
||||
use Egulias\EmailValidator\Result\Reason\ExpectingATEXT;
|
||||
use Egulias\EmailValidator\Parser\CommentStrategy\LocalComment;
|
||||
|
||||
class LocalPart extends Parser
|
||||
class LocalPart extends PartParser
|
||||
{
|
||||
|
||||
/**
|
||||
* Invalid lexer tokens for local part
|
||||
* @var array
|
||||
* @var string
|
||||
*/
|
||||
private $invalidTokens = array(
|
||||
EmailLexer::S_COMMA => EmailLexer::S_COMMA,
|
||||
EmailLexer::S_CLOSEBRACKET => EmailLexer::S_CLOSEBRACKET,
|
||||
EmailLexer::S_OPENBRACKET => EmailLexer::S_OPENBRACKET,
|
||||
EmailLexer::S_GREATERTHAN => EmailLexer::S_GREATERTHAN,
|
||||
EmailLexer::S_LOWERTHAN => EmailLexer::S_LOWERTHAN,
|
||||
EmailLexer::S_COLON => EmailLexer::S_COLON,
|
||||
EmailLexer::S_SEMICOLON => EmailLexer::S_SEMICOLON,
|
||||
EmailLexer::INVALID => EmailLexer::INVALID
|
||||
);
|
||||
private $localPart = '';
|
||||
|
||||
|
||||
public function parse() : Result
|
||||
{
|
||||
$totalLength = 0;
|
||||
$this->lexer->startRecording();
|
||||
|
||||
while ($this->lexer->token['type'] !== EmailLexer::S_AT && null !== $this->lexer->token['type']) {
|
||||
if ($this->hasDotAtStart()) {
|
||||
@@ -74,8 +64,9 @@ class LocalPart extends Parser
|
||||
return $resultEscaping;
|
||||
}
|
||||
|
||||
if (isset($this->invalidTokens[$this->lexer->token['type']])) {
|
||||
return new InvalidEmail(new ExpectingATEXT('Invalid token found'), $this->lexer->token['value']);
|
||||
$resultToken = $this->validateTokens(false);
|
||||
if ($resultToken->isInvalid()) {
|
||||
return $resultToken;
|
||||
}
|
||||
|
||||
$resultFWS = $this->parseLocalFWS();
|
||||
@@ -83,17 +74,41 @@ class LocalPart extends Parser
|
||||
return $resultFWS;
|
||||
}
|
||||
|
||||
$totalLength += strlen($this->lexer->token['value']);
|
||||
$this->lexer->moveNext();
|
||||
}
|
||||
|
||||
if ($totalLength > LocalTooLong::LOCAL_PART_LENGTH) {
|
||||
$this->lexer->stopRecording();
|
||||
$this->localPart = rtrim($this->lexer->getAccumulatedValues(), '@');
|
||||
if (strlen($this->localPart) > LocalTooLong::LOCAL_PART_LENGTH) {
|
||||
$this->warnings[LocalTooLong::CODE] = new LocalTooLong();
|
||||
}
|
||||
|
||||
return new ValidEmail();
|
||||
}
|
||||
|
||||
protected function validateTokens(bool $hasComments) : Result
|
||||
{
|
||||
$invalidTokens = array(
|
||||
EmailLexer::S_COMMA => EmailLexer::S_COMMA,
|
||||
EmailLexer::S_CLOSEBRACKET => EmailLexer::S_CLOSEBRACKET,
|
||||
EmailLexer::S_OPENBRACKET => EmailLexer::S_OPENBRACKET,
|
||||
EmailLexer::S_GREATERTHAN => EmailLexer::S_GREATERTHAN,
|
||||
EmailLexer::S_LOWERTHAN => EmailLexer::S_LOWERTHAN,
|
||||
EmailLexer::S_COLON => EmailLexer::S_COLON,
|
||||
EmailLexer::S_SEMICOLON => EmailLexer::S_SEMICOLON,
|
||||
EmailLexer::INVALID => EmailLexer::INVALID
|
||||
);
|
||||
if (isset($invalidTokens[$this->lexer->token['type']])) {
|
||||
return new InvalidEmail(new ExpectingATEXT('Invalid token found'), $this->lexer->token['value']);
|
||||
}
|
||||
return new ValidEmail();
|
||||
}
|
||||
|
||||
public function localPart() : string
|
||||
{
|
||||
return $this->localPart;
|
||||
}
|
||||
|
||||
private function parseLocalFWS() : Result
|
||||
{
|
||||
$foldingWS = new FoldingWhiteSpace($this->lexer);
|
||||
@@ -118,7 +133,7 @@ class LocalPart extends Parser
|
||||
return $parseAgain;
|
||||
}
|
||||
|
||||
private function parseComments(): Result
|
||||
protected function parseComments(): Result
|
||||
{
|
||||
$commentParser = new Comment($this->lexer, new LocalComment());
|
||||
$result = $commentParser->parse();
|
||||
|
||||
@@ -8,7 +8,7 @@ use Egulias\EmailValidator\Result\Reason\ConsecutiveDot;
|
||||
use Egulias\EmailValidator\Result\Result;
|
||||
use Egulias\EmailValidator\Result\ValidEmail;
|
||||
|
||||
abstract class Parser
|
||||
abstract class PartParser
|
||||
{
|
||||
/**
|
||||
* @var array
|
||||
@@ -25,6 +25,8 @@ abstract class Parser
|
||||
$this->lexer = $lexer;
|
||||
}
|
||||
|
||||
abstract public function parse() : Result;
|
||||
|
||||
/**
|
||||
* @return \Egulias\EmailValidator\Warning\Warning[]
|
||||
*/
|
||||
@@ -33,8 +35,6 @@ abstract class Parser
|
||||
return $this->warnings;
|
||||
}
|
||||
|
||||
abstract public function parse() : Result;
|
||||
|
||||
protected function parseFWS() : Result
|
||||
{
|
||||
$foldingWS = new FoldingWhiteSpace($this->lexer);
|
||||
@@ -52,9 +52,6 @@ abstract class Parser
|
||||
return new ValidEmail();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
*/
|
||||
protected function escaped() : bool
|
||||
{
|
||||
$previous = $this->lexer->getPrevious();
|
||||
@@ -0,0 +1,16 @@
|
||||
<?php
|
||||
|
||||
namespace Egulias\EmailValidator\Result\Reason;
|
||||
|
||||
class CommentsInIDRight implements Reason
|
||||
{
|
||||
public function code() : int
|
||||
{
|
||||
return 400;
|
||||
}
|
||||
|
||||
public function description() : string
|
||||
{
|
||||
return 'Comments are not allowed in IDRight for message-id';
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
<?php
|
||||
|
||||
namespace Egulias\EmailValidator\Validation;
|
||||
|
||||
use Egulias\EmailValidator\EmailLexer;
|
||||
use Egulias\EmailValidator\MessageIDParser;
|
||||
use Egulias\EmailValidator\Result\InvalidEmail;
|
||||
use Egulias\EmailValidator\Result\Reason\ExceptionFound;
|
||||
|
||||
class MessageIDValidation implements EmailValidation
|
||||
{
|
||||
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
private $warnings = [];
|
||||
|
||||
/**
|
||||
* @var ?InvalidEmail
|
||||
*/
|
||||
private $error;
|
||||
|
||||
public function isValid(string $email, EmailLexer $emailLexer): bool
|
||||
{
|
||||
$parser = new MessageIDParser($emailLexer);
|
||||
try {
|
||||
$result = $parser->parse($email);
|
||||
$this->warnings = $parser->getWarnings();
|
||||
if ($result->isInvalid()) {
|
||||
/** @psalm-suppress PropertyTypeCoercion */
|
||||
$this->error = $result;
|
||||
return false;
|
||||
}
|
||||
} catch (\Exception $invalid) {
|
||||
$this->error = new InvalidEmail(new ExceptionFound($invalid), '');
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public function getWarnings(): array
|
||||
{
|
||||
return $this->warnings;
|
||||
}
|
||||
|
||||
public function getError(): ?InvalidEmail
|
||||
{
|
||||
return $this->error;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,70 @@
|
||||
<?php
|
||||
|
||||
namespace Egulias\EmailValidator\Tests\EmailValidator\Validation;
|
||||
|
||||
use Egulias\EmailValidator\EmailLexer;
|
||||
use Egulias\EmailValidator\Validation\MessageIDValidation;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
class MessageIDValidationTest extends TestCase
|
||||
{
|
||||
|
||||
/**
|
||||
* @dataProvider validMessageIDs
|
||||
*/
|
||||
public function testValidMessageIDs(string $messageID)
|
||||
{
|
||||
$validator = new MessageIDValidation();
|
||||
|
||||
$this->assertTrue($validator->isValid($messageID, new EmailLexer()));
|
||||
}
|
||||
|
||||
public function validMessageIDs() : array
|
||||
{
|
||||
return [
|
||||
['a@b.c+&%$.d'],
|
||||
['a.b+&%$.c@d'],
|
||||
['a@ä'],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider invalidMessageIDs
|
||||
*/
|
||||
public function testInvalidMessageIDs(string $messageID)
|
||||
{
|
||||
$validator = new MessageIDValidation();
|
||||
|
||||
$this->assertFalse($validator->isValid($messageID, new EmailLexer()));
|
||||
}
|
||||
|
||||
public function invalidMessageIDs() : array
|
||||
{
|
||||
return [
|
||||
['example'],
|
||||
['example@with space'],
|
||||
['example@iana.'],
|
||||
['example@ia\na.'],
|
||||
/**
|
||||
* RFC 2822, section 3.6.4, Page 25
|
||||
* Since the msg-id has
|
||||
* a similar syntax to angle-addr (identical except that comments and
|
||||
* folding white space are not allowed), a good method is to put the
|
||||
* domain name (or a domain literal IP address) of the host on which the
|
||||
* message identifier was created on the right hand side of the "@", and
|
||||
* put a combination of the current absolute date and time along with
|
||||
* some other currently unique (perhaps sequential) identifier available
|
||||
* on the system (for example, a process id number) on the left hand
|
||||
* side.
|
||||
*/
|
||||
['example(comment)@example.com'],
|
||||
["\r\nFWS@example.com"]
|
||||
];
|
||||
}
|
||||
|
||||
public function testInvalidMessageIDsWithError()
|
||||
{
|
||||
$this->markTestIncomplete("missing error check");
|
||||
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user