updated-packages

This commit is contained in:
RafficMohammed
2023-01-08 00:13:22 +05:30
parent 3ff7df7487
commit da241bacb6
12659 changed files with 563377 additions and 510538 deletions

View File

@@ -0,0 +1,443 @@
<?php
namespace Egulias\EmailValidator\Parser;
use Egulias\EmailValidator\EmailLexer;
use Egulias\EmailValidator\Exception\CharNotAllowed;
use Egulias\EmailValidator\Exception\CommaInDomain;
use Egulias\EmailValidator\Exception\ConsecutiveAt;
use Egulias\EmailValidator\Exception\CRLFAtTheEnd;
use Egulias\EmailValidator\Exception\CRNoLF;
use Egulias\EmailValidator\Exception\DomainHyphened;
use Egulias\EmailValidator\Exception\DotAtEnd;
use Egulias\EmailValidator\Exception\DotAtStart;
use Egulias\EmailValidator\Exception\ExpectingATEXT;
use Egulias\EmailValidator\Exception\ExpectingDomainLiteralClose;
use Egulias\EmailValidator\Exception\ExpectingDTEXT;
use Egulias\EmailValidator\Exception\NoDomainPart;
use Egulias\EmailValidator\Exception\UnopenedComment;
use Egulias\EmailValidator\Warning\AddressLiteral;
use Egulias\EmailValidator\Warning\CFWSWithFWS;
use Egulias\EmailValidator\Warning\DeprecatedComment;
use Egulias\EmailValidator\Warning\DomainLiteral;
use Egulias\EmailValidator\Warning\DomainTooLong;
use Egulias\EmailValidator\Warning\IPV6BadChar;
use Egulias\EmailValidator\Warning\IPV6ColonEnd;
use Egulias\EmailValidator\Warning\IPV6ColonStart;
use Egulias\EmailValidator\Warning\IPV6Deprecated;
use Egulias\EmailValidator\Warning\IPV6DoubleColon;
use Egulias\EmailValidator\Warning\IPV6GroupCount;
use Egulias\EmailValidator\Warning\IPV6MaxGroups;
use Egulias\EmailValidator\Warning\LabelTooLong;
use Egulias\EmailValidator\Warning\ObsoleteDTEXT;
use Egulias\EmailValidator\Warning\TLD;
class DomainPart extends Parser
{
const DOMAIN_MAX_LENGTH = 254;
const LABEL_MAX_LENGTH = 63;
/**
* @var string
*/
protected $domainPart = '';
public function parse($domainPart)
{
$this->lexer->moveNext();
$this->performDomainStartChecks();
$domain = $this->doParseDomainPart();
$prev = $this->lexer->getPrevious();
$length = strlen($domain);
if ($prev['type'] === EmailLexer::S_DOT) {
throw new DotAtEnd();
}
if ($prev['type'] === EmailLexer::S_HYPHEN) {
throw new DomainHyphened();
}
if ($length > self::DOMAIN_MAX_LENGTH) {
$this->warnings[DomainTooLong::CODE] = new DomainTooLong();
}
if ($prev['type'] === EmailLexer::S_CR) {
throw new CRLFAtTheEnd();
}
$this->domainPart = $domain;
}
private function performDomainStartChecks()
{
$this->checkInvalidTokensAfterAT();
$this->checkEmptyDomain();
if ($this->lexer->token['type'] === EmailLexer::S_OPENPARENTHESIS) {
$this->warnings[DeprecatedComment::CODE] = new DeprecatedComment();
$this->parseDomainComments();
}
}
private function checkEmptyDomain()
{
$thereIsNoDomain = $this->lexer->token['type'] === EmailLexer::S_EMPTY ||
($this->lexer->token['type'] === EmailLexer::S_SP &&
!$this->lexer->isNextToken(EmailLexer::GENERIC));
if ($thereIsNoDomain) {
throw new NoDomainPart();
}
}
private function checkInvalidTokensAfterAT()
{
if ($this->lexer->token['type'] === EmailLexer::S_DOT) {
throw new DotAtStart();
}
if ($this->lexer->token['type'] === EmailLexer::S_HYPHEN) {
throw new DomainHyphened();
}
}
/**
* @return string
*/
public function getDomainPart()
{
return $this->domainPart;
}
/**
* @param string $addressLiteral
* @param int $maxGroups
*/
public function checkIPV6Tag($addressLiteral, $maxGroups = 8)
{
$prev = $this->lexer->getPrevious();
if ($prev['type'] === EmailLexer::S_COLON) {
$this->warnings[IPV6ColonEnd::CODE] = new IPV6ColonEnd();
}
$IPv6 = substr($addressLiteral, 5);
//Daniel Marschall's new IPv6 testing strategy
$matchesIP = explode(':', $IPv6);
$groupCount = count($matchesIP);
$colons = strpos($IPv6, '::');
if (count(preg_grep('/^[0-9A-Fa-f]{0,4}$/', $matchesIP, PREG_GREP_INVERT)) !== 0) {
$this->warnings[IPV6BadChar::CODE] = new IPV6BadChar();
}
if ($colons === false) {
// We need exactly the right number of groups
if ($groupCount !== $maxGroups) {
$this->warnings[IPV6GroupCount::CODE] = new IPV6GroupCount();
}
return;
}
if ($colons !== strrpos($IPv6, '::')) {
$this->warnings[IPV6DoubleColon::CODE] = new IPV6DoubleColon();
return;
}
if ($colons === 0 || $colons === (strlen($IPv6) - 2)) {
// RFC 4291 allows :: at the start or end of an address
//with 7 other groups in addition
++$maxGroups;
}
if ($groupCount > $maxGroups) {
$this->warnings[IPV6MaxGroups::CODE] = new IPV6MaxGroups();
} elseif ($groupCount === $maxGroups) {
$this->warnings[IPV6Deprecated::CODE] = new IPV6Deprecated();
}
}
/**
* @return string
*/
protected function doParseDomainPart()
{
$domain = '';
$label = '';
$openedParenthesis = 0;
do {
$prev = $this->lexer->getPrevious();
$this->checkNotAllowedChars($this->lexer->token);
if ($this->lexer->token['type'] === EmailLexer::S_OPENPARENTHESIS) {
$this->parseComments();
$openedParenthesis += $this->getOpenedParenthesis();
$this->lexer->moveNext();
$tmpPrev = $this->lexer->getPrevious();
if ($tmpPrev['type'] === EmailLexer::S_CLOSEPARENTHESIS) {
$openedParenthesis--;
}
}
if ($this->lexer->token['type'] === EmailLexer::S_CLOSEPARENTHESIS) {
if ($openedParenthesis === 0) {
throw new UnopenedComment();
} else {
$openedParenthesis--;
}
}
$this->checkConsecutiveDots();
$this->checkDomainPartExceptions($prev);
if ($this->hasBrackets()) {
$this->parseDomainLiteral();
}
if ($this->lexer->token['type'] === EmailLexer::S_DOT) {
$this->checkLabelLength($label);
$label = '';
} else {
$label .= $this->lexer->token['value'];
}
if ($this->isFWS()) {
$this->parseFWS();
}
$domain .= $this->lexer->token['value'];
$this->lexer->moveNext();
if ($this->lexer->token['type'] === EmailLexer::S_SP) {
throw new CharNotAllowed();
}
} while (null !== $this->lexer->token['type']);
$this->checkLabelLength($label);
return $domain;
}
private function checkNotAllowedChars(array $token)
{
$notAllowed = [EmailLexer::S_BACKSLASH => true, EmailLexer::S_SLASH=> true];
if (isset($notAllowed[$token['type']])) {
throw new CharNotAllowed();
}
}
/**
* @return string|false
*/
protected function parseDomainLiteral()
{
if ($this->lexer->isNextToken(EmailLexer::S_COLON)) {
$this->warnings[IPV6ColonStart::CODE] = new IPV6ColonStart();
}
if ($this->lexer->isNextToken(EmailLexer::S_IPV6TAG)) {
$lexer = clone $this->lexer;
$lexer->moveNext();
if ($lexer->isNextToken(EmailLexer::S_DOUBLECOLON)) {
$this->warnings[IPV6ColonStart::CODE] = new IPV6ColonStart();
}
}
return $this->doParseDomainLiteral();
}
/**
* @return string|false
*/
protected function doParseDomainLiteral()
{
$IPv6TAG = false;
$addressLiteral = '';
do {
if ($this->lexer->token['type'] === EmailLexer::C_NUL) {
throw new ExpectingDTEXT();
}
if ($this->lexer->token['type'] === EmailLexer::INVALID ||
$this->lexer->token['type'] === EmailLexer::C_DEL ||
$this->lexer->token['type'] === EmailLexer::S_LF
) {
$this->warnings[ObsoleteDTEXT::CODE] = new ObsoleteDTEXT();
}
if ($this->lexer->isNextTokenAny(array(EmailLexer::S_OPENQBRACKET, EmailLexer::S_OPENBRACKET))) {
throw new ExpectingDTEXT();
}
if ($this->lexer->isNextTokenAny(
array(EmailLexer::S_HTAB, EmailLexer::S_SP, $this->lexer->token['type'] === EmailLexer::CRLF)
)) {
$this->warnings[CFWSWithFWS::CODE] = new CFWSWithFWS();
$this->parseFWS();
}
if ($this->lexer->isNextToken(EmailLexer::S_CR)) {
throw new CRNoLF();
}
if ($this->lexer->token['type'] === EmailLexer::S_BACKSLASH) {
$this->warnings[ObsoleteDTEXT::CODE] = new ObsoleteDTEXT();
$addressLiteral .= $this->lexer->token['value'];
$this->lexer->moveNext();
$this->validateQuotedPair();
}
if ($this->lexer->token['type'] === EmailLexer::S_IPV6TAG) {
$IPv6TAG = true;
}
if ($this->lexer->token['type'] === EmailLexer::S_CLOSEQBRACKET) {
break;
}
$addressLiteral .= $this->lexer->token['value'];
} while ($this->lexer->moveNext());
$addressLiteral = str_replace('[', '', $addressLiteral);
$addressLiteral = $this->checkIPV4Tag($addressLiteral);
if (false === $addressLiteral) {
return $addressLiteral;
}
if (!$IPv6TAG) {
$this->warnings[DomainLiteral::CODE] = new DomainLiteral();
return $addressLiteral;
}
$this->warnings[AddressLiteral::CODE] = new AddressLiteral();
$this->checkIPV6Tag($addressLiteral);
return $addressLiteral;
}
/**
* @param string $addressLiteral
*
* @return string|false
*/
protected function checkIPV4Tag($addressLiteral)
{
$matchesIP = array();
// Extract IPv4 part from the end of the address-literal (if there is one)
if (preg_match(
'/\\b(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$/',
$addressLiteral,
$matchesIP
) > 0
) {
$index = strrpos($addressLiteral, $matchesIP[0]);
if ($index === 0) {
$this->warnings[AddressLiteral::CODE] = new AddressLiteral();
return false;
}
// Convert IPv4 part to IPv6 format for further testing
$addressLiteral = substr($addressLiteral, 0, (int) $index) . '0:0';
}
return $addressLiteral;
}
protected function checkDomainPartExceptions(array $prev)
{
$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']])) {
throw new ExpectingATEXT();
}
if ($this->lexer->token['type'] === EmailLexer::S_COMMA) {
throw new CommaInDomain();
}
if ($this->lexer->token['type'] === EmailLexer::S_AT) {
throw new ConsecutiveAt();
}
if ($this->lexer->token['type'] === EmailLexer::S_OPENQBRACKET && $prev['type'] !== EmailLexer::S_AT) {
throw new ExpectingATEXT();
}
if ($this->lexer->token['type'] === EmailLexer::S_HYPHEN && $this->lexer->isNextToken(EmailLexer::S_DOT)) {
throw new DomainHyphened();
}
if ($this->lexer->token['type'] === EmailLexer::S_BACKSLASH
&& $this->lexer->isNextToken(EmailLexer::GENERIC)) {
throw new ExpectingATEXT();
}
}
/**
* @return bool
*/
protected function hasBrackets()
{
if ($this->lexer->token['type'] !== EmailLexer::S_OPENBRACKET) {
return false;
}
try {
$this->lexer->find(EmailLexer::S_CLOSEBRACKET);
} catch (\RuntimeException $e) {
throw new ExpectingDomainLiteralClose();
}
return true;
}
/**
* @param string $label
*/
protected function checkLabelLength($label)
{
if ($this->isLabelTooLong($label)) {
$this->warnings[LabelTooLong::CODE] = new LabelTooLong();
}
}
/**
* @param string $label
* @return bool
*/
private function isLabelTooLong($label)
{
if (preg_match('/[^\x00-\x7F]/', $label)) {
idn_to_ascii($label, IDNA_DEFAULT, INTL_IDNA_VARIANT_UTS46, $idnaInfo);
return (bool) ($idnaInfo['errors'] & IDNA_ERROR_LABEL_TOO_LONG);
}
return strlen($label) > self::LABEL_MAX_LENGTH;
}
protected function parseDomainComments()
{
$this->isUnclosedComment();
while (!$this->lexer->isNextToken(EmailLexer::S_CLOSEPARENTHESIS)) {
$this->warnEscaping();
$this->lexer->moveNext();
}
$this->lexer->moveNext();
if ($this->lexer->isNextToken(EmailLexer::S_DOT)) {
throw new ExpectingATEXT();
}
}
protected function addTLDWarnings()
{
if ($this->warnings[DomainLiteral::CODE]) {
$this->warnings[TLD::CODE] = new TLD();
}
}
}

View File

@@ -0,0 +1,145 @@
<?php
namespace Egulias\EmailValidator\Parser;
use Egulias\EmailValidator\Exception\DotAtEnd;
use Egulias\EmailValidator\Exception\DotAtStart;
use Egulias\EmailValidator\EmailLexer;
use Egulias\EmailValidator\Exception\ExpectingAT;
use Egulias\EmailValidator\Exception\ExpectingATEXT;
use Egulias\EmailValidator\Exception\UnclosedQuotedString;
use Egulias\EmailValidator\Exception\UnopenedComment;
use Egulias\EmailValidator\Warning\CFWSWithFWS;
use Egulias\EmailValidator\Warning\LocalTooLong;
class LocalPart extends Parser
{
public function parse($localPart)
{
$parseDQuote = true;
$closingQuote = false;
$openedParenthesis = 0;
$totalLength = 0;
while ($this->lexer->token['type'] !== EmailLexer::S_AT && null !== $this->lexer->token['type']) {
if ($this->lexer->token['type'] === EmailLexer::S_DOT && null === $this->lexer->getPrevious()['type']) {
throw new DotAtStart();
}
$closingQuote = $this->checkDQUOTE($closingQuote);
if ($closingQuote && $parseDQuote) {
$parseDQuote = $this->parseDoubleQuote();
}
if ($this->lexer->token['type'] === EmailLexer::S_OPENPARENTHESIS) {
$this->parseComments();
$openedParenthesis += $this->getOpenedParenthesis();
}
if ($this->lexer->token['type'] === EmailLexer::S_CLOSEPARENTHESIS) {
if ($openedParenthesis === 0) {
throw new UnopenedComment();
}
$openedParenthesis--;
}
$this->checkConsecutiveDots();
if ($this->lexer->token['type'] === EmailLexer::S_DOT &&
$this->lexer->isNextToken(EmailLexer::S_AT)
) {
throw new DotAtEnd();
}
$this->warnEscaping();
$this->isInvalidToken($this->lexer->token, $closingQuote);
if ($this->isFWS()) {
$this->parseFWS();
}
$totalLength += strlen($this->lexer->token['value']);
$this->lexer->moveNext();
}
if ($totalLength > LocalTooLong::LOCAL_PART_LENGTH) {
$this->warnings[LocalTooLong::CODE] = new LocalTooLong();
}
}
/**
* @return bool
*/
protected function parseDoubleQuote()
{
$parseAgain = true;
$special = array(
EmailLexer::S_CR => true,
EmailLexer::S_HTAB => true,
EmailLexer::S_LF => true
);
$invalid = array(
EmailLexer::C_NUL => true,
EmailLexer::S_HTAB => true,
EmailLexer::S_CR => true,
EmailLexer::S_LF => true
);
$setSpecialsWarning = true;
$this->lexer->moveNext();
while ($this->lexer->token['type'] !== EmailLexer::S_DQUOTE && null !== $this->lexer->token['type']) {
$parseAgain = false;
if (isset($special[$this->lexer->token['type']]) && $setSpecialsWarning) {
$this->warnings[CFWSWithFWS::CODE] = new CFWSWithFWS();
$setSpecialsWarning = false;
}
if ($this->lexer->token['type'] === EmailLexer::S_BACKSLASH && $this->lexer->isNextToken(EmailLexer::S_DQUOTE)) {
$this->lexer->moveNext();
}
$this->lexer->moveNext();
if (!$this->escaped() && isset($invalid[$this->lexer->token['type']])) {
throw new ExpectingATEXT();
}
}
$prev = $this->lexer->getPrevious();
if ($prev['type'] === EmailLexer::S_BACKSLASH) {
if (!$this->checkDQUOTE(false)) {
throw new UnclosedQuotedString();
}
}
if (!$this->lexer->isNextToken(EmailLexer::S_AT) && $prev['type'] !== EmailLexer::S_BACKSLASH) {
throw new ExpectingAT();
}
return $parseAgain;
}
/**
* @param bool $closingQuote
*/
protected function isInvalidToken(array $token, $closingQuote)
{
$forbidden = array(
EmailLexer::S_COMMA,
EmailLexer::S_CLOSEBRACKET,
EmailLexer::S_OPENBRACKET,
EmailLexer::S_GREATERTHAN,
EmailLexer::S_LOWERTHAN,
EmailLexer::S_COLON,
EmailLexer::S_SEMICOLON,
EmailLexer::INVALID
);
if (in_array($token['type'], $forbidden) && !$closingQuote) {
throw new ExpectingATEXT();
}
}
}

View File

@@ -0,0 +1,249 @@
<?php
namespace Egulias\EmailValidator\Parser;
use Egulias\EmailValidator\EmailLexer;
use Egulias\EmailValidator\Exception\AtextAfterCFWS;
use Egulias\EmailValidator\Exception\ConsecutiveDot;
use Egulias\EmailValidator\Exception\CRLFAtTheEnd;
use Egulias\EmailValidator\Exception\CRLFX2;
use Egulias\EmailValidator\Exception\CRNoLF;
use Egulias\EmailValidator\Exception\ExpectingQPair;
use Egulias\EmailValidator\Exception\ExpectingATEXT;
use Egulias\EmailValidator\Exception\ExpectingCTEXT;
use Egulias\EmailValidator\Exception\UnclosedComment;
use Egulias\EmailValidator\Exception\UnclosedQuotedString;
use Egulias\EmailValidator\Warning\CFWSNearAt;
use Egulias\EmailValidator\Warning\CFWSWithFWS;
use Egulias\EmailValidator\Warning\Comment;
use Egulias\EmailValidator\Warning\QuotedPart;
use Egulias\EmailValidator\Warning\QuotedString;
abstract class Parser
{
/**
* @var array
*/
protected $warnings = [];
/**
* @var EmailLexer
*/
protected $lexer;
/**
* @var int
*/
protected $openedParenthesis = 0;
public function __construct(EmailLexer $lexer)
{
$this->lexer = $lexer;
}
/**
* @return \Egulias\EmailValidator\Warning\Warning[]
*/
public function getWarnings()
{
return $this->warnings;
}
/**
* @param string $str
*/
abstract public function parse($str);
/** @return int */
public function getOpenedParenthesis()
{
return $this->openedParenthesis;
}
/**
* validateQuotedPair
*/
protected function validateQuotedPair()
{
if (!($this->lexer->token['type'] === EmailLexer::INVALID
|| $this->lexer->token['type'] === EmailLexer::C_DEL)) {
throw new ExpectingQPair();
}
$this->warnings[QuotedPart::CODE] =
new QuotedPart($this->lexer->getPrevious()['type'], $this->lexer->token['type']);
}
protected function parseComments()
{
$this->openedParenthesis = 1;
$this->isUnclosedComment();
$this->warnings[Comment::CODE] = new Comment();
while (!$this->lexer->isNextToken(EmailLexer::S_CLOSEPARENTHESIS)) {
if ($this->lexer->isNextToken(EmailLexer::S_OPENPARENTHESIS)) {
$this->openedParenthesis++;
}
$this->warnEscaping();
$this->lexer->moveNext();
}
$this->lexer->moveNext();
if ($this->lexer->isNextTokenAny(array(EmailLexer::GENERIC, EmailLexer::S_EMPTY))) {
throw new ExpectingATEXT();
}
if ($this->lexer->isNextToken(EmailLexer::S_AT)) {
$this->warnings[CFWSNearAt::CODE] = new CFWSNearAt();
}
}
/**
* @return bool
*/
protected function isUnclosedComment()
{
try {
$this->lexer->find(EmailLexer::S_CLOSEPARENTHESIS);
return true;
} catch (\RuntimeException $e) {
throw new UnclosedComment();
}
}
protected function parseFWS()
{
$previous = $this->lexer->getPrevious();
$this->checkCRLFInFWS();
if ($this->lexer->token['type'] === EmailLexer::S_CR) {
throw new CRNoLF();
}
if ($this->lexer->isNextToken(EmailLexer::GENERIC) && $previous['type'] !== EmailLexer::S_AT) {
throw new AtextAfterCFWS();
}
if ($this->lexer->token['type'] === EmailLexer::S_LF || $this->lexer->token['type'] === EmailLexer::C_NUL) {
throw new ExpectingCTEXT();
}
if ($this->lexer->isNextToken(EmailLexer::S_AT) || $previous['type'] === EmailLexer::S_AT) {
$this->warnings[CFWSNearAt::CODE] = new CFWSNearAt();
} else {
$this->warnings[CFWSWithFWS::CODE] = new CFWSWithFWS();
}
}
protected function checkConsecutiveDots()
{
if ($this->lexer->token['type'] === EmailLexer::S_DOT && $this->lexer->isNextToken(EmailLexer::S_DOT)) {
throw new ConsecutiveDot();
}
}
/**
* @return bool
*/
protected function isFWS()
{
if ($this->escaped()) {
return false;
}
if ($this->lexer->token['type'] === EmailLexer::S_SP ||
$this->lexer->token['type'] === EmailLexer::S_HTAB ||
$this->lexer->token['type'] === EmailLexer::S_CR ||
$this->lexer->token['type'] === EmailLexer::S_LF ||
$this->lexer->token['type'] === EmailLexer::CRLF
) {
return true;
}
return false;
}
/**
* @return bool
*/
protected function escaped()
{
$previous = $this->lexer->getPrevious();
if ($previous && $previous['type'] === EmailLexer::S_BACKSLASH
&&
$this->lexer->token['type'] !== EmailLexer::GENERIC
) {
return true;
}
return false;
}
/**
* @return bool
*/
protected function warnEscaping()
{
if ($this->lexer->token['type'] !== EmailLexer::S_BACKSLASH) {
return false;
}
if ($this->lexer->isNextToken(EmailLexer::GENERIC)) {
throw new ExpectingATEXT();
}
if (!$this->lexer->isNextTokenAny(array(EmailLexer::S_SP, EmailLexer::S_HTAB, EmailLexer::C_DEL))) {
return false;
}
$this->warnings[QuotedPart::CODE] =
new QuotedPart($this->lexer->getPrevious()['type'], $this->lexer->token['type']);
return true;
}
/**
* @param bool $hasClosingQuote
*
* @return bool
*/
protected function checkDQUOTE($hasClosingQuote)
{
if ($this->lexer->token['type'] !== EmailLexer::S_DQUOTE) {
return $hasClosingQuote;
}
if ($hasClosingQuote) {
return $hasClosingQuote;
}
$previous = $this->lexer->getPrevious();
if ($this->lexer->isNextToken(EmailLexer::GENERIC) && $previous['type'] === EmailLexer::GENERIC) {
throw new ExpectingATEXT();
}
try {
$this->lexer->find(EmailLexer::S_DQUOTE);
$hasClosingQuote = true;
} catch (\Exception $e) {
throw new UnclosedQuotedString();
}
$this->warnings[QuotedString::CODE] = new QuotedString($previous['value'], $this->lexer->token['value']);
return $hasClosingQuote;
}
protected function checkCRLFInFWS()
{
if ($this->lexer->token['type'] !== EmailLexer::CRLF) {
return;
}
if (!$this->lexer->isNextTokenAny(array(EmailLexer::S_SP, EmailLexer::S_HTAB))) {
throw new CRLFX2();
}
if (!$this->lexer->isNextTokenAny(array(EmailLexer::S_SP, EmailLexer::S_HTAB))) {
throw new CRLFAtTheEnd();
}
}
}