Version 1
[yaffs-website] / vendor / egulias / email-validator / src / Egulias / EmailValidator / Parser / DomainPart.php
diff --git a/vendor/egulias/email-validator/src/Egulias/EmailValidator/Parser/DomainPart.php b/vendor/egulias/email-validator/src/Egulias/EmailValidator/Parser/DomainPart.php
new file mode 100644 (file)
index 0000000..66a51fb
--- /dev/null
@@ -0,0 +1,339 @@
+<?php
+
+
+namespace Egulias\EmailValidator\Parser;
+
+use Egulias\EmailValidator\EmailLexer;
+use Egulias\EmailValidator\EmailValidator;
+
+class DomainPart extends Parser
+{
+    const DOMAIN_MAX_LENGTH = 254;
+    protected $domainPart = '';
+
+    public function parse($domainPart)
+    {
+        $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) {
+            $this->warnings[] = EmailValidator::DEPREC_COMMENT;
+            $this->parseDomainComments();
+        }
+
+        $domain = $this->doParseDomainPart();
+
+        $prev = $this->lexer->getPrevious();
+        $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) {
+            $this->warnings[] = EmailValidator::RFC5322_DOMAIN_TOOLONG;
+        }
+        if ($prev['type'] === EmailLexer::S_CR) {
+            throw new \InvalidArgumentException('ERR_FWS_CRLF_END');
+        }
+        $this->domainPart = $domain;
+    }
+
+    public function getDomainPart()
+    {
+        return $this->domainPart;
+    }
+
+    public function checkIPV6Tag($addressLiteral, $maxGroups = 8)
+    {
+        $prev = $this->lexer->getPrevious();
+        if ($prev['type'] === EmailLexer::S_COLON) {
+            $this->warnings[] = EmailValidator::RFC5322_IPV6_COLONEND;
+        }
+
+        $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[] = EmailValidator::RFC5322_IPV6_BADCHAR;
+        }
+
+        if ($colons === false) {
+            // We need exactly the right number of groups
+            if ($groupCount !== $maxGroups) {
+                $this->warnings[] = EmailValidator::RFC5322_IPV6_GRPCOUNT;
+            }
+            return;
+        }
+
+        if ($colons !== strrpos($IPv6, '::')) {
+            $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
+            ++$maxGroups;
+        }
+
+        if ($groupCount > $maxGroups) {
+            $this->warnings[] = EmailValidator::RFC5322_IPV6_MAXGRPS;
+        } elseif ($groupCount === $maxGroups) {
+            $this->warnings[] = EmailValidator::RFC5321_IPV6DEPRECATED;
+        }
+    }
+
+    protected function doParseDomainPart()
+    {
+        $domain = '';
+        $openedParenthesis = 0;
+        $openBrackets = false;
+        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 \InvalidArgumentException('ERR_UNOPENEDCOMMENT');
+                } else {
+                    $openedParenthesis--;
+                }
+            }
+
+            $this->checkConsecutiveDots();
+            $this->checkDomainPartExceptions($prev);
+
+            if ($openBrackets = $this->hasBrackets($openBrackets)) {
+                $this->parseDomainLiteral();
+            }
+
+            $this->checkLabelLength($prev);
+
+            if ($this->isFWS()) {
+                $this->parseFWS();
+            }
+
+            $domain .= $this->lexer->token['value'];
+            $this->lexer->moveNext();
+        } while ($this->lexer->token);
+
+        return $domain;
+    }
+
+    private function checkNotAllowedChars($token)
+    {
+        $notAllowed = array(EmailLexer::S_BACKSLASH => true, EmailLexer::S_SLASH=> true);
+        if (isset($notAllowed[$token['type']])) {
+            throw new \InvalidArgumentException('ERR_DOMAIN_CHAR_NOT_ALLOWED');
+        }
+    }
+
+    protected function parseDomainLiteral()
+    {
+        if ($this->lexer->isNextToken(EmailLexer::S_COLON)) {
+            $this->warnings[] = EmailValidator::RFC5322_IPV6_COLONSTRT;
+        }
+        if ($this->lexer->isNextToken(EmailLexer::S_IPV6TAG)) {
+            $lexer = clone $this->lexer;
+            $lexer->moveNext();
+            if ($lexer->isNextToken(EmailLexer::S_DOUBLECOLON)) {
+                $this->warnings[] = EmailValidator::RFC5322_IPV6_COLONSTRT;
+            }
+        }
+
+        return $this->doParseDomainLiteral();
+    }
+
+    protected function doParseDomainLiteral()
+    {
+        $IPv6TAG = false;
+        $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
+            ) {
+                $this->warnings[] = EmailValidator::RFC5322_DOMLIT_OBSDTEXT;
+            }
+
+            if ($this->lexer->isNextTokenAny(array(EmailLexer::S_OPENQBRACKET, EmailLexer::S_OPENBRACKET))) {
+                throw new \InvalidArgumentException('ERR_EXPECTING_DTEXT');
+            }
+
+            if ($this->lexer->isNextTokenAny(
+                array(EmailLexer::S_HTAB, EmailLexer::S_SP, $this->lexer->token['type'] === EmailLexer::CRLF)
+            )) {
+                $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) {
+                $this->warnings[] = EmailValidator::RFC5322_DOMLIT_OBSDTEXT;
+                $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[] = EmailValidator::RFC5322_DOMAINLITERAL;
+            return $addressLiteral;
+        }
+
+        $this->warnings[] = EmailValidator::RFC5321_ADDRESSLITERAL;
+
+        $this->checkIPV6Tag($addressLiteral);
+
+        return $addressLiteral;
+    }
+
+    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[] = EmailValidator::RFC5321_ADDRESSLITERAL;
+                return false;
+            }
+            // Convert IPv4 part to IPv6 format for further testing
+            $addressLiteral = substr($addressLiteral, 0, $index) . '0:0';
+        }
+
+        return $addressLiteral;
+    }
+
+    protected function checkDomainPartExceptions($prev)
+    {
+        $invalidDomainTokens = array(
+            EmailLexer::S_DQUOTE => true,
+            EmailLexer::S_SEMICOLON => true,
+            EmailLexer::S_GREATERTHAN => true,
+            EmailLexer::S_LOWERTHAN => true,
+        );
+
+        if (isset($invalidDomainTokens[$this->lexer->token['type']])) {
+            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($openBrackets)
+    {
+        if ($this->lexer->token['type'] === EmailLexer::S_CLOSEBRACKET && !$openBrackets) {
+            throw new \InvalidArgumentException('ERR_EXPECTING_OPENBRACKET');
+        }
+
+        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)
+    {
+        if ($this->lexer->token['type'] === EmailLexer::S_DOT &&
+            $prev['type'] === EmailLexer::GENERIC &&
+            strlen($prev['value']) > 63
+        ) {
+            $this->warnings[] = EmailValidator::RFC5322_LABEL_TOOLONG;
+        }
+    }
+
+    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 \InvalidArgumentException('ERR_EXPECTING_ATEXT');
+        }
+    }
+}