mirror of
https://github.com/egulias/EmailValidator.git
synced 2026-09-01 21:19:25 +00:00
remove Zephir
This commit is contained in:
Binary file not shown.
@@ -1,102 +0,0 @@
|
||||
namespace Egulias\EmailValidator;
|
||||
|
||||
use Egulias\EmailValidator\Parser\DomainPart;
|
||||
use Egulias\EmailValidator\Parser\LocalPart;
|
||||
/**
|
||||
* EmailParser
|
||||
*
|
||||
* @author Eduardo Gulias Davis <me@egulias.com>
|
||||
*/
|
||||
class EmailParser
|
||||
{
|
||||
const EMAIL_MAX_LENGTH = 254;
|
||||
protected warnings = [];
|
||||
protected domainPart = "";
|
||||
protected localPart = "";
|
||||
protected lexer;
|
||||
protected localPartParser;
|
||||
protected domainPartParser;
|
||||
public function __construct(<EmailLexer> lexer) -> void
|
||||
{
|
||||
let this->lexer = lexer;
|
||||
let this->localPartParser = new LocalPart(this->lexer);
|
||||
let this->domainPartParser = new DomainPart(this->lexer);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $str
|
||||
* @return array
|
||||
*/
|
||||
public function parse(str) -> array
|
||||
{
|
||||
var tmpArray384eacd3233973d48b46f6665fe87aa5;
|
||||
|
||||
this->lexer->setInput(str);
|
||||
|
||||
if !this->hasAtToken() {
|
||||
throw new \InvalidArgumentException("ERR_NOLOCALPART");
|
||||
}
|
||||
this->localPartParser->parse(str);
|
||||
this->domainPartParser->parse(str);
|
||||
this->setParts(str);
|
||||
|
||||
if this->lexer->hasInvalidTokens() {
|
||||
throw new \InvalidArgumentException("ERR_INVALID_ATEXT");
|
||||
}
|
||||
let tmpArray384eacd3233973d48b46f6665fe87aa5 = ["local" : this->localPart, "domain" : this->domainPart];
|
||||
return tmpArray384eacd3233973d48b46f6665fe87aa5;
|
||||
}
|
||||
|
||||
public function getWarnings()
|
||||
{
|
||||
var localPartWarnings, domainPartWarnings;
|
||||
|
||||
let localPartWarnings = this->localPartParser->getWarnings();
|
||||
let domainPartWarnings = this->domainPartParser->getWarnings();
|
||||
let this->warnings = array_merge(localPartWarnings, domainPartWarnings);
|
||||
this->addLongEmailWarning(this->localPart, this->domainPart);
|
||||
|
||||
return this->warnings;
|
||||
}
|
||||
|
||||
public function getParsedDomainPart()
|
||||
{
|
||||
|
||||
return this->domainPart;
|
||||
}
|
||||
|
||||
protected function setParts(email) -> void
|
||||
{
|
||||
var parts;
|
||||
|
||||
let parts = explode("@", email);
|
||||
let this->domainPart = this->domainPartParser->getDomainPart();
|
||||
let this->localPart = parts[0];
|
||||
}
|
||||
|
||||
protected function hasAtToken()
|
||||
{
|
||||
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(string localPart, string parsedDomainPart) -> void
|
||||
{
|
||||
|
||||
if strlen(localPart . "@" . parsedDomainPart) > self::EMAIL_MAX_LENGTH {
|
||||
let this->warnings[] = EmailValidator::RFC5322_TOOLONG;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,172 +0,0 @@
|
||||
namespace Egulias\EmailValidator;
|
||||
|
||||
/**
|
||||
* EmailValidator
|
||||
*
|
||||
* @author Eduardo Gulias Davis <me@egulias.com>
|
||||
*/
|
||||
class EmailValidator
|
||||
{
|
||||
const ERR_CONSECUTIVEATS = 128;
|
||||
const ERR_EXPECTING_DTEXT = 129;
|
||||
const ERR_NOLOCALPART = 130;
|
||||
const ERR_NODOMAIN = 131;
|
||||
const ERR_CONSECUTIVEDOTS = 132;
|
||||
const ERR_ATEXT_AFTER_CFWS = 133;
|
||||
const ERR_ATEXT_AFTER_QS = 134;
|
||||
const ERR_ATEXT_AFTER_DOMLIT = 135;
|
||||
const ERR_EXPECTING_QPAIR = 136;
|
||||
const ERR_EXPECTING_ATEXT = 137;
|
||||
const ERR_EXPECTING_QTEXT = 138;
|
||||
const ERR_EXPECTING_CTEXT = 139;
|
||||
const ERR_BACKSLASHEND = 140;
|
||||
const ERR_DOT_START = 141;
|
||||
const ERR_DOT_END = 142;
|
||||
const ERR_DOMAINHYPHENSTART = 143;
|
||||
const ERR_DOMAINHYPHENEND = 144;
|
||||
const ERR_UNCLOSEDQUOTEDSTR = 145;
|
||||
const ERR_UNCLOSEDCOMMENT = 146;
|
||||
const ERR_UNCLOSEDDOMLIT = 147;
|
||||
const ERR_FWS_CRLF_X2 = 148;
|
||||
const ERR_FWS_CRLF_END = 149;
|
||||
const ERR_CR_NO_LF = 150;
|
||||
const ERR_DEPREC_REACHED = 151;
|
||||
const RFC5321_TLD = 9;
|
||||
const RFC5321_TLDNUMERIC = 10;
|
||||
const RFC5321_QUOTEDSTRING = 11;
|
||||
const RFC5321_ADDRESSLITERAL = 12;
|
||||
const RFC5321_IPV6DEPRECATED = 13;
|
||||
const CFWS_COMMENT = 17;
|
||||
const CFWS_FWS = 18;
|
||||
const DEPREC_LOCALPART = 33;
|
||||
const DEPREC_FWS = 34;
|
||||
const DEPREC_QTEXT = 35;
|
||||
const DEPREC_QP = 36;
|
||||
const DEPREC_COMMENT = 37;
|
||||
const DEPREC_CTEXT = 38;
|
||||
const DEPREC_CFWS_NEAR_AT = 49;
|
||||
const RFC5322_LOCAL_TOOLONG = 64;
|
||||
const RFC5322_LABEL_TOOLONG = 63;
|
||||
const RFC5322_DOMAIN = 65;
|
||||
const RFC5322_TOOLONG = 66;
|
||||
const RFC5322_DOMAIN_TOOLONG = 255;
|
||||
const RFC5322_DOMAINLITERAL = 70;
|
||||
const RFC5322_DOMLIT_OBSDTEXT = 71;
|
||||
const RFC5322_IPV6_GRPCOUNT = 72;
|
||||
const RFC5322_IPV6_2X2XCOLON = 73;
|
||||
const RFC5322_IPV6_BADCHAR = 74;
|
||||
const RFC5322_IPV6_MAXGRPS = 75;
|
||||
const RFC5322_IPV6_COLONSTRT = 76;
|
||||
const RFC5322_IPV6_COLONEND = 77;
|
||||
const DNSWARN_NO_MX_RECORD = 5;
|
||||
const DNSWARN_NO_RECORD = 6;
|
||||
protected parser;
|
||||
protected warnings = [];
|
||||
protected error;
|
||||
protected threshold = 255;
|
||||
public function __construct() -> void
|
||||
{
|
||||
let this->parser = new EmailParser(new EmailLexer());
|
||||
}
|
||||
|
||||
public function isValid(email, checkDNS = false, strict = false)
|
||||
{
|
||||
var e, rClass, dns, error;
|
||||
|
||||
try {
|
||||
this->parser->parse((string) email);
|
||||
let this->warnings = this->parser->getWarnings();
|
||||
} catch \Exception, e {
|
||||
let rClass = new \ReflectionClass(this);
|
||||
let this->error = rClass->getConstant(e->getMessage());
|
||||
|
||||
return false;
|
||||
}
|
||||
let dns = true;
|
||||
|
||||
if checkDNS {
|
||||
let dns = this->checkDNS();
|
||||
}
|
||||
|
||||
if this->hasWarnings() && (int) max(this->warnings) > this->threshold {
|
||||
let this->error = self::ERR_DEPREC_REACHED;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
return !strict || !this->hasWarnings() && dns;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return boolean
|
||||
*/
|
||||
public function hasWarnings() -> boolean
|
||||
{
|
||||
|
||||
return !empty(this->warnings);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function getWarnings() -> array
|
||||
{
|
||||
|
||||
return this->warnings;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getError() -> string
|
||||
{
|
||||
|
||||
return this->error;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $threshold
|
||||
*
|
||||
* @return EmailValidator
|
||||
*/
|
||||
public function setThreshold(int threshold)
|
||||
{
|
||||
let this->threshold = (int) threshold;
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return int
|
||||
*/
|
||||
public function getThreshold() -> int
|
||||
{
|
||||
|
||||
return this->threshold;
|
||||
}
|
||||
|
||||
protected function checkDNS()
|
||||
{
|
||||
var checked, result;
|
||||
|
||||
let checked = true;
|
||||
let result = checkdnsrr(trim(this->parser->getParsedDomainPart()), "MX");
|
||||
|
||||
if !result {
|
||||
let this->warnings[] = self::DNSWARN_NO_RECORD;
|
||||
let checked = false;
|
||||
this->addTLDWarnings();
|
||||
}
|
||||
|
||||
return checked;
|
||||
}
|
||||
|
||||
protected function addTLDWarnings() -> void
|
||||
{
|
||||
|
||||
if !in_array(self::DNSWARN_NO_RECORD, this->warnings) && !in_array(self::DNSWARN_NO_MX_RECORD, this->warnings) && in_array(self::RFC5322_DOMAINLITERAL, this->warnings) {
|
||||
let this->warnings[] = self::RFC5321_TLD;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,326 +0,0 @@
|
||||
namespace Egulias\EmailValidator\Parser;
|
||||
|
||||
use Egulias\EmailValidator\EmailLexer;
|
||||
use Egulias\EmailValidator\Parser\Parser;
|
||||
use Egulias\EmailValidator\EmailValidator;
|
||||
class DomainPart extends Parser
|
||||
{
|
||||
const DOMAIN_MAX_LENGTH = 254;
|
||||
protected domainPart = "";
|
||||
public function parse(domainPart) -> void
|
||||
{
|
||||
var domain, prev, length;
|
||||
|
||||
this->lexer->moveNext();
|
||||
|
||||
if this->lexer->token["type"] === EmailLexer::S_DOT {
|
||||
throw new \InvalidArgumentException("ERR_DOT_START");
|
||||
}
|
||||
|
||||
if this->lexer->token["type"] === EmailLexer::S_EMPTY {
|
||||
throw new \InvalidArgumentException("ERR_NODOMAIN");
|
||||
}
|
||||
|
||||
if this->lexer->token["type"] === EmailLexer::S_HYPHEN {
|
||||
throw new \InvalidArgumentException("ERR_DOMAINHYPHENEND");
|
||||
}
|
||||
|
||||
if this->lexer->token["type"] === EmailLexer::S_OPENPARENTHESIS {
|
||||
let this->warnings[] = EmailValidator::DEPREC_COMMENT;
|
||||
this->parseDomainComments();
|
||||
}
|
||||
let domain = this->doParseDomainPart();
|
||||
let prev = this->lexer->getPrevious();
|
||||
let length = strlen(domain);
|
||||
|
||||
if prev["type"] === EmailLexer::S_DOT {
|
||||
throw new \InvalidArgumentException("ERR_DOT_END");
|
||||
}
|
||||
|
||||
if prev["type"] === EmailLexer::S_HYPHEN {
|
||||
throw new \InvalidArgumentException("ERR_DOMAINHYPHENEND");
|
||||
}
|
||||
|
||||
if length > self::DOMAIN_MAX_LENGTH {
|
||||
let this->warnings[] = EmailValidator::RFC5322_DOMAIN_TOOLONG;
|
||||
}
|
||||
|
||||
if prev["type"] === EmailLexer::S_CR {
|
||||
throw new \InvalidArgumentException("ERR_FWS_CRLF_END");
|
||||
}
|
||||
let this->domainPart = domain;
|
||||
}
|
||||
|
||||
public function getDomainPart()
|
||||
{
|
||||
|
||||
return this->domainPart;
|
||||
}
|
||||
|
||||
public function checkIPV6Tag(addressLiteral, maxGroups = 8)
|
||||
{
|
||||
var prev, IPv6, matchesIP, groupCount, colons;
|
||||
|
||||
let prev = this->lexer->getPrevious();
|
||||
|
||||
if prev["type"] === EmailLexer::S_COLON {
|
||||
let this->warnings[] = EmailValidator::RFC5322_IPV6_COLONEND;
|
||||
}
|
||||
let IPv6 = substr(addressLiteral, 5);
|
||||
//Daniel Marschall's new IPv6 testing strategy
|
||||
let matchesIP = explode(":", IPv6);
|
||||
let groupCount = count(matchesIP);
|
||||
let colons = strpos(IPv6, "::");
|
||||
|
||||
if count(preg_grep("/^[0-9A-Fa-f]{0,4}$/", matchesIP, PREG_GREP_INVERT)) !== 0 {
|
||||
let this->warnings[] = EmailValidator::RFC5322_IPV6_BADCHAR;
|
||||
}
|
||||
|
||||
if colons === false {
|
||||
// We need exactly the right number of groups
|
||||
|
||||
if groupCount !== maxGroups {
|
||||
let this->warnings[] = EmailValidator::RFC5322_IPV6_GRPCOUNT;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if colons !== strrpos(IPv6, "::") {
|
||||
let this->warnings[] = EmailValidator::RFC5322_IPV6_2X2XCOLON;
|
||||
|
||||
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
|
||||
let maxGroups++;
|
||||
}
|
||||
|
||||
if groupCount > maxGroups {
|
||||
let this->warnings[] = EmailValidator::RFC5322_IPV6_MAXGRPS;
|
||||
} elseif groupCount === maxGroups {
|
||||
let this->warnings[] = EmailValidator::RFC5321_IPV6DEPRECATED;
|
||||
}
|
||||
}
|
||||
|
||||
protected function doParseDomainPart()
|
||||
{
|
||||
var domain, prev;
|
||||
|
||||
let domain = "";
|
||||
do {
|
||||
let 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->lexer->moveNext();
|
||||
}
|
||||
this->checkConsecutiveDots();
|
||||
this->checkDomainPartExceptions(prev);
|
||||
|
||||
if this->hasBrackets() {
|
||||
this->parseDomainLiteral();
|
||||
}
|
||||
this->checkLabelLength(prev);
|
||||
|
||||
if this->isFWS() {
|
||||
this->parseFWS();
|
||||
}
|
||||
let domain .= this->lexer->token["value"];
|
||||
this->lexer->moveNext();
|
||||
} while (this->lexer->token);
|
||||
|
||||
return domain;
|
||||
}
|
||||
|
||||
protected function parseDomainLiteral()
|
||||
{
|
||||
var lexer;
|
||||
|
||||
|
||||
if this->lexer->isNextToken(EmailLexer::S_COLON) {
|
||||
let this->warnings[] = EmailValidator::RFC5322_IPV6_COLONSTRT;
|
||||
}
|
||||
|
||||
if this->lexer->isNextToken(EmailLexer::S_IPV6TAG) {
|
||||
let lexer = clone this->lexer;
|
||||
lexer->moveNext();
|
||||
|
||||
if lexer->isNextToken(EmailLexer::S_DOUBLECOLON) {
|
||||
let this->warnings[] = EmailValidator::RFC5322_IPV6_COLONSTRT;
|
||||
}
|
||||
}
|
||||
|
||||
return this->doParseDomainLiteral();
|
||||
}
|
||||
|
||||
protected function doParseDomainLiteral()
|
||||
{
|
||||
var IPv6TAG, addressLiteral, tmpArray660bd629014c38ffb14ea5f4192457b6, tmpArray9934a9b75899ddf8df794ea12f1b354a;
|
||||
|
||||
let IPv6TAG = false;
|
||||
let addressLiteral = "";
|
||||
do {
|
||||
|
||||
if this->lexer->token["type"] === EmailLexer::C_NUL {
|
||||
throw new \InvalidArgumentException("ERR_EXPECTING_DTEXT");
|
||||
}
|
||||
|
||||
if this->lexer->token["type"] === EmailLexer::INVALID || this->lexer->token["type"] === EmailLexer::C_DEL || this->lexer->token["type"] === EmailLexer::S_LF {
|
||||
let this->warnings[] = EmailValidator::RFC5322_DOMLIT_OBSDTEXT;
|
||||
}
|
||||
let tmpArray660bd629014c38ffb14ea5f4192457b6 = [EmailLexer::S_OPENQBRACKET, EmailLexer::S_OPENBRACKET];
|
||||
if this->lexer->isNextTokenAny(tmpArray660bd629014c38ffb14ea5f4192457b6) {
|
||||
throw new \InvalidArgumentException("ERR_EXPECTING_DTEXT");
|
||||
}
|
||||
let tmpArray9934a9b75899ddf8df794ea12f1b354a = [EmailLexer::S_HTAB, EmailLexer::S_SP, this->lexer->token["type"] === EmailLexer::CRLF];
|
||||
if this->lexer->isNextTokenAny(tmpArray9934a9b75899ddf8df794ea12f1b354a) {
|
||||
let this->warnings[] = EmailValidator::CFWS_FWS;
|
||||
this->parseFWS();
|
||||
}
|
||||
|
||||
if this->lexer->isNextToken(EmailLexer::S_CR) {
|
||||
throw new \InvalidArgumentException("ERR_CR_NO_LF");
|
||||
}
|
||||
|
||||
if this->lexer->token["type"] === EmailLexer::S_BACKSLASH {
|
||||
let this->warnings[] = EmailValidator::RFC5322_DOMLIT_OBSDTEXT;
|
||||
let addressLiteral .= this->lexer->token["value"];
|
||||
this->lexer->moveNext();
|
||||
this->validateQuotedPair();
|
||||
}
|
||||
|
||||
if this->lexer->token["type"] === EmailLexer::S_IPV6TAG {
|
||||
let IPv6TAG = true;
|
||||
}
|
||||
|
||||
if this->lexer->token["type"] === EmailLexer::S_CLOSEQBRACKET {
|
||||
break;
|
||||
}
|
||||
let addressLiteral .= this->lexer->token["value"];
|
||||
} while (this->lexer->moveNext());
|
||||
let addressLiteral = str_replace("[", "", addressLiteral);
|
||||
let addressLiteral = this->checkIPV4Tag(addressLiteral);
|
||||
|
||||
if addressLiteral === false {
|
||||
|
||||
return addressLiteral;
|
||||
}
|
||||
|
||||
if !IPv6TAG {
|
||||
let this->warnings[] = EmailValidator::RFC5322_DOMAINLITERAL;
|
||||
|
||||
return addressLiteral;
|
||||
}
|
||||
let this->warnings[] = EmailValidator::RFC5321_ADDRESSLITERAL;
|
||||
this->checkIPV6Tag(addressLiteral);
|
||||
|
||||
return addressLiteral;
|
||||
}
|
||||
|
||||
protected function checkIPV4Tag(addressLiteral)
|
||||
{
|
||||
var matchesIP, index;
|
||||
|
||||
|
||||
let matchesIP = [];
|
||||
// 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 {
|
||||
let index = strrpos(addressLiteral, matchesIP[0]);
|
||||
|
||||
if index === 0 {
|
||||
let this->warnings[] = EmailValidator::RFC5321_ADDRESSLITERAL;
|
||||
|
||||
return false;
|
||||
}
|
||||
// Convert IPv4 part to IPv6 format for further testing
|
||||
let addressLiteral = substr(addressLiteral, 0, index) . "0:0";
|
||||
}
|
||||
|
||||
return addressLiteral;
|
||||
}
|
||||
|
||||
protected function checkDomainPartExceptions(prev) -> void
|
||||
{
|
||||
var invalidDomainTokens;
|
||||
|
||||
|
||||
let invalidDomainTokens = [EmailLexer::S_DQUOTE : true, EmailLexer::S_SEMICOLON : true, EmailLexer::S_GREATERTHAN : true, EmailLexer::S_LOWERTHAN : true];
|
||||
|
||||
if isset var tmpArray;
|
||||
this->lexer->token["type"];
|
||||
invalidDomainTokens[this->lexer->token] {
|
||||
throw new \InvalidArgumentException("ERR_EXPECTING_ATEXT");
|
||||
}
|
||||
|
||||
if this->lexer->token["type"] === EmailLexer::S_COMMA {
|
||||
throw new \InvalidArgumentException("ERR_COMMA_IN_DOMAIN");
|
||||
}
|
||||
|
||||
if this->lexer->token["type"] === EmailLexer::S_AT {
|
||||
throw new \InvalidArgumentException("ERR_CONSECUTIVEATS");
|
||||
}
|
||||
|
||||
if this->lexer->token["type"] === EmailLexer::S_OPENQBRACKET && prev["type"] !== EmailLexer::S_AT {
|
||||
throw new \InvalidArgumentException("ERR_EXPECTING_ATEXT");
|
||||
}
|
||||
|
||||
if this->lexer->token["type"] === EmailLexer::S_HYPHEN && this->lexer->isNextToken(EmailLexer::S_DOT) {
|
||||
throw new \InvalidArgumentException("ERR_DOMAINHYPHENEND");
|
||||
}
|
||||
|
||||
if this->lexer->token["type"] === EmailLexer::S_BACKSLASH && this->lexer->isNextToken(EmailLexer::GENERIC) {
|
||||
throw new \InvalidArgumentException("ERR_EXPECTING_ATEXT");
|
||||
}
|
||||
}
|
||||
|
||||
protected function hasBrackets()
|
||||
{
|
||||
var e;
|
||||
|
||||
|
||||
if this->lexer->token["type"] !== EmailLexer::S_OPENBRACKET {
|
||||
|
||||
return false;
|
||||
}
|
||||
try {
|
||||
this->lexer->find(EmailLexer::S_CLOSEBRACKET);
|
||||
} catch \RuntimeException, e {
|
||||
throw new \InvalidArgumentException("ERR_EXPECTING_DOMLIT_CLOSE");
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
protected function checkLabelLength(prev) -> void
|
||||
{
|
||||
|
||||
if this->lexer->token["type"] === EmailLexer::S_DOT && prev["type"] === EmailLexer::GENERIC && strlen(prev["value"]) > 63 {
|
||||
let this->warnings[] = EmailValidator::RFC5322_LABEL_TOOLONG;
|
||||
}
|
||||
}
|
||||
|
||||
protected function parseDomainComments() -> void
|
||||
{
|
||||
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 \InvalidArgumentException("ERR_EXPECTING_ATEXT");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,108 +0,0 @@
|
||||
namespace Egulias\EmailValidator\Parser;
|
||||
|
||||
use Egulias\EmailValidator\EmailLexer;
|
||||
use Egulias\EmailValidator\EmailValidator;
|
||||
use InvalidArgumentException;
|
||||
class LocalPart extends Parser
|
||||
{
|
||||
public function parse(localPart) -> void
|
||||
{
|
||||
var parseDQuote, closingQuote, prev;
|
||||
|
||||
let parseDQuote = true;
|
||||
let closingQuote = false;
|
||||
|
||||
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");
|
||||
}
|
||||
let closingQuote = this->checkDQUOTE(closingQuote);
|
||||
|
||||
if closingQuote && parseDQuote {
|
||||
let parseDQuote = this->parseDoubleQuote();
|
||||
}
|
||||
|
||||
if this->lexer->token["type"] === EmailLexer::S_OPENPARENTHESIS {
|
||||
this->parseComments();
|
||||
}
|
||||
this->checkConsecutiveDots();
|
||||
|
||||
if this->lexer->token["type"] === EmailLexer::S_DOT && this->lexer->isNextToken(EmailLexer::S_AT) {
|
||||
throw new \InvalidArgumentException("ERR_DOT_END");
|
||||
}
|
||||
this->warnEscaping();
|
||||
this->isInvalidToken(this->lexer->token, closingQuote);
|
||||
|
||||
if this->isFWS() {
|
||||
this->parseFWS();
|
||||
}
|
||||
this->lexer->moveNext();
|
||||
|
||||
}
|
||||
let prev = this->lexer->getPrevious();
|
||||
|
||||
if strlen(prev["value"]) > EmailValidator::RFC5322_LOCAL_TOOLONG {
|
||||
let this->warnings[] = EmailValidator::RFC5322_LOCAL_TOOLONG;
|
||||
}
|
||||
}
|
||||
|
||||
protected function parseDoubleQuote()
|
||||
{
|
||||
var parseAgain, special, invalid, setSpecialsWarning, prev;
|
||||
|
||||
let parseAgain = true;
|
||||
|
||||
let special = [EmailLexer::S_CR : true, EmailLexer::S_HTAB : true, EmailLexer::S_LF : true];
|
||||
|
||||
let invalid = [EmailLexer::C_NUL : true, EmailLexer::S_HTAB : true, EmailLexer::S_CR : true, EmailLexer::S_LF : true];
|
||||
let setSpecialsWarning = true;
|
||||
this->lexer->moveNext();
|
||||
|
||||
while (this->lexer->token["type"] !== EmailLexer::S_DQUOTE && this->lexer->token) {
|
||||
let parseAgain = false;
|
||||
|
||||
if isset var tmpArray;
|
||||
this->lexer->token["type"];
|
||||
special[this->lexer->token] && setSpecialsWarning {
|
||||
let this->warnings[] = EmailValidator::CFWS_FWS;
|
||||
let setSpecialsWarning = false;
|
||||
}
|
||||
this->lexer->moveNext();
|
||||
|
||||
if !this->escaped() && isset var tmpArray;
|
||||
this->lexer->token["type"];
|
||||
invalid[this->lexer->token] {
|
||||
throw new InvalidArgumentException("ERR_EXPECTED_ATEXT");
|
||||
}
|
||||
|
||||
}
|
||||
let prev = this->lexer->getPrevious();
|
||||
|
||||
if prev["type"] === EmailLexer::S_BACKSLASH {
|
||||
|
||||
if !this->checkDQUOTE(false) {
|
||||
throw new \InvalidArgumentException("ERR_UNCLOSED_DQUOTE");
|
||||
}
|
||||
}
|
||||
|
||||
if !this->lexer->isNextToken(EmailLexer::S_AT) && prev["type"] !== EmailLexer::S_BACKSLASH {
|
||||
throw new \InvalidArgumentException("ERR_EXPECED_AT");
|
||||
}
|
||||
|
||||
return parseAgain;
|
||||
}
|
||||
|
||||
protected function isInvalidToken(token, closingQuote) -> void
|
||||
{
|
||||
var forbidden;
|
||||
|
||||
|
||||
let forbidden = [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");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,210 +0,0 @@
|
||||
namespace Egulias\EmailValidator\Parser;
|
||||
|
||||
use Egulias\EmailValidator\EmailLexer;
|
||||
use Egulias\EmailValidator\EmailValidator;
|
||||
abstract class Parser
|
||||
{
|
||||
protected warnings = [];
|
||||
protected lexer;
|
||||
public function __construct(<EmailLexer> lexer) -> void
|
||||
{
|
||||
let this->lexer = lexer;
|
||||
}
|
||||
|
||||
public function getWarnings()
|
||||
{
|
||||
|
||||
return this->warnings;
|
||||
}
|
||||
|
||||
abstract function parse(str) -> void;
|
||||
|
||||
/**
|
||||
* validateQuotedPair
|
||||
*/
|
||||
protected function validateQuotedPair() -> void
|
||||
{
|
||||
|
||||
if !(this->lexer->token["type"] === EmailLexer::INVALID || this->lexer->token["type"] === EmailLexer::C_DEL) {
|
||||
throw new \InvalidArgumentException("ERR_EXPECTING_QPAIR");
|
||||
}
|
||||
let this->warnings[] = EmailValidator::DEPREC_QP;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string the the comment
|
||||
* @throws \InvalidArgumentException
|
||||
*/
|
||||
protected function parseComments() -> string
|
||||
{
|
||||
var tmpArray63f0c3c6be7adf1793a82cc46795d34e;
|
||||
|
||||
this->isUnclosedComment();
|
||||
let this->warnings[] = EmailValidator::CFWS_COMMENT;
|
||||
|
||||
while (!this->lexer->isNextToken(EmailLexer::S_CLOSEPARENTHESIS)) {
|
||||
this->warnEscaping();
|
||||
this->lexer->moveNext();
|
||||
|
||||
}
|
||||
this->lexer->moveNext();
|
||||
let tmpArray63f0c3c6be7adf1793a82cc46795d34e = [EmailLexer::GENERIC, EmailLexer::S_EMPTY];
|
||||
if this->lexer->isNextTokenAny(tmpArray63f0c3c6be7adf1793a82cc46795d34e) {
|
||||
throw new \InvalidArgumentException("ERR_EXPECTING_ATEXT");
|
||||
}
|
||||
|
||||
if this->lexer->isNextToken(EmailLexer::S_AT) {
|
||||
let this->warnings[] = EmailValidator::DEPREC_CFWS_NEAR_AT;
|
||||
}
|
||||
}
|
||||
|
||||
protected function isUnclosedComment()
|
||||
{
|
||||
var e;
|
||||
|
||||
try {
|
||||
this->lexer->find(EmailLexer::S_CLOSEPARENTHESIS);
|
||||
|
||||
return true;
|
||||
} catch \RuntimeException, e {
|
||||
throw new \InvalidArgumentException("ERR_UNCLOSEDCOMMENT");
|
||||
}
|
||||
}
|
||||
|
||||
protected function parseFWS() -> void
|
||||
{
|
||||
var previous;
|
||||
|
||||
let previous = this->lexer->getPrevious();
|
||||
this->checkCRLFInFWS();
|
||||
|
||||
if this->lexer->token["type"] === EmailLexer::S_CR {
|
||||
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");
|
||||
}
|
||||
|
||||
if this->lexer->token["type"] === EmailLexer::S_LF || this->lexer->token["type"] === EmailLexer::C_NUL {
|
||||
throw new \InvalidArgumentException("ERR_EXPECTING_CTEXT");
|
||||
}
|
||||
|
||||
if this->lexer->isNextToken(EmailLexer::S_AT) || previous["type"] === EmailLexer::S_AT {
|
||||
let this->warnings[] = EmailValidator::DEPREC_CFWS_NEAR_AT;
|
||||
} else {
|
||||
let this->warnings[] = EmailValidator::CFWS_FWS;
|
||||
}
|
||||
}
|
||||
|
||||
protected function checkConsecutiveDots() -> void
|
||||
{
|
||||
|
||||
if this->lexer->token["type"] === EmailLexer::S_DOT && this->lexer->isNextToken(EmailLexer::S_DOT) {
|
||||
throw new \InvalidArgumentException("ERR_CONSECUTIVEDOTS");
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
protected function escaped()
|
||||
{
|
||||
var previous;
|
||||
|
||||
let previous = this->lexer->getPrevious();
|
||||
|
||||
if previous["type"] === EmailLexer::S_BACKSLASH && this->lexer->token["type"] !== EmailLexer::GENERIC {
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
protected function warnEscaping()
|
||||
{
|
||||
var tmpArray612d23a3c73245450bf1b63fe4fddaa8;
|
||||
|
||||
|
||||
if this->lexer->token["type"] !== EmailLexer::S_BACKSLASH {
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
if this->lexer->isNextToken(EmailLexer::GENERIC) {
|
||||
throw new \InvalidArgumentException("ERR_EXPECTING_ATEXT");
|
||||
}
|
||||
let tmpArray612d23a3c73245450bf1b63fe4fddaa8 = [EmailLexer::S_SP, EmailLexer::S_HTAB, EmailLexer::C_DEL];
|
||||
if !this->lexer->isNextTokenAny(tmpArray612d23a3c73245450bf1b63fe4fddaa8) {
|
||||
|
||||
return false;
|
||||
}
|
||||
let this->warnings[] = EmailValidator::DEPREC_QP;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
protected function checkDQUOTE(hasClosingQuote)
|
||||
{
|
||||
var previous, e;
|
||||
|
||||
|
||||
if this->lexer->token["type"] !== EmailLexer::S_DQUOTE {
|
||||
|
||||
return hasClosingQuote;
|
||||
}
|
||||
|
||||
if hasClosingQuote {
|
||||
|
||||
return hasClosingQuote;
|
||||
}
|
||||
let previous = this->lexer->getPrevious();
|
||||
|
||||
if this->lexer->isNextToken(EmailLexer::GENERIC) && previous["type"] === EmailLexer::GENERIC {
|
||||
throw new \InvalidArgumentException("ERR_EXPECTING_ATEXT");
|
||||
}
|
||||
let this->warnings[] = EmailValidator::RFC5321_QUOTEDSTRING;
|
||||
try {
|
||||
this->lexer->find(EmailLexer::S_DQUOTE);
|
||||
let hasClosingQuote = true;
|
||||
} catch \Exception, e {
|
||||
throw new \InvalidArgumentException("ERR_UNCLOSEDQUOTEDSTR");
|
||||
}
|
||||
|
||||
return hasClosingQuote;
|
||||
}
|
||||
|
||||
protected function checkCRLFInFWS()
|
||||
{
|
||||
var tmpArray1ece19b1ca3512633175a37153944cbe;
|
||||
|
||||
|
||||
if this->lexer->token["type"] !== EmailLexer::CRLF {
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if this->lexer->isNextToken(EmailLexer::CRLF) {
|
||||
throw new \InvalidArgumentException("ERR_FWS_CRLF_X2");
|
||||
}
|
||||
let tmpArray1ece19b1ca3512633175a37153944cbe = [EmailLexer::S_SP, EmailLexer::S_HTAB];
|
||||
if !this->lexer->isNextTokenAny(tmpArray1ece19b1ca3512633175a37153944cbe) {
|
||||
throw new \InvalidArgumentException("ERR_FWS_CRLF_END");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user