#19 and #10 - Improvement of QuotedPart parsing

This commit is contained in:
Eduardo Gulias Davis
2014-09-02 00:35:48 +02:00
parent 65afaf3f2b
commit 39b451bb2b
5 changed files with 92 additions and 14 deletions
@@ -84,6 +84,7 @@ class EmailLexer extends AbstractLexer
if (!$search->lookahead) {
throw new \UnexpectedValueException($type . ' not found');
}
return true;
}
/**
+49 -11
View File
@@ -3,7 +3,6 @@
namespace Egulias\EmailValidator\Parser;
use Egulias\EmailValidator\EmailLexer;
use Egulias\EmailValidator\Parser\Parser;
use Egulias\EmailValidator\EmailValidator;
@@ -11,7 +10,9 @@ class LocalPart extends Parser
{
public function parse($localPart)
{
$parseDQuote = true;
$closingQuote = false;
while ($this->lexer->token['type'] !== EmailLexer::S_AT && $this->lexer->token) {
if ($this->lexer->token['type'] === EmailLexer::S_DOT && !$this->lexer->getPrevious()) {
@@ -19,6 +20,10 @@ class LocalPart extends Parser
}
$closingQuote = $this->checkDQUOTE($closingQuote);
if ($closingQuote && $parseDQuote) {
$this->parseDoubleQuote();
$parseDQuote = false;
}
if ($this->lexer->token['type'] === EmailLexer::S_OPENPARENTHESIS) {
$this->parseComments();
@@ -26,20 +31,15 @@ class LocalPart extends Parser
$this->checkConsecutiveDots();
if ($this->lexer->token['type'] === EmailLexer::S_DOT && $this->lexer->isNextToken(EmailLexer::S_AT)) {
if (
$this->lexer->token['type'] === EmailLexer::S_DOT &&
$this->lexer->isNextToken(EmailLexer::S_AT)
) {
throw new \InvalidArgumentException('ERR_DOT_END');
}
$this->warnEscaping();
if ($this->lexer->isNextTokenAny(
array(
EmailLexer::INVALID, EmailLexer::S_LOWERTHAN, EmailLexer::S_GREATERTHAN
)
)
) {
throw new \InvalidArgumentException('ERR_EXPECTING_ATEXT');
}
$this->isInvalidToken($this->lexer->token, $closingQuote);
if ($this->isFWS()) {
$this->parseFWS();
@@ -53,4 +53,42 @@ class LocalPart extends Parser
$this->warnings[] = EmailValidator::RFC5322_LOCAL_TOOLONG;
}
}
protected function parseDoubleQuote()
{
$special = array (
EmailLexer::S_CR => true,
EmailLexer::S_HTAB => true,
EmailLexer::S_LF => true
);
$setSpecialsWarning = true;
$this->lexer->moveNext();
while ($this->lexer->token['type'] !== EmailLexer::S_DQUOTE && $this->lexer->token) {
if (isset($special[$this->lexer->token['type']]) && $setSpecialsWarning) {
$this->warnings[] = EmailValidator::CFWS_FWS;
$setSpecialsWarning = false;
}
$this->lexer->moveNext();
}
}
protected function isInvalidToken($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 \InvalidArgumentException('ERR_EXPECTING_ATEXT');
}
}
}
@@ -102,6 +102,10 @@ abstract class Parser
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 ||
@@ -114,6 +118,21 @@ abstract class Parser
return false;
}
protected function escaped()
{
$previous = $this->lexer->getPrevious();
if ($previous['type'] === EmailLexer::S_BACKSLASH
&&
($this->lexer->token['type'] === EmailLexer::S_SP ||
$this->lexer->token['type'] === EmailLexer::S_HTAB)
) {
return true;
}
return false;
}
protected function warnEscaping()
{
if ($this->lexer->token['type'] !== EmailLexer::S_BACKSLASH) {