Skip to content

Commit

Permalink
#80 validate number of closing parenthesis
Browse files Browse the repository at this point in the history
  • Loading branch information
whyte624 authored and egulias committed Oct 11, 2015
1 parent f6447f8 commit a7b3853
Show file tree
Hide file tree
Showing 5 changed files with 45 additions and 20 deletions.
1 change: 1 addition & 0 deletions src/Egulias/EmailValidator/EmailValidator.php
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ class EmailValidator
const ERR_FWS_CRLF_END = 149;
const ERR_CR_NO_LF = 150;
const ERR_DEPREC_REACHED = 151;
const ERR_UNOPENEDCOMMENT = 152;
const RFC5321_TLD = 9;
const RFC5321_TLDNUMERIC = 10;
const RFC5321_QUOTEDSTRING = 11;
Expand Down
18 changes: 14 additions & 4 deletions src/Egulias/EmailValidator/Parser/DomainPart.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@
namespace Egulias\EmailValidator\Parser;

use Egulias\EmailValidator\EmailLexer;
use Egulias\EmailValidator\Parser\Parser;
use Egulias\EmailValidator\EmailValidator;

class DomainPart extends Parser
Expand Down Expand Up @@ -103,17 +102,28 @@ public function checkIPV6Tag($addressLiteral, $maxGroups = 8)
protected function doParseDomainPart()
{
$domain = '';
$openedParenthesis = 0;
do {

$prev = $this->lexer->getPrevious();

if ($this->lexer->token['type'] === EmailLexer::S_SLASH) {
throw new \InvalidArgumentException('ERR_DOMAIN_CHAR_NOT_ALLOWED');
}

if ($this->lexer->token['type'] === EmailLexer::S_OPENPARENTHESIS) {
$this->parseComments();
$this->parseComments($openedParenthesis);
$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 \InvalidArgumentException('ERR_UNOPENEDCOMMENT');
} else {
$openedParenthesis--;
}
}

$this->checkConsecutiveDots();
Expand Down Expand Up @@ -180,7 +190,7 @@ protected function doParseDomainLiteral()
}

if ($this->lexer->isNextToken(EmailLexer::S_CR)) {
throw new \InvalidArgumentException("ERR_CR_NO_LF");
throw new \InvalidArgumentException('ERR_CR_NO_LF');
}
if ($this->lexer->token['type'] === EmailLexer::S_BACKSLASH) {
$this->warnings[] = EmailValidator::RFC5322_DOMLIT_OBSDTEXT;
Expand Down
21 changes: 13 additions & 8 deletions src/Egulias/EmailValidator/Parser/LocalPart.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,17 +4,16 @@

use Egulias\EmailValidator\EmailLexer;
use Egulias\EmailValidator\EmailValidator;
use \InvalidArgumentException;

class LocalPart extends Parser
{
public function parse($localPart)
{
$parseDQuote = true;
$closingQuote = false;
$openedParenthesis = 0;

while ($this->lexer->token['type'] !== EmailLexer::S_AT && $this->lexer->token) {

if ($this->lexer->token['type'] === EmailLexer::S_DOT && !$this->lexer->getPrevious()) {
throw new \InvalidArgumentException('ERR_DOT_START');
}
Expand All @@ -25,13 +24,19 @@ public function parse($localPart)
}

if ($this->lexer->token['type'] === EmailLexer::S_OPENPARENTHESIS) {
$this->parseComments();
$this->parseComments($openedParenthesis);
}
if ($this->lexer->token['type'] === EmailLexer::S_CLOSEPARENTHESIS) {
if ($openedParenthesis === 0) {
throw new \InvalidArgumentException('ERR_UNOPENEDCOMMENT');
} else {
$openedParenthesis--;
}
}

$this->checkConsecutiveDots();

if (
$this->lexer->token['type'] === EmailLexer::S_DOT &&
if ($this->lexer->token['type'] === EmailLexer::S_DOT &&
$this->lexer->isNextToken(EmailLexer::S_AT)
) {
throw new \InvalidArgumentException('ERR_DOT_END');
Expand Down Expand Up @@ -82,20 +87,20 @@ protected function parseDoubleQuote()
$this->lexer->moveNext();

if (!$this->escaped() && isset($invalid[$this->lexer->token['type']])) {
throw new InvalidArgumentException("ERR_EXPECTED_ATEXT");
throw new \InvalidArgumentException('ERR_EXPECTED_ATEXT');
}
}

$prev = $this->lexer->getPrevious();

if ($prev['type'] === EmailLexer::S_BACKSLASH) {
if (!$this->checkDQUOTE(false)) {
throw new \InvalidArgumentException("ERR_UNCLOSED_DQUOTE");
throw new \InvalidArgumentException('ERR_UNCLOSED_DQUOTE');
}
}

if (!$this->lexer->isNextToken(EmailLexer::S_AT) && $prev['type'] !== EmailLexer::S_BACKSLASH) {
throw new \InvalidArgumentException("ERR_EXPECED_AT");
throw new \InvalidArgumentException('ERR_EXPECED_AT');
}

return $parseAgain;
Expand Down
20 changes: 12 additions & 8 deletions src/Egulias/EmailValidator/Parser/Parser.php
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ public function getWarnings()
return $this->warnings;
}

abstract function parse($str);
abstract public function parse($str);

/**
* validateQuotedPair
Expand All @@ -36,14 +36,18 @@ protected function validateQuotedPair()
}

/**
* @return string the the comment
* @throws \InvalidArgumentException
* @param int $openedParenthesis
* @return string the comment
*/
protected function parseComments()
protected function parseComments(&$openedParenthesis = 0)
{
$openedParenthesis++;
$this->isUnclosedComment();
$this->warnings[] = EmailValidator::CFWS_COMMENT;
while (!$this->lexer->isNextToken(EmailLexer::S_CLOSEPARENTHESIS)) {
if ($this->lexer->isNextToken(EmailLexer::S_OPENPARENTHESIS)) {
$openedParenthesis++;
}
$this->warnEscaping();
$this->lexer->moveNext();
}
Expand Down Expand Up @@ -75,11 +79,11 @@ protected function parseFWS()
$this->checkCRLFInFWS();

if ($this->lexer->token['type'] === EmailLexer::S_CR) {
throw new \InvalidArgumentException("ERR_CR_NO_LF");
throw new \InvalidArgumentException('ERR_CR_NO_LF');
}

if ($this->lexer->isNextToken(EmailLexer::GENERIC) && $previous['type'] !== EmailLexer::S_AT) {
throw new \InvalidArgumentException("ERR_ATEXT_AFTER_CFWS");
throw new \InvalidArgumentException('ERR_ATEXT_AFTER_CFWS');
}

if ($this->lexer->token['type'] === EmailLexer::S_LF || $this->lexer->token['type'] === EmailLexer::C_NUL) {
Expand Down Expand Up @@ -181,10 +185,10 @@ protected function checkCRLFInFWS()
return;
}
if ($this->lexer->isNextToken(EmailLexer::CRLF)) {
throw new \InvalidArgumentException("ERR_FWS_CRLF_X2");
throw new \InvalidArgumentException('ERR_FWS_CRLF_X2');
}
if (!$this->lexer->isNextTokenAny(array(EmailLexer::S_SP, EmailLexer::S_HTAB))) {
throw new \InvalidArgumentException("ERR_FWS_CRLF_END");
throw new \InvalidArgumentException('ERR_FWS_CRLF_END');
}
}
}
5 changes: 5 additions & 0 deletions tests/egulias/Tests/EmailValidator/EmailValidatorTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,11 @@ public function getInvalidEmailsWithErrors()
array(EmailValidator::ERR_DOT_END, 'example@localhost.'),
array(EmailValidator::ERR_DOT_END, '[email protected]'),
array(EmailValidator::ERR_UNCLOSEDCOMMENT, '(example@localhost'),
array(EmailValidator::ERR_UNOPENEDCOMMENT, 'comment)example@localhost'),
array(EmailValidator::ERR_UNOPENEDCOMMENT, 'example(comment))@localhost'),
array(EmailValidator::ERR_UNOPENEDCOMMENT, 'example@comment)localhost'),
array(EmailValidator::ERR_UNOPENEDCOMMENT, 'example@localhost(comment))'),
array(EmailValidator::ERR_UNOPENEDCOMMENT, 'example@(comment))example.com'),
array(EmailValidator::ERR_UNCLOSEDQUOTEDSTR, '"example@localhost'),
array(EmailValidator::ERR_EXPECTING_ATEXT, 'exa"mple@localhost'),
//This was the original. But atext is not allowed after \n
Expand Down

0 comments on commit a7b3853

Please sign in to comment.