LICENSE 0000666 00000002055 13436750351 0005566 0 ustar 00 Copyright (c) 2013-2016 Eduardo Gulias Davis
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is furnished
to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
README.md 0000666 00000006405 13436750351 0006043 0 ustar 00 #EmailValidator
[![Build Status](https://travis-ci.org/egulias/EmailValidator.png?branch=master)](https://travis-ci.org/egulias/EmailValidator) [![Coverage Status](https://coveralls.io/repos/egulias/EmailValidator/badge.png?branch=master)](https://coveralls.io/r/egulias/EmailValidator?branch=master) [![Scrutinizer Code Quality](https://scrutinizer-ci.com/g/egulias/EmailValidator/badges/quality-score.png?b=master)](https://scrutinizer-ci.com/g/egulias/EmailValidator/?branch=master) [![SensioLabsInsight](https://insight.sensiolabs.com/projects/22ba6692-9c02-42e5-a65d-1c5696bfffc6/small.png)](https://insight.sensiolabs.com/projects/22ba6692-9c02-42e5-a65d-1c5696bfffc6)
=============================
With the help of
![Powered by PhpStorm](https://www.jetbrains.com/phpstorm/documentation/docs/logo_phpstorm.png)
##Installation##
Run the command below to install via Composer
```shell
composer require egulias/email-validator "~2.0"
```
##Getting Started##
`EmailValidator`requires you to decide which (or combination of them) validation/s strategy/ies you'd like to follow for each [validation](#available-validations).
A basic example with the RFC validation
```php
isValid("example@example.com", new RFCValidation()) //true
```
###Available validations###
1. [RFCValidation](https://github.com/egulias/EmailValidator/blob/master/EmailValidator/Validation/RFCValidation.php)
2. [NoWarningsRFCValidation](https://github.com/egulias/EmailValidator/blob/master/EmailValidator/Validation/NoRFCWarningsValidation.php)
3. [DNSCheckValidation](https://github.com/egulias/EmailValidator/blob/master/EmailValidator/Validation/DNSCheckValidation.php)
4. [SpoofCheckValidation](https://github.com/egulias/EmailValidator/blob/master/EmailValidator/Validation/SpoofCheckValidation.php)
5. [MultipleValidationsWithAnd](https://github.com/egulias/EmailValidator/blob/master/EmailValidator/Validation/MultipleValidationWithAnd.php)
6. [Your own validation](#how-to-extend)
`MultipleValidationsWithAnd`
It is a validation that operates over other validations performing a logical and (&&) over the result of each validation.
```php
isValid("example@example.com", $multipleValidations) //true
```
###How to extend###
It's easy! You just need to extend [EmailValidation](https://github.com/egulias/EmailValidator/blob/master/EmailValidator/Validation/EmailValidation.php) and you can use your own validation.
##Other Contributors##
(You can find current contributors [here](https://github.com/egulias/EmailValidator/graphs/contributors))
As this is a port from another library and work, here are other people related to the previous one:
* Ricard Clau [@ricardclau](http://github.com/ricardclau): Performance against PHP built-in filter_var
* Josepf Bielawski [@stloyd](http://github.com/stloyd): For its first re-work of Dominic's lib
* Dominic Sayers [@dominicsayers](http://github.com/dominicsayers): The original isemail function
##License##
Released under the MIT License attached with this code.
documentation/RFC5321BNF.html 0000666 00000005473 13436750351 0011602 0 ustar 00
The BNF from RFC 5321 defining parts of a valid SMTP address
Mailbox = Local-part "@" ( Domain / address-literal )
Local-part = Dot-string / Quoted-string
; MAY be case-sensitive
Dot-string = Atom *("." Atom)
Atom = 1*atext
Quoted-string = DQUOTE *QcontentSMTP DQUOTE
QcontentSMTP = qtextSMTP / quoted-pairSMTP
quoted-pairSMTP = %d92 %d32-126
; i.e., backslash followed by any ASCII
; graphic (including itself) or SPace
qtextSMTP = %d32-33 / %d35-91 / %d93-126
; i.e., within a quoted string, any
; ASCII graphic or space is permitted
; without blackslash-quoting except
; double-quote and the backslash itself.
Domain = sub-domain *("." sub-domain)
sub-domain = Let-dig [Ldh-str]
Let-dig = ALPHA / DIGIT
Ldh-str = *( ALPHA / DIGIT / "-" ) Let-dig
address-literal = "[" ( IPv4-address-literal /
IPv6-address-literal /
General-address-literal ) "]"
; See Section 4.1.3
IPv4-address-literal = Snum 3("." Snum)
IPv6-address-literal = "IPv6:" IPv6-addr
General-address-literal = Standardized-tag ":" 1*dcontent
Standardized-tag = Ldh-str
; Standardized-tag MUST be specified in a
; Standards-Track RFC and registered with IANA
dcontent = %d33-90 / ; Printable US-ASCII
%d94-126 ; excl. "[", "\", "]"
Snum = 1*3DIGIT
; representing a decimal integer
; value in the range 0 through 255
IPv6-addr = IPv6-full / IPv6-comp / IPv6v4-full / IPv6v4-comp
IPv6-hex = 1*4HEXDIG
IPv6-full = IPv6-hex 7(":" IPv6-hex)
IPv6-comp = [IPv6-hex *5(":" IPv6-hex)] "::"
[IPv6-hex *5(":" IPv6-hex)]
; The "::" represents at least 2 16-bit groups of
; zeros. No more than 6 groups in addition to the
; "::" may be present.
IPv6v4-full = IPv6-hex 5(":" IPv6-hex) ":" IPv4-address-literal
IPv6v4-comp = [IPv6-hex *3(":" IPv6-hex)] "::"
[IPv6-hex *3(":" IPv6-hex) ":"]
IPv4-address-literal
; The "::" represents at least 2 16-bit groups of
; zeros. No more than 4 groups in addition to the
; "::" and IPv4-address-literal may be present.
documentation/Other.md 0000666 00000005577 13436750351 0011051 0 ustar 00 Email length
------------
http://tools.ietf.org/html/rfc5321#section-4.1.2
Forward-path = Path
Path = "<" [ A-d-l ":" ] Mailbox ">"
http://tools.ietf.org/html/rfc5321#section-4.5.3.1.3
http://tools.ietf.org/html/rfc1035#section-2.3.4
DNS
---
http://tools.ietf.org/html/rfc5321#section-2.3.5
Names that can
be resolved to MX RRs or address (i.e., A or AAAA) RRs (as discussed
in Section 5) are permitted, as are CNAME RRs whose targets can be
resolved, in turn, to MX or address RRs.
http://tools.ietf.org/html/rfc5321#section-5.1
The lookup first attempts to locate an MX record associated with the
name. If a CNAME record is found, the resulting name is processed as
if it were the initial name. ... If an empty list of MXs is returned,
the address is treated as if it was associated with an implicit MX
RR, with a preference of 0, pointing to that host.
is_email() author's note: We will regard the existence of a CNAME to be
sufficient evidence of the domain's existence. For performance reasons
we will not repeat the DNS lookup for the CNAME's target, but we will
raise a warning because we didn't immediately find an MX record.
Check for TLD addresses
-----------------------
TLD addresses are specifically allowed in RFC 5321 but they are
unusual to say the least. We will allocate a separate
status to these addresses on the basis that they are more likely
to be typos than genuine addresses (unless we've already
established that the domain does have an MX record)
http://tools.ietf.org/html/rfc5321#section-2.3.5
In the case
of a top-level domain used by itself in an email address, a single
string is used without any dots. This makes the requirement,
described in more detail below, that only fully-qualified domain
names appear in SMTP transactions on the public Internet,
particularly important where top-level domains are involved.
TLD format
----------
The format of TLDs has changed a number of times. The standards
used by IANA have been largely ignored by ICANN, leading to
confusion over the standards being followed. These are not defined
anywhere, except as a general component of a DNS host name (a label).
However, this could potentially lead to 123.123.123.123 being a
valid DNS name (rather than an IP address) and thereby creating
an ambiguity. The most authoritative statement on TLD formats that
the author can find is in a (rejected!) erratum to RFC 1123
submitted by John Klensin, the author of RFC 5321:
http://www.rfc-editor.org/errata_search.php?rfc=1123&eid=1353
However, a valid host name can never have the dotted-decimal
form #.#.#.#, since this change does not permit the highest-level
component label to start with a digit even if it is not all-numeric.
Comments
--------
Comments at the start of the domain are deprecated in the text
Comments at the start of a subdomain are obs-domain
(http://tools.ietf.org/html/rfc5322#section-3.4.1)
documentation/RFC5322BNF.html 0000666 00000011505 13436750351 0011574 0 ustar 00
The BNF from RFC 5322 defining parts of a valid internet message address
addr-spec = local-part "@" domain
local-part = dot-atom / quoted-string / obs-local-part
dot-atom = [CFWS] dot-atom-text [CFWS]
CFWS = (1*([FWS] comment) [FWS]) / FWS
FWS = ([*WSP CRLF] 1*WSP) / obs-FWS
; Folding white space
WSP = SP / HTAB ; white space
obs-FWS = 1*([CRLF] WSP) ; As amended in erratum #1908
ctext = %d33-39 / ; Printable US-ASCII
%d42-91 / ; characters not including
%d93-126 / ; "(", ")", or "\"
obs-ctext
obs-ctext = obs-NO-WS-CTL
ccontent = ctext / quoted-pair / comment
comment = "(" *([FWS] ccontent) [FWS] ")"
dot-atom-text = 1*atext *("." 1*atext)
atext = ALPHA / DIGIT / ; Printable US-ASCII
"!" / "#" / ; characters not including
"$" / "%" / ; specials. Used for atoms.
"&" / "'" /
"*" / "+" /
"-" / "/" /
"=" / "?" /
"^" / "_" /
"`" / "{" /
"|" / "}" /
"~"
specials = "(" / ")" / ; Special characters that do
"<" / ">" / ; not appear in atext
"[" / "]" /
":" / ";" /
"@" / "\" /
"," / "." /
DQUOTE
quoted-string = [CFWS]
DQUOTE *([FWS] qcontent) [FWS] DQUOTE
[CFWS]
qcontent = qtext / quoted-pair
qtext = %d33 / ; Printable US-ASCII
%d35-91 / ; characters not including
%d93-126 / ; "\" or the quote character
obs-qtext
obs-qtext = obs-NO-WS-CTL
obs-NO-WS-CTL = %d1-8 / ; US-ASCII control
%d11 / ; characters that do not
%d12 / ; include the carriage
%d14-31 / ; return, line feed, and
%d127 ; white space characters
quoted-pair = ("\" (VCHAR / WSP)) / obs-qp
VCHAR = %x21-7E ; visible (printing) characters
obs-qp = "\" (%d0 / obs-NO-WS-CTL / LF / CR)
obs-local-part = word *("." word)
word = atom / quoted-string
atom = [CFWS] 1*atext [CFWS]
domain = dot-atom / domain-literal / obs-domain
domain-literal = [CFWS] "[" *([FWS] dtext) [FWS] "]" [CFWS]
dtext = %d33-90 / ; Printable US-ASCII
%d94-126 / ; characters not including
obs-dtext ; "[", "]", or "\"
obs-dtext = obs-NO-WS-CTL / quoted-pair
obs-domain = atom *("." atom)
NB For SMTP mail, the domain-literal is restricted by RFC5321 as follows:
Mailbox = Local-part "@" ( Domain / address-literal )
address-literal = "[" ( IPv4-address-literal /
IPv6-address-literal /
General-address-literal ) "]"
IPv4-address-literal = Snum 3("." Snum)
IPv6-address-literal = "IPv6:" IPv6-addr
Snum = 1*3DIGIT
; representing a decimal integer
; value in the range 0 through 255
IPv6-addr = IPv6-full / IPv6-comp / IPv6v4-full / IPv6v4-comp
IPv6-hex = 1*4HEXDIG
IPv6-full = IPv6-hex 7(":" IPv6-hex)
IPv6-comp = [IPv6-hex *5(":" IPv6-hex)] "::"
[IPv6-hex *5(":" IPv6-hex)]
; The "::" represents at least 2 16-bit groups of
; zeros. No more than 6 groups in addition to the
; "::" may be present.
IPv6v4-full = IPv6-hex 5(":" IPv6-hex) ":" IPv4-address-literal
IPv6v4-comp = [IPv6-hex *3(":" IPv6-hex)] "::"
[IPv6-hex *3(":" IPv6-hex) ":"]
IPv4-address-literal
; The "::" represents at least 2 16-bit groups of
; zeros. No more than 4 groups in addition to the
; "::" and IPv4-address-literal may be present.
composer.json 0000666 00000001602 13436750351 0007300 0 ustar 00 {
"name": "egulias/email-validator",
"description": "A library for validating emails against several RFCs",
"homepage": "https://github.com/egulias/EmailValidator",
"type": "Library",
"keywords": ["email", "validation", "validator", "emailvalidation", "emailvalidator"],
"license": "MIT",
"authors": [
{"name": "Eduardo Gulias Davis"}
],
"extra": {
"branch-alias": {
"dev-master": "2.0.x-dev"
}
},
"repositories": [
{
"type": "git",
"url": "https://github.com/dominicsayers/isemail"
}
],
"require": {
"php": ">= 5.5",
"doctrine/lexer": "^1.0.1"
},
"require-dev" : {
"satooshi/php-coveralls": "dev-master",
"phpunit/phpunit": "^4.8.0",
"dominicsayers/isemail": "dev-master"
},
"autoload": {
"psr-4": {
"Egulias\\EmailValidator\\": "EmailValidator"
}
}
}
.travis.yml 0000666 00000001010 13436750351 0006660 0 ustar 00 sudo: false
language: php
php:
- 5.5
- 5.6
- 7.0
- hhvm
env:
global:
- deps=no
matrix:
fast_finish: true
include:
- php: 5.5
env: deps=low
- php: 5.6
env: deps=high
install:
- if [ "$deps" = "no" ]; then composer install; fi
- if [ "$deps" = "low" ]; then composer update --prefer-lowest; fi
- if [ "$deps" = "high" ]; then composer update; fi
script:
- mkdir -p build/logs
- phpunit --coverage-clover build/logs/clover.xml
after_script:
- php vendor/bin/coveralls
EmailValidator/Validation/RFCValidation.php 0000666 00000001711 13436750351 0014704 0 ustar 00 parser = new EmailParser($emailLexer);
try {
$this->parser->parse((string)$email);
} catch (InvalidEmail $invalid) {
$this->error = $invalid;
return false;
}
$this->warnings = $this->parser->getWarnings();
return true;
}
public function getError()
{
return $this->error;
}
public function getWarnings()
{
return $this->warnings;
}
}
EmailValidator/Validation/MultipleValidationWithAnd.php 0000666 00000002243 13436750351 0017345 0 ustar 00 validations = $validations;
}
public function isValid($email, EmailLexer $emailLexer)
{
$result = true;
$errors = [];
foreach ($this->validations as $validation) {
$emailLexer->reset();
$result = $result && $validation->isValid($email, $emailLexer);
$this->warnings = array_merge($this->warnings, $validation->getWarnings());
$errors[] = $validation->getError();
}
$this->error = new MultipleErrors($errors);
return $result;
}
public function getError()
{
return $this->error;
}
public function getWarnings()
{
return $this->warnings;
}
}
EmailValidator/Validation/SpoofCheckValidation.php 0000666 00000001361 13436750351 0016317 0 ustar 00 setChecks(Spoofchecker::SINGLE_SCRIPT);
if ($checker->isSuspicious($email)) {
$this->error = new SpoofEmail();
}
return $this->error === null;
}
public function getError()
{
return $this->error;
}
public function getWarnings()
{
return [];
}
}
EmailValidator/Validation/DNSCheckValidation.php 0000666 00000003450 13436750351 0015656 0 ustar 00 extractHost($result);
}
return $this->checkDNS($host);
}
public function getError()
{
return $this->error;
}
public function getWarnings()
{
return $this->warnings;
}
private function extractHost(array $result)
{
foreach ($result as $match) {
$onlyDomainPattern = "/^([a-z0-9]+([._-][a-z0-9]+))+$/";
if (preg_match($onlyDomainPattern, $match, $domainResult)) {
return $domainResult[0];
}
}
}
protected function checkDNS($host)
{
$Aresult = true;
$MXresult = checkdnsrr($host, 'MX');
if (!$MXresult) {
$this->warnings[NoDNSMXRecord::CODE] = new NoDNSMXRecord();
$Aresult = checkdnsrr($host, 'A');
if (!$Aresult) {
$this->error = new NoDNSRecord();
}
}
return $MXresult || $Aresult;
}
}
EmailValidator/Validation/NoRFCWarningsValidation.php 0000666 00000000461 13436750351 0016713 0 ustar 00 getWarnings());
}
}
EmailValidator/Validation/MultipleErrors.php 0000666 00000000772 13436750351 0015255 0 ustar 00 errors = $errors;
parent::__construct();
}
public function getErrors()
{
return $this->errors;
}
}
EmailValidator/Validation/EmailValidation.php 0000666 00000000531 13436750351 0015320 0 ustar 00 message = 'Email is too long, exceeds ' . EmailParser::EMAIL_MAX_LENGTH;
}
}
EmailValidator/Warning/LocalTooLong.php 0000666 00000000456 13436750351 0014133 0 ustar 00 message = 'Local part is too long, exceeds 64 chars (octets)';
$this->rfcNumber = 5322;
}
}
EmailValidator/Warning/TLD.php 0000666 00000000274 13436750351 0012220 0 ustar 00 message = "RFC5321, TLD";
}
}
EmailValidator/Warning/Warning.php 0000666 00000001002 13436750351 0013170 0 ustar 00 message;
}
public function code()
{
return self::CODE;
}
public function RFCNumber()
{
return $this->rfcNumber;
}
public function __toString()
{
return $this->message() . " rfc: " . $this->rfcNumber . "interal code: " . static::CODE;
}
}
EmailValidator/Warning/Comment.php 0000666 00000000321 13436750351 0013170 0 ustar 00 message = "Comments found in this email";
}
}
EmailValidator/Warning/DomainLiteral.php 0000666 00000000352 13436750351 0014316 0 ustar 00 message = 'Domain Literal';
$this->rfcNumber = 5322;
}
}
EmailValidator/Warning/AddressLiteral.php 0000666 00000000373 13436750351 0014477 0 ustar 00 message = 'Address literal in domain part';
$this->rfcNumber = 5321;
}
}
EmailValidator/Warning/DeprecatedComment.php 0000666 00000000322 13436750351 0015152 0 ustar 00 message = 'Deprecated comments';
}
}
EmailValidator/Warning/QuotedPart.php 0000666 00000000416 13436750351 0013663 0 ustar 00 message = "Deprecated Quoted String found between $prevToken and $postToken";
}
}
EmailValidator/Warning/CFWSNearAt.php 0000666 00000000335 13436750351 0013430 0 ustar 00 message = "Deprecated folding white space near @";
}
}
EmailValidator/Warning/IPV6GroupCount.php 0000666 00000000372 13436750351 0014346 0 ustar 00 message = 'Group count is not IPV6 valid';
$this->rfcNumber = 5322;
}
}
EmailValidator/Warning/IPV6BadChar.php 0000666 00000000371 13436750351 0013524 0 ustar 00 message = 'Bad char in IPV6 domain literal';
$this->rfcNumber = 5322;
}
}
EmailValidator/Warning/IPV6ColonEnd.php 0000666 00000000404 13436750351 0013736 0 ustar 00 message = ':: found at the end of the domain literal';
$this->rfcNumber = 5322;
}
}
EmailValidator/Warning/NoDNSMXRecord.php 0000666 00000000404 13436750351 0014115 0 ustar 00 message = 'No MX DSN record was found for this email';
$this->rfcNumber = 5321;
}
}
EmailValidator/Warning/QuotedString.php 0000666 00000000405 13436750351 0014221 0 ustar 00 message = "Quoted String found between $prevToken and $postToken";
}
}
EmailValidator/Warning/IPV6ColonStart.php 0000666 00000000410 13436750351 0014322 0 ustar 00 message = ':: found at the start of the domain literal';
$this->rfcNumber = 5322;
}
}
EmailValidator/Warning/LabelTooLong.php 0000666 00000000351 13436750351 0014112 0 ustar 00 message = 'Label too long';
$this->rfcNumber = 5322;
}
}
EmailValidator/Warning/DomainTooLong.php 0000666 00000000402 13436750351 0014277 0 ustar 00 message = 'Domain is too long, exceeds 255 chars';
$this->rfcNumber = 5322;
}
}
EmailValidator/Warning/IPV6MaxGroups.php 0000666 00000000415 13436750351 0014164 0 ustar 00 message = 'Reached the maximum number of IPV6 groups allowed';
$this->rfcNumber = 5321;
}
}
EmailValidator/Warning/IPV6DoubleColon.php 0000666 00000000377 13436750351 0014453 0 ustar 00 message = 'Double colon found after IPV6 tag';
$this->rfcNumber = 5322;
}
}
EmailValidator/Warning/CFWSWithFWS.php 0000666 00000000355 13436750351 0013553 0 ustar 00 message = 'Folding whites space followed by folding white space';
}
}
EmailValidator/Warning/IPV6Deprecated.php 0000666 00000000364 13436750351 0014302 0 ustar 00 message = 'Deprecated form of IPV6';
$this->rfcNumber = 5321;
}
}
EmailValidator/Warning/ObsoleteDTEXT.php 0000666 00000000374 13436750351 0014163 0 ustar 00 rfcNumber = 5322;
$this->message = 'Obsolete DTEXT in domain literal';
}
}
EmailValidator/EmailValidator.php 0000666 00000002307 13436750351 0013064 0 ustar 00 lexer = new EmailLexer();
}
/**
* @param $email
* @param EmailValidation $emailValidation
* @return bool
*/
public function isValid($email, EmailValidation $emailValidation)
{
$isValid = $emailValidation->isValid($email, $this->lexer);
$this->warnings = $emailValidation->getWarnings();
$this->error = $emailValidation->getError();
return $isValid;
}
/**
* @return boolean
*/
public function hasWarnings()
{
return !empty($this->warnings);
}
/**
* @return array
*/
public function getWarnings()
{
return $this->warnings;
}
/**
* @return string
*/
public function getError()
{
return $this->error;
}
}
EmailValidator/EmailParser.php 0000666 00000005112 13436750351 0012370 0 ustar 00
*/
class EmailParser
{
const EMAIL_MAX_LENGTH = 254;
protected $warnings;
protected $domainPart = '';
protected $localPart = '';
protected $lexer;
protected $localPartParser;
protected $domainPartParser;
public function __construct(EmailLexer $lexer)
{
$this->lexer = $lexer;
$this->localPartParser = new LocalPart($this->lexer);
$this->domainPartParser = new DomainPart($this->lexer);
$this->warnings = new \SplObjectStorage();
}
/**
* @param $str
* @return array
*/
public function parse($str)
{
$this->lexer->setInput($str);
if (!$this->hasAtToken()) {
throw new NoLocalPart();
}
$this->localPartParser->parse($str);
$this->domainPartParser->parse($str);
$this->setParts($str);
if ($this->lexer->hasInvalidTokens()) {
throw new ExpectingATEXT();
}
return array('local' => $this->localPart, 'domain' => $this->domainPart);
}
public function getWarnings()
{
$localPartWarnings = $this->localPartParser->getWarnings();
$domainPartWarnings = $this->domainPartParser->getWarnings();
$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)
{
$parts = explode('@', $email);
$this->domainPart = $this->domainPartParser->getDomainPart();
$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($localPart, $parsedDomainPart)
{
if (strlen($localPart . '@' . $parsedDomainPart) > self::EMAIL_MAX_LENGTH) {
$this->warnings[EmailTooLong::CODE] = new EmailTooLong();
}
}
}
EmailValidator/EmailLexer.php 0000666 00000012072 13436750351 0012216 0 ustar 00 self::S_OPENPARENTHESIS,
')' => self::S_CLOSEPARENTHESIS,
'<' => self::S_LOWERTHAN,
'>' => self::S_GREATERTHAN,
'[' => self::S_OPENBRACKET,
']' => self::S_CLOSEBRACKET,
':' => self::S_COLON,
';' => self::S_SEMICOLON,
'@' => self::S_AT,
'\\' => self::S_BACKSLASH,
'/' => self::S_SLASH,
',' => self::S_COMMA,
'.' => self::S_DOT,
'"' => self::S_DQUOTE,
'-' => self::S_HYPHEN,
'::' => self::S_DOUBLECOLON,
' ' => self::S_SP,
"\t" => self::S_HTAB,
"\r" => self::S_CR,
"\n" => self::S_LF,
"\r\n" => self::CRLF,
'IPv6' => self::S_IPV6TAG,
'<' => self::S_LOWERTHAN,
'>' => self::S_GREATERTHAN,
'{' => self::S_OPENQBRACKET,
'}' => self::S_CLOSEQBRACKET,
'' => self::S_EMPTY,
'\0' => self::C_NUL,
);
protected $hasInvalidTokens = false;
protected $previous;
public function reset()
{
$this->hasInvalidTokens = false;
parent::reset();
}
public function hasInvalidTokens()
{
return $this->hasInvalidTokens;
}
/**
* @param $type
* @throws \UnexpectedValueException
* @return boolean
*/
public function find($type)
{
$search = clone $this;
$search->skipUntil($type);
if (!$search->lookahead) {
throw new \UnexpectedValueException($type . ' not found');
}
return true;
}
/**
* getPrevious
*
* @return array token
*/
public function getPrevious()
{
return $this->previous;
}
/**
* moveNext
*
* @return boolean
*/
public function moveNext()
{
$this->previous = $this->token;
return parent::moveNext();
}
/**
* Lexical catchable patterns.
*
* @return string[]
*/
protected function getCatchablePatterns()
{
return array(
'[a-zA-Z_]+[46]?', //ASCII and domain literal
'[^\x00-\x7F]', //UTF-8
'[0-9]+',
'\r\n',
'::',
'\s+?',
'.',
);
}
/**
* Lexical non-catchable patterns.
*
* @return string[]
*/
protected function getNonCatchablePatterns()
{
return array('[\xA0-\xff]+');
}
/**
* Retrieve token type. Also processes the token value if necessary.
*
* @param string $value
* @throws \InvalidArgumentException
* @return integer
*/
protected function getType(&$value)
{
if ($this->isNullType($value)) {
return self::C_NUL;
}
if ($this->isValid($value)) {
return $this->charValue[$value];
}
if ($this->isUTF8Invalid($value)) {
$this->hasInvalidTokens = true;
return self::INVALID;
}
return self::GENERIC;
}
protected function isValid($value)
{
if (isset($this->charValue[$value])) {
return true;
}
return false;
}
/**
* @param $value
* @return bool
*/
protected function isNullType($value)
{
if ($value === "\0") {
return true;
}
return false;
}
/**
* @param $value
* @return bool
*/
protected function isUTF8Invalid($value)
{
if (preg_match('/\p{Cc}+/u', $value)) {
return true;
}
return false;
}
protected function getModifiers()
{
return 'iu';
}
}
EmailValidator/Parser/Parser.php 0000666 00000014421 13436750351 0012657 0 ustar 00 lexer = $lexer;
}
public function getWarnings()
{
return $this->warnings;
}
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 ExpectedQPair();
}
$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();
}
}
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();
}
}
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()
{
$previous = $this->lexer->getPrevious();
if ($previous['type'] === EmailLexer::S_BACKSLASH
&&
$this->lexer->token['type'] !== EmailLexer::GENERIC
) {
return true;
}
return false;
}
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;
}
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();
}
}
}
EmailValidator/Parser/LocalPart.php 0000666 00000010555 13436750351 0013310 0 ustar 00 lexer->token['type'] !== EmailLexer::S_AT && $this->lexer->token) {
if ($this->lexer->token['type'] === EmailLexer::S_DOT && !$this->lexer->getPrevious()) {
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();
} else {
$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();
}
$this->lexer->moveNext();
}
$prev = $this->lexer->getPrevious();
if (strlen($prev['value']) > LocalTooLong::LOCAL_PART_LENGTH) {
$this->warnings[LocalTooLong::CODE] = new LocalTooLong();
}
}
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 && $this->lexer->token) {
$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;
}
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 ExpectingATEXT();
}
}
}
EmailValidator/Parser/DomainPart.php 0000666 00000027704 13436750351 0013471 0 ustar 00 lexer->moveNext();
if ($this->lexer->token['type'] === EmailLexer::S_DOT) {
throw new DotAtStart();
}
if ($this->lexer->token['type'] === EmailLexer::S_EMPTY) {
throw new NoDomainPart();
}
if ($this->lexer->token['type'] === EmailLexer::S_HYPHEN) {
throw new DomainHyphened();
}
if ($this->lexer->token['type'] === EmailLexer::S_OPENPARENTHESIS) {
$this->warnings[DeprecatedComment::CODE] = new DeprecatedComment();
$this->parseDomainComments();
}
$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;
}
public function getDomainPart()
{
return $this->domainPart;
}
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();
}
}
protected function doParseDomainPart()
{
$domain = '';
$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();
}
$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 = [EmailLexer::S_BACKSLASH => true, EmailLexer::S_SLASH=> true];
if (isset($notAllowed[$token['type']])) {
throw new CharNotAllowed();
}
}
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();
}
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;
}
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, $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 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();
}
}
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;
}
protected function checkLabelLength($prev)
{
if ($this->lexer->token['type'] === EmailLexer::S_DOT &&
$prev['type'] === EmailLexer::GENERIC &&
strlen($prev['value']) > 63
) {
$this->warnings[LabelTooLong::CODE] = new LabelTooLong();
}
}
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();
}
}
}
EmailValidator/Exception/ExpectingATEXT.php 0000666 00000000236 13436750351 0014660 0 ustar 00
./Tests/EmailValidator
./vendor/
./vendor
.coveralls.yml 0000666 00000000114 13436750351 0007346 0 ustar 00 service_name: travis-ci
src_dir: .
coverage_clover: build/logs/clover*.xml
composer.lock 0000666 00000157143 13436750351 0007273 0 ustar 00 {
"_readme": [
"This file locks the dependencies of your project to a known state",
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file",
"This file is @generated automatically"
],
"hash": "cd8cdb976fb5cd5012d94c224aa4fd4b",
"content-hash": "b0395bec21f73086fad52837dc689634",
"packages": [
{
"name": "doctrine/lexer",
"version": "v1.0.1",
"source": {
"type": "git",
"url": "https://github.com/doctrine/lexer.git",
"reference": "83893c552fd2045dd78aef794c31e694c37c0b8c"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/doctrine/lexer/zipball/83893c552fd2045dd78aef794c31e694c37c0b8c",
"reference": "83893c552fd2045dd78aef794c31e694c37c0b8c",
"shasum": ""
},
"require": {
"php": ">=5.3.2"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.0.x-dev"
}
},
"autoload": {
"psr-0": {
"Doctrine\\Common\\Lexer\\": "lib/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Roman Borschel",
"email": "roman@code-factory.org"
},
{
"name": "Guilherme Blanco",
"email": "guilhermeblanco@gmail.com"
},
{
"name": "Johannes Schmitt",
"email": "schmittjoh@gmail.com"
}
],
"description": "Base library for a lexer that can be used in Top-Down, Recursive Descent Parsers.",
"homepage": "http://www.doctrine-project.org",
"keywords": [
"lexer",
"parser"
],
"time": "2014-09-09 13:34:57"
}
],
"packages-dev": [
{
"name": "doctrine/instantiator",
"version": "1.0.5",
"source": {
"type": "git",
"url": "https://github.com/doctrine/instantiator.git",
"reference": "8e884e78f9f0eb1329e445619e04456e64d8051d"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/doctrine/instantiator/zipball/8e884e78f9f0eb1329e445619e04456e64d8051d",
"reference": "8e884e78f9f0eb1329e445619e04456e64d8051d",
"shasum": ""
},
"require": {
"php": ">=5.3,<8.0-DEV"
},
"require-dev": {
"athletic/athletic": "~0.1.8",
"ext-pdo": "*",
"ext-phar": "*",
"phpunit/phpunit": "~4.0",
"squizlabs/php_codesniffer": "~2.0"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.0.x-dev"
}
},
"autoload": {
"psr-4": {
"Doctrine\\Instantiator\\": "src/Doctrine/Instantiator/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Marco Pivetta",
"email": "ocramius@gmail.com",
"homepage": "http://ocramius.github.com/"
}
],
"description": "A small, lightweight utility to instantiate objects in PHP without invoking their constructors",
"homepage": "https://github.com/doctrine/instantiator",
"keywords": [
"constructor",
"instantiate"
],
"time": "2015-06-14 21:17:01"
},
{
"name": "dominicsayers/isemail",
"version": "dev-master",
"source": {
"type": "git",
"url": "https://github.com/dominicsayers/isemail",
"reference": "64286085b40c39e6f39b1d23276d90635e5b3099"
},
"type": "library",
"autoload": {
"files": [
"is_email.php"
]
},
"license": [
"BSD"
],
"authors": [
{
"name": "Dominic Sayers",
"email": "dominic@sayers.cc"
}
],
"description": "Checks an email address against the following RFCs: 3696, 1123, 4291, 5321, 5322",
"homepage": "http://isemail.info",
"keywords": [
"email",
"validation"
],
"support": {
"source": "https://github.com/dominicsayers/isemail",
"issues": "https://github.com/dominicsayers/isemail/issues"
},
"time": "2014-11-26 12:46:56"
},
{
"name": "guzzlehttp/guzzle",
"version": "6.2.0",
"source": {
"type": "git",
"url": "https://github.com/guzzle/guzzle.git",
"reference": "d094e337976dff9d8e2424e8485872194e768662"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/guzzle/guzzle/zipball/d094e337976dff9d8e2424e8485872194e768662",
"reference": "d094e337976dff9d8e2424e8485872194e768662",
"shasum": ""
},
"require": {
"guzzlehttp/promises": "~1.0",
"guzzlehttp/psr7": "~1.1",
"php": ">=5.5.0"
},
"require-dev": {
"ext-curl": "*",
"phpunit/phpunit": "~4.0",
"psr/log": "~1.0"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "6.2-dev"
}
},
"autoload": {
"files": [
"src/functions_include.php"
],
"psr-4": {
"GuzzleHttp\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Michael Dowling",
"email": "mtdowling@gmail.com",
"homepage": "https://github.com/mtdowling"
}
],
"description": "Guzzle is a PHP HTTP client library",
"homepage": "http://guzzlephp.org/",
"keywords": [
"client",
"curl",
"framework",
"http",
"http client",
"rest",
"web service"
],
"time": "2016-03-21 20:02:09"
},
{
"name": "guzzlehttp/promises",
"version": "1.1.0",
"source": {
"type": "git",
"url": "https://github.com/guzzle/promises.git",
"reference": "bb9024c526b22f3fe6ae55a561fd70653d470aa8"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/guzzle/promises/zipball/bb9024c526b22f3fe6ae55a561fd70653d470aa8",
"reference": "bb9024c526b22f3fe6ae55a561fd70653d470aa8",
"shasum": ""
},
"require": {
"php": ">=5.5.0"
},
"require-dev": {
"phpunit/phpunit": "~4.0"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.0-dev"
}
},
"autoload": {
"psr-4": {
"GuzzleHttp\\Promise\\": "src/"
},
"files": [
"src/functions_include.php"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Michael Dowling",
"email": "mtdowling@gmail.com",
"homepage": "https://github.com/mtdowling"
}
],
"description": "Guzzle promises library",
"keywords": [
"promise"
],
"time": "2016-03-08 01:15:46"
},
{
"name": "guzzlehttp/psr7",
"version": "1.3.0",
"source": {
"type": "git",
"url": "https://github.com/guzzle/psr7.git",
"reference": "31382fef2889136415751badebbd1cb022a4ed72"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/guzzle/psr7/zipball/31382fef2889136415751badebbd1cb022a4ed72",
"reference": "31382fef2889136415751badebbd1cb022a4ed72",
"shasum": ""
},
"require": {
"php": ">=5.4.0",
"psr/http-message": "~1.0"
},
"provide": {
"psr/http-message-implementation": "1.0"
},
"require-dev": {
"phpunit/phpunit": "~4.0"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.0-dev"
}
},
"autoload": {
"psr-4": {
"GuzzleHttp\\Psr7\\": "src/"
},
"files": [
"src/functions_include.php"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Michael Dowling",
"email": "mtdowling@gmail.com",
"homepage": "https://github.com/mtdowling"
}
],
"description": "PSR-7 message implementation",
"keywords": [
"http",
"message",
"stream",
"uri"
],
"time": "2016-04-13 19:56:01"
},
{
"name": "phpdocumentor/reflection-docblock",
"version": "2.0.4",
"source": {
"type": "git",
"url": "https://github.com/phpDocumentor/ReflectionDocBlock.git",
"reference": "d68dbdc53dc358a816f00b300704702b2eaff7b8"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/phpDocumentor/ReflectionDocBlock/zipball/d68dbdc53dc358a816f00b300704702b2eaff7b8",
"reference": "d68dbdc53dc358a816f00b300704702b2eaff7b8",
"shasum": ""
},
"require": {
"php": ">=5.3.3"
},
"require-dev": {
"phpunit/phpunit": "~4.0"
},
"suggest": {
"dflydev/markdown": "~1.0",
"erusev/parsedown": "~1.0"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "2.0.x-dev"
}
},
"autoload": {
"psr-0": {
"phpDocumentor": [
"src/"
]
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Mike van Riel",
"email": "mike.vanriel@naenius.com"
}
],
"time": "2015-02-03 12:10:50"
},
{
"name": "phpspec/prophecy",
"version": "v1.6.0",
"source": {
"type": "git",
"url": "https://github.com/phpspec/prophecy.git",
"reference": "3c91bdf81797d725b14cb62906f9a4ce44235972"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/phpspec/prophecy/zipball/3c91bdf81797d725b14cb62906f9a4ce44235972",
"reference": "3c91bdf81797d725b14cb62906f9a4ce44235972",
"shasum": ""
},
"require": {
"doctrine/instantiator": "^1.0.2",
"php": "^5.3|^7.0",
"phpdocumentor/reflection-docblock": "~2.0",
"sebastian/comparator": "~1.1",
"sebastian/recursion-context": "~1.0"
},
"require-dev": {
"phpspec/phpspec": "~2.0"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.5.x-dev"
}
},
"autoload": {
"psr-0": {
"Prophecy\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Konstantin Kudryashov",
"email": "ever.zet@gmail.com",
"homepage": "http://everzet.com"
},
{
"name": "Marcello Duarte",
"email": "marcello.duarte@gmail.com"
}
],
"description": "Highly opinionated mocking framework for PHP 5.3+",
"homepage": "https://github.com/phpspec/prophecy",
"keywords": [
"Double",
"Dummy",
"fake",
"mock",
"spy",
"stub"
],
"time": "2016-02-15 07:46:21"
},
{
"name": "phpunit/php-code-coverage",
"version": "2.2.4",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/php-code-coverage.git",
"reference": "eabf68b476ac7d0f73793aada060f1c1a9bf8979"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/eabf68b476ac7d0f73793aada060f1c1a9bf8979",
"reference": "eabf68b476ac7d0f73793aada060f1c1a9bf8979",
"shasum": ""
},
"require": {
"php": ">=5.3.3",
"phpunit/php-file-iterator": "~1.3",
"phpunit/php-text-template": "~1.2",
"phpunit/php-token-stream": "~1.3",
"sebastian/environment": "^1.3.2",
"sebastian/version": "~1.0"
},
"require-dev": {
"ext-xdebug": ">=2.1.4",
"phpunit/phpunit": "~4"
},
"suggest": {
"ext-dom": "*",
"ext-xdebug": ">=2.2.1",
"ext-xmlwriter": "*"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "2.2.x-dev"
}
},
"autoload": {
"classmap": [
"src/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"authors": [
{
"name": "Sebastian Bergmann",
"email": "sb@sebastian-bergmann.de",
"role": "lead"
}
],
"description": "Library that provides collection, processing, and rendering functionality for PHP code coverage information.",
"homepage": "https://github.com/sebastianbergmann/php-code-coverage",
"keywords": [
"coverage",
"testing",
"xunit"
],
"time": "2015-10-06 15:47:00"
},
{
"name": "phpunit/php-file-iterator",
"version": "1.4.1",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/php-file-iterator.git",
"reference": "6150bf2c35d3fc379e50c7602b75caceaa39dbf0"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/6150bf2c35d3fc379e50c7602b75caceaa39dbf0",
"reference": "6150bf2c35d3fc379e50c7602b75caceaa39dbf0",
"shasum": ""
},
"require": {
"php": ">=5.3.3"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.4.x-dev"
}
},
"autoload": {
"classmap": [
"src/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"authors": [
{
"name": "Sebastian Bergmann",
"email": "sb@sebastian-bergmann.de",
"role": "lead"
}
],
"description": "FilterIterator implementation that filters files based on a list of suffixes.",
"homepage": "https://github.com/sebastianbergmann/php-file-iterator/",
"keywords": [
"filesystem",
"iterator"
],
"time": "2015-06-21 13:08:43"
},
{
"name": "phpunit/php-text-template",
"version": "1.2.1",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/php-text-template.git",
"reference": "31f8b717e51d9a2afca6c9f046f5d69fc27c8686"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/php-text-template/zipball/31f8b717e51d9a2afca6c9f046f5d69fc27c8686",
"reference": "31f8b717e51d9a2afca6c9f046f5d69fc27c8686",
"shasum": ""
},
"require": {
"php": ">=5.3.3"
},
"type": "library",
"autoload": {
"classmap": [
"src/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"authors": [
{
"name": "Sebastian Bergmann",
"email": "sebastian@phpunit.de",
"role": "lead"
}
],
"description": "Simple template engine.",
"homepage": "https://github.com/sebastianbergmann/php-text-template/",
"keywords": [
"template"
],
"time": "2015-06-21 13:50:34"
},
{
"name": "phpunit/php-timer",
"version": "1.0.8",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/php-timer.git",
"reference": "38e9124049cf1a164f1e4537caf19c99bf1eb260"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/php-timer/zipball/38e9124049cf1a164f1e4537caf19c99bf1eb260",
"reference": "38e9124049cf1a164f1e4537caf19c99bf1eb260",
"shasum": ""
},
"require": {
"php": ">=5.3.3"
},
"require-dev": {
"phpunit/phpunit": "~4|~5"
},
"type": "library",
"autoload": {
"classmap": [
"src/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"authors": [
{
"name": "Sebastian Bergmann",
"email": "sb@sebastian-bergmann.de",
"role": "lead"
}
],
"description": "Utility class for timing",
"homepage": "https://github.com/sebastianbergmann/php-timer/",
"keywords": [
"timer"
],
"time": "2016-05-12 18:03:57"
},
{
"name": "phpunit/php-token-stream",
"version": "1.4.8",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/php-token-stream.git",
"reference": "3144ae21711fb6cac0b1ab4cbe63b75ce3d4e8da"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/php-token-stream/zipball/3144ae21711fb6cac0b1ab4cbe63b75ce3d4e8da",
"reference": "3144ae21711fb6cac0b1ab4cbe63b75ce3d4e8da",
"shasum": ""
},
"require": {
"ext-tokenizer": "*",
"php": ">=5.3.3"
},
"require-dev": {
"phpunit/phpunit": "~4.2"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.4-dev"
}
},
"autoload": {
"classmap": [
"src/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"authors": [
{
"name": "Sebastian Bergmann",
"email": "sebastian@phpunit.de"
}
],
"description": "Wrapper around PHP's tokenizer extension.",
"homepage": "https://github.com/sebastianbergmann/php-token-stream/",
"keywords": [
"tokenizer"
],
"time": "2015-09-15 10:49:45"
},
{
"name": "phpunit/phpunit",
"version": "4.8.25",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/phpunit.git",
"reference": "6d1588a6542a52ed89636e5a9876bc7502bbb853"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/6d1588a6542a52ed89636e5a9876bc7502bbb853",
"reference": "6d1588a6542a52ed89636e5a9876bc7502bbb853",
"shasum": ""
},
"require": {
"ext-dom": "*",
"ext-json": "*",
"ext-pcre": "*",
"ext-reflection": "*",
"ext-spl": "*",
"php": ">=5.3.3",
"phpspec/prophecy": "^1.3.1",
"phpunit/php-code-coverage": "~2.1",
"phpunit/php-file-iterator": "~1.4",
"phpunit/php-text-template": "~1.2",
"phpunit/php-timer": "^1.0.6",
"phpunit/phpunit-mock-objects": "~2.3",
"sebastian/comparator": "~1.1",
"sebastian/diff": "~1.2",
"sebastian/environment": "~1.3",
"sebastian/exporter": "~1.2",
"sebastian/global-state": "~1.0",
"sebastian/version": "~1.0",
"symfony/yaml": "~2.1|~3.0"
},
"suggest": {
"phpunit/php-invoker": "~1.1"
},
"bin": [
"phpunit"
],
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "4.8.x-dev"
}
},
"autoload": {
"classmap": [
"src/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"authors": [
{
"name": "Sebastian Bergmann",
"email": "sebastian@phpunit.de",
"role": "lead"
}
],
"description": "The PHP Unit Testing framework.",
"homepage": "https://phpunit.de/",
"keywords": [
"phpunit",
"testing",
"xunit"
],
"time": "2016-05-10 18:47:12"
},
{
"name": "phpunit/phpunit-mock-objects",
"version": "2.3.8",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/phpunit-mock-objects.git",
"reference": "ac8e7a3db35738d56ee9a76e78a4e03d97628983"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/phpunit-mock-objects/zipball/ac8e7a3db35738d56ee9a76e78a4e03d97628983",
"reference": "ac8e7a3db35738d56ee9a76e78a4e03d97628983",
"shasum": ""
},
"require": {
"doctrine/instantiator": "^1.0.2",
"php": ">=5.3.3",
"phpunit/php-text-template": "~1.2",
"sebastian/exporter": "~1.2"
},
"require-dev": {
"phpunit/phpunit": "~4.4"
},
"suggest": {
"ext-soap": "*"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "2.3.x-dev"
}
},
"autoload": {
"classmap": [
"src/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"authors": [
{
"name": "Sebastian Bergmann",
"email": "sb@sebastian-bergmann.de",
"role": "lead"
}
],
"description": "Mock Object library for PHPUnit",
"homepage": "https://github.com/sebastianbergmann/phpunit-mock-objects/",
"keywords": [
"mock",
"xunit"
],
"time": "2015-10-02 06:51:40"
},
{
"name": "psr/http-message",
"version": "1.0",
"source": {
"type": "git",
"url": "https://github.com/php-fig/http-message.git",
"reference": "85d63699f0dbedb190bbd4b0d2b9dc707ea4c298"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/php-fig/http-message/zipball/85d63699f0dbedb190bbd4b0d2b9dc707ea4c298",
"reference": "85d63699f0dbedb190bbd4b0d2b9dc707ea4c298",
"shasum": ""
},
"require": {
"php": ">=5.3.0"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.0.x-dev"
}
},
"autoload": {
"psr-4": {
"Psr\\Http\\Message\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "PHP-FIG",
"homepage": "http://www.php-fig.org/"
}
],
"description": "Common interface for HTTP messages",
"keywords": [
"http",
"http-message",
"psr",
"psr-7",
"request",
"response"
],
"time": "2015-05-04 20:22:00"
},
{
"name": "psr/log",
"version": "1.0.0",
"source": {
"type": "git",
"url": "https://github.com/php-fig/log.git",
"reference": "fe0936ee26643249e916849d48e3a51d5f5e278b"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/php-fig/log/zipball/fe0936ee26643249e916849d48e3a51d5f5e278b",
"reference": "fe0936ee26643249e916849d48e3a51d5f5e278b",
"shasum": ""
},
"type": "library",
"autoload": {
"psr-0": {
"Psr\\Log\\": ""
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "PHP-FIG",
"homepage": "http://www.php-fig.org/"
}
],
"description": "Common interface for logging libraries",
"keywords": [
"log",
"psr",
"psr-3"
],
"time": "2012-12-21 11:40:51"
},
{
"name": "satooshi/php-coveralls",
"version": "dev-master",
"source": {
"type": "git",
"url": "https://github.com/satooshi/php-coveralls.git",
"reference": "50c60bb64054974f8ed7540ae6e75fd7981a5fd3"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/satooshi/php-coveralls/zipball/50c60bb64054974f8ed7540ae6e75fd7981a5fd3",
"reference": "50c60bb64054974f8ed7540ae6e75fd7981a5fd3",
"shasum": ""
},
"require": {
"ext-json": "*",
"ext-simplexml": "*",
"guzzlehttp/guzzle": "^6.0",
"php": ">=5.5",
"psr/log": "^1.0",
"symfony/config": "^2.1|^3.0",
"symfony/console": "^2.1|^3.0",
"symfony/stopwatch": "^2.0|^3.0",
"symfony/yaml": "^2.0|^3.0"
},
"suggest": {
"symfony/http-kernel": "Allows Symfony integration"
},
"bin": [
"bin/coveralls"
],
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "2.0-dev"
}
},
"autoload": {
"psr-4": {
"Satooshi\\": "src/Satooshi/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Kitamura Satoshi",
"email": "with.no.parachute@gmail.com",
"homepage": "https://www.facebook.com/satooshi.jp"
}
],
"description": "PHP client library for Coveralls API",
"homepage": "https://github.com/satooshi/php-coveralls",
"keywords": [
"ci",
"coverage",
"github",
"test"
],
"time": "2016-01-20 17:44:41"
},
{
"name": "sebastian/comparator",
"version": "1.2.0",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/comparator.git",
"reference": "937efb279bd37a375bcadf584dec0726f84dbf22"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/937efb279bd37a375bcadf584dec0726f84dbf22",
"reference": "937efb279bd37a375bcadf584dec0726f84dbf22",
"shasum": ""
},
"require": {
"php": ">=5.3.3",
"sebastian/diff": "~1.2",
"sebastian/exporter": "~1.2"
},
"require-dev": {
"phpunit/phpunit": "~4.4"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.2.x-dev"
}
},
"autoload": {
"classmap": [
"src/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"authors": [
{
"name": "Jeff Welch",
"email": "whatthejeff@gmail.com"
},
{
"name": "Volker Dusch",
"email": "github@wallbash.com"
},
{
"name": "Bernhard Schussek",
"email": "bschussek@2bepublished.at"
},
{
"name": "Sebastian Bergmann",
"email": "sebastian@phpunit.de"
}
],
"description": "Provides the functionality to compare PHP values for equality",
"homepage": "http://www.github.com/sebastianbergmann/comparator",
"keywords": [
"comparator",
"compare",
"equality"
],
"time": "2015-07-26 15:48:44"
},
{
"name": "sebastian/diff",
"version": "1.4.1",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/diff.git",
"reference": "13edfd8706462032c2f52b4b862974dd46b71c9e"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/13edfd8706462032c2f52b4b862974dd46b71c9e",
"reference": "13edfd8706462032c2f52b4b862974dd46b71c9e",
"shasum": ""
},
"require": {
"php": ">=5.3.3"
},
"require-dev": {
"phpunit/phpunit": "~4.8"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.4-dev"
}
},
"autoload": {
"classmap": [
"src/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"authors": [
{
"name": "Kore Nordmann",
"email": "mail@kore-nordmann.de"
},
{
"name": "Sebastian Bergmann",
"email": "sebastian@phpunit.de"
}
],
"description": "Diff implementation",
"homepage": "https://github.com/sebastianbergmann/diff",
"keywords": [
"diff"
],
"time": "2015-12-08 07:14:41"
},
{
"name": "sebastian/environment",
"version": "1.3.6",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/environment.git",
"reference": "2292b116f43c272ff4328083096114f84ea46a56"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/2292b116f43c272ff4328083096114f84ea46a56",
"reference": "2292b116f43c272ff4328083096114f84ea46a56",
"shasum": ""
},
"require": {
"php": ">=5.3.3"
},
"require-dev": {
"phpunit/phpunit": "~4.4"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.3.x-dev"
}
},
"autoload": {
"classmap": [
"src/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"authors": [
{
"name": "Sebastian Bergmann",
"email": "sebastian@phpunit.de"
}
],
"description": "Provides functionality to handle HHVM/PHP environments",
"homepage": "http://www.github.com/sebastianbergmann/environment",
"keywords": [
"Xdebug",
"environment",
"hhvm"
],
"time": "2016-05-04 07:59:13"
},
{
"name": "sebastian/exporter",
"version": "1.2.1",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/exporter.git",
"reference": "7ae5513327cb536431847bcc0c10edba2701064e"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/7ae5513327cb536431847bcc0c10edba2701064e",
"reference": "7ae5513327cb536431847bcc0c10edba2701064e",
"shasum": ""
},
"require": {
"php": ">=5.3.3",
"sebastian/recursion-context": "~1.0"
},
"require-dev": {
"phpunit/phpunit": "~4.4"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.2.x-dev"
}
},
"autoload": {
"classmap": [
"src/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"authors": [
{
"name": "Jeff Welch",
"email": "whatthejeff@gmail.com"
},
{
"name": "Volker Dusch",
"email": "github@wallbash.com"
},
{
"name": "Bernhard Schussek",
"email": "bschussek@2bepublished.at"
},
{
"name": "Sebastian Bergmann",
"email": "sebastian@phpunit.de"
},
{
"name": "Adam Harvey",
"email": "aharvey@php.net"
}
],
"description": "Provides the functionality to export PHP variables for visualization",
"homepage": "http://www.github.com/sebastianbergmann/exporter",
"keywords": [
"export",
"exporter"
],
"time": "2015-06-21 07:55:53"
},
{
"name": "sebastian/global-state",
"version": "1.1.1",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/global-state.git",
"reference": "bc37d50fea7d017d3d340f230811c9f1d7280af4"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/bc37d50fea7d017d3d340f230811c9f1d7280af4",
"reference": "bc37d50fea7d017d3d340f230811c9f1d7280af4",
"shasum": ""
},
"require": {
"php": ">=5.3.3"
},
"require-dev": {
"phpunit/phpunit": "~4.2"
},
"suggest": {
"ext-uopz": "*"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.0-dev"
}
},
"autoload": {
"classmap": [
"src/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"authors": [
{
"name": "Sebastian Bergmann",
"email": "sebastian@phpunit.de"
}
],
"description": "Snapshotting of global state",
"homepage": "http://www.github.com/sebastianbergmann/global-state",
"keywords": [
"global state"
],
"time": "2015-10-12 03:26:01"
},
{
"name": "sebastian/recursion-context",
"version": "1.0.2",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/recursion-context.git",
"reference": "913401df809e99e4f47b27cdd781f4a258d58791"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/recursion-context/zipball/913401df809e99e4f47b27cdd781f4a258d58791",
"reference": "913401df809e99e4f47b27cdd781f4a258d58791",
"shasum": ""
},
"require": {
"php": ">=5.3.3"
},
"require-dev": {
"phpunit/phpunit": "~4.4"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.0.x-dev"
}
},
"autoload": {
"classmap": [
"src/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"authors": [
{
"name": "Jeff Welch",
"email": "whatthejeff@gmail.com"
},
{
"name": "Sebastian Bergmann",
"email": "sebastian@phpunit.de"
},
{
"name": "Adam Harvey",
"email": "aharvey@php.net"
}
],
"description": "Provides functionality to recursively process PHP variables",
"homepage": "http://www.github.com/sebastianbergmann/recursion-context",
"time": "2015-11-11 19:50:13"
},
{
"name": "sebastian/version",
"version": "1.0.6",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/version.git",
"reference": "58b3a85e7999757d6ad81c787a1fbf5ff6c628c6"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/version/zipball/58b3a85e7999757d6ad81c787a1fbf5ff6c628c6",
"reference": "58b3a85e7999757d6ad81c787a1fbf5ff6c628c6",
"shasum": ""
},
"type": "library",
"autoload": {
"classmap": [
"src/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"authors": [
{
"name": "Sebastian Bergmann",
"email": "sebastian@phpunit.de",
"role": "lead"
}
],
"description": "Library that helps with managing the version number of Git-hosted PHP projects",
"homepage": "https://github.com/sebastianbergmann/version",
"time": "2015-06-21 13:59:46"
},
{
"name": "symfony/config",
"version": "v3.0.6",
"source": {
"type": "git",
"url": "https://github.com/symfony/config.git",
"reference": "24f155da1ff180df8e15e34a8f6e2f8a0eadefa8"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/config/zipball/24f155da1ff180df8e15e34a8f6e2f8a0eadefa8",
"reference": "24f155da1ff180df8e15e34a8f6e2f8a0eadefa8",
"shasum": ""
},
"require": {
"php": ">=5.5.9",
"symfony/filesystem": "~2.8|~3.0"
},
"suggest": {
"symfony/yaml": "To use the yaml reference dumper"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "3.0-dev"
}
},
"autoload": {
"psr-4": {
"Symfony\\Component\\Config\\": ""
},
"exclude-from-classmap": [
"/Tests/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Fabien Potencier",
"email": "fabien@symfony.com"
},
{
"name": "Symfony Community",
"homepage": "https://symfony.com/contributors"
}
],
"description": "Symfony Config Component",
"homepage": "https://symfony.com",
"time": "2016-04-20 18:53:54"
},
{
"name": "symfony/console",
"version": "v3.0.6",
"source": {
"type": "git",
"url": "https://github.com/symfony/console.git",
"reference": "34a214710e0714b6efcf40ba3cd1e31373a97820"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/console/zipball/34a214710e0714b6efcf40ba3cd1e31373a97820",
"reference": "34a214710e0714b6efcf40ba3cd1e31373a97820",
"shasum": ""
},
"require": {
"php": ">=5.5.9",
"symfony/polyfill-mbstring": "~1.0"
},
"require-dev": {
"psr/log": "~1.0",
"symfony/event-dispatcher": "~2.8|~3.0",
"symfony/process": "~2.8|~3.0"
},
"suggest": {
"psr/log": "For using the console logger",
"symfony/event-dispatcher": "",
"symfony/process": ""
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "3.0-dev"
}
},
"autoload": {
"psr-4": {
"Symfony\\Component\\Console\\": ""
},
"exclude-from-classmap": [
"/Tests/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Fabien Potencier",
"email": "fabien@symfony.com"
},
{
"name": "Symfony Community",
"homepage": "https://symfony.com/contributors"
}
],
"description": "Symfony Console Component",
"homepage": "https://symfony.com",
"time": "2016-04-28 09:48:42"
},
{
"name": "symfony/filesystem",
"version": "v3.0.6",
"source": {
"type": "git",
"url": "https://github.com/symfony/filesystem.git",
"reference": "74fec3511b62cb934b64bce1d96f06fffa4beafd"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/filesystem/zipball/74fec3511b62cb934b64bce1d96f06fffa4beafd",
"reference": "74fec3511b62cb934b64bce1d96f06fffa4beafd",
"shasum": ""
},
"require": {
"php": ">=5.5.9"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "3.0-dev"
}
},
"autoload": {
"psr-4": {
"Symfony\\Component\\Filesystem\\": ""
},
"exclude-from-classmap": [
"/Tests/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Fabien Potencier",
"email": "fabien@symfony.com"
},
{
"name": "Symfony Community",
"homepage": "https://symfony.com/contributors"
}
],
"description": "Symfony Filesystem Component",
"homepage": "https://symfony.com",
"time": "2016-04-12 18:09:53"
},
{
"name": "symfony/polyfill-mbstring",
"version": "v1.1.1",
"source": {
"type": "git",
"url": "https://github.com/symfony/polyfill-mbstring.git",
"reference": "1289d16209491b584839022f29257ad859b8532d"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/1289d16209491b584839022f29257ad859b8532d",
"reference": "1289d16209491b584839022f29257ad859b8532d",
"shasum": ""
},
"require": {
"php": ">=5.3.3"
},
"suggest": {
"ext-mbstring": "For best performance"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.1-dev"
}
},
"autoload": {
"psr-4": {
"Symfony\\Polyfill\\Mbstring\\": ""
},
"files": [
"bootstrap.php"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Nicolas Grekas",
"email": "p@tchwork.com"
},
{
"name": "Symfony Community",
"homepage": "https://symfony.com/contributors"
}
],
"description": "Symfony polyfill for the Mbstring extension",
"homepage": "https://symfony.com",
"keywords": [
"compatibility",
"mbstring",
"polyfill",
"portable",
"shim"
],
"time": "2016-01-20 09:13:37"
},
{
"name": "symfony/stopwatch",
"version": "v3.0.6",
"source": {
"type": "git",
"url": "https://github.com/symfony/stopwatch.git",
"reference": "6015187088421e9499d8f8316bdb396f8b806c06"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/stopwatch/zipball/6015187088421e9499d8f8316bdb396f8b806c06",
"reference": "6015187088421e9499d8f8316bdb396f8b806c06",
"shasum": ""
},
"require": {
"php": ">=5.5.9"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "3.0-dev"
}
},
"autoload": {
"psr-4": {
"Symfony\\Component\\Stopwatch\\": ""
},
"exclude-from-classmap": [
"/Tests/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Fabien Potencier",
"email": "fabien@symfony.com"
},
{
"name": "Symfony Community",
"homepage": "https://symfony.com/contributors"
}
],
"description": "Symfony Stopwatch Component",
"homepage": "https://symfony.com",
"time": "2016-03-04 07:55:57"
},
{
"name": "symfony/yaml",
"version": "v3.0.6",
"source": {
"type": "git",
"url": "https://github.com/symfony/yaml.git",
"reference": "0047c8366744a16de7516622c5b7355336afae96"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/yaml/zipball/0047c8366744a16de7516622c5b7355336afae96",
"reference": "0047c8366744a16de7516622c5b7355336afae96",
"shasum": ""
},
"require": {
"php": ">=5.5.9"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "3.0-dev"
}
},
"autoload": {
"psr-4": {
"Symfony\\Component\\Yaml\\": ""
},
"exclude-from-classmap": [
"/Tests/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Fabien Potencier",
"email": "fabien@symfony.com"
},
{
"name": "Symfony Community",
"homepage": "https://symfony.com/contributors"
}
],
"description": "Symfony Yaml Component",
"homepage": "https://symfony.com",
"time": "2016-03-04 07:55:57"
}
],
"aliases": [],
"minimum-stability": "stable",
"stability-flags": {
"satooshi/php-coveralls": 20,
"dominicsayers/isemail": 20
},
"prefer-stable": false,
"prefer-lowest": false,
"platform": {
"php": ">= 5.5"
},
"platform-dev": []
}
Tests/resources/is_email_tests.xml 0000666 00000134204 13436750351 0013425 0 ustar 00
New test set
This test set is designed to replace and extend the coverage of the original set but with fewer tests.
Thanks to Michael Rushton (michael@squiloople.com) for starting this work and contributing tests 1-100
ISEMAIL_ERR
ISEMAIL_ERR_NODOMAIN
Michael Rushton
http://squiloople.com/tag/email/
test
ISEMAIL_ERR
ISEMAIL_ERR_NODOMAIN
Michael Rushton
http://squiloople.com/tag/email/
@
ISEMAIL_ERR
ISEMAIL_ERR_NOLOCALPART
Michael Rushton
http://squiloople.com/tag/email/
test@
ISEMAIL_ERR
ISEMAIL_ERR_NODOMAIN
Michael Rushton
http://squiloople.com/tag/email/
test@io
io. currently has an MX-record (Feb 2011). Some DNS setups seem to find it, some don't. If you don't see the MX for io. then try setting your DNS server to 8.8.8.8 (the Google DNS server)
ISEMAIL_VALID_CATEGORY
ISEMAIL_VALID
Michael Rushton
http://squiloople.com/tag/email/
@io
io. currently has an MX-record (Feb 2011)
ISEMAIL_ERR
ISEMAIL_ERR_NOLOCALPART
Michael Rushton
http://squiloople.com/tag/email/
@iana.org
ISEMAIL_ERR
ISEMAIL_ERR_NOLOCALPART
Michael Rushton
http://squiloople.com/tag/email/
test@iana.org
ISEMAIL_VALID_CATEGORY
ISEMAIL_VALID
Michael Rushton
http://squiloople.com/tag/email/
test@nominet.org.uk
ISEMAIL_VALID_CATEGORY
ISEMAIL_VALID
Michael Rushton
http://squiloople.com/tag/email/
test@about.museum
ISEMAIL_VALID_CATEGORY
ISEMAIL_VALID
Michael Rushton
http://squiloople.com/tag/email/
a@iana.org
ISEMAIL_VALID_CATEGORY
ISEMAIL_VALID
Michael Rushton
http://squiloople.com/tag/email/
test@e.com
ISEMAIL_DNSWARN
ISEMAIL_DNSWARN_NO_RECORD
Michael Rushton
http://squiloople.com/tag/email/
test@iana.a
ISEMAIL_DNSWARN
ISEMAIL_DNSWARN_NO_RECORD
Michael Rushton
http://squiloople.com/tag/email/
test.test@iana.org
ISEMAIL_VALID_CATEGORY
ISEMAIL_VALID
Michael Rushton
http://squiloople.com/tag/email/
.test@iana.org
ISEMAIL_ERR
ISEMAIL_ERR_DOT_START
Michael Rushton
http://squiloople.com/tag/email/
test.@iana.org
ISEMAIL_ERR
ISEMAIL_ERR_DOT_END
Michael Rushton
http://squiloople.com/tag/email/
test..iana.org
ISEMAIL_ERR
ISEMAIL_ERR_CONSECUTIVEDOTS
Michael Rushton
http://squiloople.com/tag/email/
test_exa-mple.com
ISEMAIL_ERR
ISEMAIL_ERR_NODOMAIN
Michael Rushton
http://squiloople.com/tag/email/
!#$%&`*+/=?^`{|}~@iana.org
ISEMAIL_VALID_CATEGORY
ISEMAIL_VALID
Michael Rushton
http://squiloople.com/tag/email/
test\@test@iana.org
ISEMAIL_ERR
ISEMAIL_ERR_EXPECTING_ATEXT
Michael Rushton
http://squiloople.com/tag/email/
123@iana.org
ISEMAIL_VALID_CATEGORY
ISEMAIL_VALID
Michael Rushton
http://squiloople.com/tag/email/
test@123.com
ISEMAIL_VALID_CATEGORY
ISEMAIL_VALID
Michael Rushton
http://squiloople.com/tag/email/
test@iana.123
ISEMAIL_RFC5321
ISEMAIL_RFC5321_TLDNUMERIC
Michael Rushton
http://squiloople.com/tag/email/
test@255.255.255.255
ISEMAIL_RFC5321
ISEMAIL_RFC5321_TLDNUMERIC
Michael Rushton
http://squiloople.com/tag/email/
abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghiklm@iana.org
ISEMAIL_VALID_CATEGORY
ISEMAIL_VALID
Michael Rushton
http://squiloople.com/tag/email/
abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghiklmn@iana.org
ISEMAIL_RFC5322
ISEMAIL_RFC5322_LOCAL_TOOLONG
Michael Rushton
http://squiloople.com/tag/email/
test@abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghikl.com
ISEMAIL_DNSWARN
ISEMAIL_DNSWARN_NO_RECORD
Michael Rushton
http://squiloople.com/tag/email/
test@abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghiklm.com
ISEMAIL_RFC5322
ISEMAIL_RFC5322_LABEL_TOOLONG
Michael Rushton
http://squiloople.com/tag/email/
test@mason-dixon.com
ISEMAIL_VALID_CATEGORY
ISEMAIL_VALID
Michael Rushton
http://squiloople.com/tag/email/
test@-iana.org
ISEMAIL_ERR
ISEMAIL_ERR_DOMAINHYPHENSTART
Michael Rushton
http://squiloople.com/tag/email/
test@iana-.com
ISEMAIL_ERR
ISEMAIL_ERR_DOMAINHYPHENEND
Michael Rushton
http://squiloople.com/tag/email/
test@c--n.com
c--n.com currently has an MX-record (May 2011)
ISEMAIL_VALID_CATEGORY
ISEMAIL_VALID
Michael Rushton
http://squiloople.com/tag/email/
test@iana.co-uk
ISEMAIL_DNSWARN
ISEMAIL_DNSWARN_NO_RECORD
Michael Rushton
http://squiloople.com/tag/email/
test@.iana.org
ISEMAIL_ERR
ISEMAIL_ERR_DOT_START
Michael Rushton
http://squiloople.com/tag/email/
test@iana.org.
ISEMAIL_ERR
ISEMAIL_ERR_DOT_END
Michael Rushton
http://squiloople.com/tag/email/
test@iana..com
ISEMAIL_ERR
ISEMAIL_ERR_CONSECUTIVEDOTS
Michael Rushton
http://squiloople.com/tag/email/
a@a.b.c.d.e.f.g.h.i.j.k.l.m.n.o.p.q.r.s.t.u.v.w.x.y.z.a.b.c.d.e.f.g.h.i.j.k.l.m.n.o.p.q.r.s.t.u.v.w.x.y.z.a.b.c.d.e.f.g.h.i.j.k.l.m.n.o.p.q.r.s.t.u.v.w.x.y.z.a.b.c.d.e.f.g.h.i.j.k.l.m.n.o.p.q.r.s.t.u.v.w.x.y.z.a.b.c.d.e.f.g.h.i.j.k.l.m.n.o.p.q.r.s.t.u.v
ISEMAIL_DNSWARN
ISEMAIL_DNSWARN_NO_RECORD
Michael Rushton
http://squiloople.com/tag/email/
abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghiklm@abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghikl.abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghikl.abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghi
ISEMAIL_DNSWARN
ISEMAIL_DNSWARN_NO_RECORD
Michael Rushton
http://squiloople.com/tag/email/
abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghiklm@abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghikl.abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghikl.abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghij
ISEMAIL_RFC5322
ISEMAIL_RFC5322_TOOLONG
Michael Rushton
http://squiloople.com/tag/email/
a@abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghikl.abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghikl.abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghikl.abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefg.hij
ISEMAIL_RFC5322
ISEMAIL_RFC5322_TOOLONG
Michael Rushton
http://squiloople.com/tag/email/
a@abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghikl.abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghikl.abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghikl.abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefg.hijk
ISEMAIL_RFC5322
ISEMAIL_RFC5322_DOMAIN_TOOLONG
Michael Rushton
http://squiloople.com/tag/email/
"test"@iana.org
ISEMAIL_RFC5321
ISEMAIL_RFC5321_QUOTEDSTRING
Michael Rushton
http://squiloople.com/tag/email/
""@iana.org
ISEMAIL_RFC5321
ISEMAIL_RFC5321_QUOTEDSTRING
Michael Rushton
http://squiloople.com/tag/email/
"""@iana.org
ISEMAIL_ERR
ISEMAIL_ERR_EXPECTING_ATEXT
Michael Rushton
http://squiloople.com/tag/email/
"\a"@iana.org
ISEMAIL_RFC5321
ISEMAIL_RFC5321_QUOTEDSTRING
Michael Rushton
http://squiloople.com/tag/email/
"\""@iana.org
ISEMAIL_RFC5321
ISEMAIL_RFC5321_QUOTEDSTRING
Michael Rushton
http://squiloople.com/tag/email/
"\"@iana.org
ISEMAIL_ERR
ISEMAIL_ERR_UNCLOSEDQUOTEDSTR
Michael Rushton
http://squiloople.com/tag/email/
"\\"@iana.org
ISEMAIL_RFC5321
ISEMAIL_RFC5321_QUOTEDSTRING
Michael Rushton
http://squiloople.com/tag/email/
test"@iana.org
ISEMAIL_ERR
ISEMAIL_ERR_EXPECTING_ATEXT
Michael Rushton
http://squiloople.com/tag/email/
"test@iana.org
ISEMAIL_ERR
ISEMAIL_ERR_UNCLOSEDQUOTEDSTR
Michael Rushton
http://squiloople.com/tag/email/
"test"test@iana.org
ISEMAIL_ERR
ISEMAIL_ERR_ATEXT_AFTER_QS
Michael Rushton
http://squiloople.com/tag/email/
test"text"@iana.org
ISEMAIL_ERR
ISEMAIL_ERR_EXPECTING_ATEXT
Michael Rushton
http://squiloople.com/tag/email/
"test""test"@iana.org
ISEMAIL_ERR
ISEMAIL_ERR_EXPECTING_ATEXT
Michael Rushton
http://squiloople.com/tag/email/
"test"."test"@iana.org
ISEMAIL_DEPREC
ISEMAIL_DEPREC_LOCALPART
Michael Rushton
http://squiloople.com/tag/email/
"test\ test"@iana.org
ISEMAIL_RFC5321
ISEMAIL_RFC5321_QUOTEDSTRING
Michael Rushton
http://squiloople.com/tag/email/
"test".test@iana.org
ISEMAIL_DEPREC
ISEMAIL_DEPREC_LOCALPART
Michael Rushton
http://squiloople.com/tag/email/
"test␀"@iana.org
ISEMAIL_ERR
ISEMAIL_ERR_EXPECTING_QTEXT
Michael Rushton
http://squiloople.com/tag/email/
"test\␀"@iana.org
ISEMAIL_DEPREC
ISEMAIL_DEPREC_QP
Michael Rushton
http://squiloople.com/tag/email/
"abcdefghijklmnopqrstuvwxyz abcdefghijklmnopqrstuvwxyz abcdefghj"@iana.org
Quotes are still part of the length restriction
ISEMAIL_RFC5322
ISEMAIL_RFC5322_LOCAL_TOOLONG
Dominic Sayers
http://isemail.info
"abcdefghijklmnopqrstuvwxyz abcdefghijklmnopqrstuvwxyz abcdefg\h"@iana.org
Quoted pair is still part of the length restriction
ISEMAIL_RFC5322
ISEMAIL_RFC5322_LOCAL_TOOLONG
Dominic Sayers
http://isemail.info
test@[255.255.255.255]
ISEMAIL_RFC5321
ISEMAIL_RFC5321_ADDRESSLITERAL
Michael Rushton
http://squiloople.com/tag/email/
test@a[255.255.255.255]
ISEMAIL_ERR
ISEMAIL_ERR_EXPECTING_ATEXT
Michael Rushton
http://squiloople.com/tag/email/
test@[255.255.255]
ISEMAIL_RFC5322
ISEMAIL_RFC5322_DOMAINLITERAL
Michael Rushton
http://squiloople.com/tag/email/
test@[255.255.255.255.255]
ISEMAIL_RFC5322
ISEMAIL_RFC5322_DOMAINLITERAL
Michael Rushton
http://squiloople.com/tag/email/
test@[255.255.255.256]
ISEMAIL_RFC5322
ISEMAIL_RFC5322_DOMAINLITERAL
Michael Rushton
http://squiloople.com/tag/email/
test@[1111:2222:3333:4444:5555:6666:7777:8888]
ISEMAIL_RFC5322
ISEMAIL_RFC5322_DOMAINLITERAL
Michael Rushton
http://squiloople.com/tag/email/
test@[IPv6:1111:2222:3333:4444:5555:6666:7777]
ISEMAIL_RFC5322
ISEMAIL_RFC5322_IPV6_GRPCOUNT
Michael Rushton
http://squiloople.com/tag/email/
test@[IPv6:1111:2222:3333:4444:5555:6666:7777:8888]
ISEMAIL_RFC5321
ISEMAIL_RFC5321_ADDRESSLITERAL
Michael Rushton
http://squiloople.com/tag/email/
test@[IPv6:1111:2222:3333:4444:5555:6666:7777:8888:9999]
ISEMAIL_RFC5322
ISEMAIL_RFC5322_IPV6_GRPCOUNT
Michael Rushton
http://squiloople.com/tag/email/
test@[IPv6:1111:2222:3333:4444:5555:6666:7777:888G]
ISEMAIL_RFC5322
ISEMAIL_RFC5322_IPV6_BADCHAR
Michael Rushton
http://squiloople.com/tag/email/
test@[IPv6:1111:2222:3333:4444:5555:6666::8888]
ISEMAIL_DEPREC
ISEMAIL_RFC5321_IPV6DEPRECATED
Michael Rushton
http://squiloople.com/tag/email/
test@[IPv6:1111:2222:3333:4444:5555::8888]
ISEMAIL_RFC5321
ISEMAIL_RFC5321_ADDRESSLITERAL
Michael Rushton
http://squiloople.com/tag/email/
test@[IPv6:1111:2222:3333:4444:5555:6666::7777:8888]
ISEMAIL_RFC5322
ISEMAIL_RFC5322_IPV6_MAXGRPS
Michael Rushton
http://squiloople.com/tag/email/
test@[IPv6::3333:4444:5555:6666:7777:8888]
ISEMAIL_RFC5322
ISEMAIL_RFC5322_IPV6_COLONSTRT
Michael Rushton
http://squiloople.com/tag/email/
test@[IPv6:::3333:4444:5555:6666:7777:8888]
ISEMAIL_RFC5321
ISEMAIL_RFC5321_ADDRESSLITERAL
Michael Rushton
http://squiloople.com/tag/email/
test@[IPv6:1111::4444:5555::8888]
ISEMAIL_RFC5322
ISEMAIL_RFC5322_IPV6_2X2XCOLON
Michael Rushton
http://squiloople.com/tag/email/
test@[IPv6:::]
ISEMAIL_RFC5321
ISEMAIL_RFC5321_ADDRESSLITERAL
Michael Rushton
http://squiloople.com/tag/email/
test@[IPv6:1111:2222:3333:4444:5555:255.255.255.255]
ISEMAIL_RFC5322
ISEMAIL_RFC5322_IPV6_GRPCOUNT
Michael Rushton
http://squiloople.com/tag/email/
test@[IPv6:1111:2222:3333:4444:5555:6666:255.255.255.255]
ISEMAIL_RFC5321
ISEMAIL_RFC5321_ADDRESSLITERAL
Michael Rushton
http://squiloople.com/tag/email/
test@[IPv6:1111:2222:3333:4444:5555:6666:7777:255.255.255.255]
ISEMAIL_RFC5322
ISEMAIL_RFC5322_IPV6_GRPCOUNT
Michael Rushton
http://squiloople.com/tag/email/
test@[IPv6:1111:2222:3333:4444::255.255.255.255]
ISEMAIL_RFC5321
ISEMAIL_RFC5321_ADDRESSLITERAL
Michael Rushton
http://squiloople.com/tag/email/
test@[IPv6:1111:2222:3333:4444:5555:6666::255.255.255.255]
ISEMAIL_RFC5322
ISEMAIL_RFC5322_IPV6_MAXGRPS
Michael Rushton
http://squiloople.com/tag/email/
test@[IPv6:1111:2222:3333:4444:::255.255.255.255]
ISEMAIL_RFC5322
ISEMAIL_RFC5322_IPV6_2X2XCOLON
Michael Rushton
http://squiloople.com/tag/email/
test@[IPv6::255.255.255.255]
ISEMAIL_RFC5322
ISEMAIL_RFC5322_IPV6_COLONSTRT
Michael Rushton
http://squiloople.com/tag/email/
test @iana.org
ISEMAIL_DEPREC
ISEMAIL_DEPREC_CFWS_NEAR_AT
Michael Rushton
http://squiloople.com/tag/email/
test@ iana .com
ISEMAIL_DEPREC
ISEMAIL_DEPREC_CFWS_NEAR_AT
Michael Rushton
http://squiloople.com/tag/email/
test . test@iana.org
ISEMAIL_DEPREC
ISEMAIL_DEPREC_FWS
Michael Rushton
http://squiloople.com/tag/email/
␍␊ test@iana.org
FWS
ISEMAIL_CFWS
ISEMAIL_CFWS_FWS
Michael Rushton
http://squiloople.com/tag/email/
␍␊ ␍␊ test@iana.org
FWS with one line composed entirely of WSP -- only allowed as obsolete FWS (someone might allow only non-obsolete FWS)
ISEMAIL_DEPREC
ISEMAIL_DEPREC_FWS
Michael Rushton
http://squiloople.com/tag/email/
(comment)test@iana.org
ISEMAIL_CFWS
ISEMAIL_CFWS_COMMENT
Michael Rushton
http://squiloople.com/tag/email/
((comment)test@iana.org
ISEMAIL_ERR
ISEMAIL_ERR_UNCLOSEDCOMMENT
Michael Rushton
http://squiloople.com/tag/email/
(comment(comment))test@iana.org
ISEMAIL_CFWS
ISEMAIL_CFWS_COMMENT
Michael Rushton
http://squiloople.com/tag/email/
test@(comment)iana.org
ISEMAIL_DEPREC
ISEMAIL_DEPREC_CFWS_NEAR_AT
Michael Rushton
http://squiloople.com/tag/email/
test(comment)test@iana.org
ISEMAIL_ERR
ISEMAIL_ERR_ATEXT_AFTER_CFWS
Michael Rushton
http://squiloople.com/tag/email/
test@(comment)[255.255.255.255]
ISEMAIL_DEPREC
ISEMAIL_DEPREC_CFWS_NEAR_AT
Michael Rushton
http://squiloople.com/tag/email/
(comment)abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghiklm@iana.org
ISEMAIL_CFWS
ISEMAIL_CFWS_COMMENT
Michael Rushton
http://squiloople.com/tag/email/
test@(comment)abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghikl.com
ISEMAIL_DEPREC
ISEMAIL_DEPREC_CFWS_NEAR_AT
Michael Rushton
http://squiloople.com/tag/email/
(comment)test@abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghik.abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghik.abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijk.abcdefghijklmnopqrstuvwxyzabcdefghijk.abcdefghijklmnopqrstu
ISEMAIL_CFWS
ISEMAIL_CFWS_COMMENT
Michael Rushton
http://squiloople.com/tag/email/
test@iana.org␊
ISEMAIL_ERR
ISEMAIL_ERR_EXPECTING_ATEXT
Michael Rushton
http://squiloople.com/tag/email/
test@xn--hxajbheg2az3al.xn--jxalpdlp
A valid IDN from ICANN's IDN TLD evaluation gateway
ISEMAIL_VALID_CATEGORY
ISEMAIL_VALID
Michael Rushton
http://squiloople.com/tag/email/
xn--test@iana.org
RFC 3490: "unless the
email standards are revised to invite the use of IDNA for local
parts, a domain label that holds the local part of an email address
SHOULD NOT begin with the ACE prefix, and even if it does, it is to
be interpreted literally as a local part that happens to begin with
the ACE prefix"
ISEMAIL_VALID_CATEGORY
ISEMAIL_VALID
Dominic Sayers
http://isemail.info
test@iana.org-
ISEMAIL_ERR
ISEMAIL_ERR_DOMAINHYPHENEND
Dominic Sayers
http://isemail.info
"test@iana.org
ISEMAIL_ERR
ISEMAIL_ERR_UNCLOSEDQUOTEDSTR
Dominic Sayers
http://isemail.info
(test@iana.org
ISEMAIL_ERR
ISEMAIL_ERR_UNCLOSEDCOMMENT
Dominic Sayers
http://isemail.info
test@(iana.org
ISEMAIL_ERR
ISEMAIL_ERR_UNCLOSEDCOMMENT
Dominic Sayers
http://isemail.info
test@[1.2.3.4
ISEMAIL_ERR
ISEMAIL_ERR_UNCLOSEDDOMLIT
Dominic Sayers
http://isemail.info
"test\"@iana.org
ISEMAIL_ERR
ISEMAIL_ERR_UNCLOSEDQUOTEDSTR
Dominic Sayers
http://isemail.info
(comment\)test@iana.org
ISEMAIL_ERR
ISEMAIL_ERR_UNCLOSEDCOMMENT
Dominic Sayers
http://isemail.info
test@iana.org(comment\)
ISEMAIL_ERR
ISEMAIL_ERR_UNCLOSEDCOMMENT
Dominic Sayers
http://isemail.info
test@iana.org(comment\
ISEMAIL_ERR
ISEMAIL_ERR_BACKSLASHEND
Dominic Sayers
http://isemail.info
test@[RFC-5322-domain-literal]
ISEMAIL_RFC5322
ISEMAIL_RFC5322_DOMAINLITERAL
Dominic Sayers
http://isemail.info
test@[RFC-5322]-domain-literal]
ISEMAIL_ERR
ISEMAIL_ERR_ATEXT_AFTER_DOMLIT
Dominic Sayers
http://isemail.info
test@[RFC-5322-[domain-literal]
ISEMAIL_ERR
ISEMAIL_ERR_EXPECTING_DTEXT
Dominic Sayers
http://isemail.info
test@[RFC-5322-\␇-domain-literal]
obs-dtext and obs-qp
ISEMAIL_RFC5322
ISEMAIL_RFC5322_DOMLIT_OBSDTEXT
Dominic Sayers
http://isemail.info
test@[RFC-5322-\␉-domain-literal]
ISEMAIL_RFC5322
ISEMAIL_RFC5322_DOMLIT_OBSDTEXT
Dominic Sayers
http://isemail.info
test@[RFC-5322-\]-domain-literal]
ISEMAIL_RFC5322
ISEMAIL_RFC5322_DOMLIT_OBSDTEXT
Dominic Sayers
http://isemail.info
test@[RFC-5322-domain-literal\]
ISEMAIL_ERR
ISEMAIL_ERR_UNCLOSEDDOMLIT
Dominic Sayers
http://isemail.info
test@[RFC-5322-domain-literal\
ISEMAIL_ERR
ISEMAIL_ERR_BACKSLASHEND
Dominic Sayers
http://isemail.info
test@[RFC 5322 domain literal]
Spaces are FWS in a domain literal
ISEMAIL_RFC5322
ISEMAIL_RFC5322_DOMAINLITERAL
Dominic Sayers
http://isemail.info
test@[RFC-5322-domain-literal] (comment)
ISEMAIL_RFC5322
ISEMAIL_RFC5322_DOMAINLITERAL
Dominic Sayers
http://isemail.info
@iana.org
ISEMAIL_ERR
ISEMAIL_ERR_EXPECTING_ATEXT
Dominic Sayers
http://isemail.info
test@.org
ISEMAIL_ERR
ISEMAIL_ERR_EXPECTING_ATEXT
Dominic Sayers
http://isemail.info
""@iana.org
ISEMAIL_DEPREC
ISEMAIL_DEPREC_QTEXT
Dominic Sayers
http://isemail.info
"\"@iana.org
ISEMAIL_DEPREC
ISEMAIL_DEPREC_QP
Dominic Sayers
http://isemail.info
()test@iana.org
ISEMAIL_DEPREC
ISEMAIL_DEPREC_CTEXT
Dominic Sayers
http://isemail.info
test@iana.org␍
No LF after the CR
ISEMAIL_ERR
ISEMAIL_ERR_CR_NO_LF
Dominic Sayers
http://isemail.info
␍test@iana.org
No LF after the CR
ISEMAIL_ERR
ISEMAIL_ERR_CR_NO_LF
Dominic Sayers
http://isemail.info
"␍test"@iana.org
No LF after the CR
ISEMAIL_ERR
ISEMAIL_ERR_CR_NO_LF
Dominic Sayers
http://isemail.info
(␍)test@iana.org
No LF after the CR
ISEMAIL_ERR
ISEMAIL_ERR_CR_NO_LF
Dominic Sayers
http://isemail.info
test@iana.org(␍)
No LF after the CR
ISEMAIL_ERR
ISEMAIL_ERR_CR_NO_LF
Dominic Sayers
http://isemail.info
␊test@iana.org
ISEMAIL_ERR
ISEMAIL_ERR_EXPECTING_ATEXT
Michael Rushton
http://squiloople.com/tag/email/
"␊"@iana.org
ISEMAIL_ERR
ISEMAIL_ERR_EXPECTING_QTEXT
Dominic Sayers
http://isemail.info
"\␊"@iana.org
ISEMAIL_DEPREC
ISEMAIL_DEPREC_QP
Dominic Sayers
http://isemail.info
(␊)test@iana.org
ISEMAIL_ERR
ISEMAIL_ERR_EXPECTING_CTEXT
Dominic Sayers
http://isemail.info
␇@iana.org
ISEMAIL_ERR
ISEMAIL_ERR_EXPECTING_ATEXT
Dominic Sayers
http://isemail.info
test@␇.org
ISEMAIL_ERR
ISEMAIL_ERR_EXPECTING_ATEXT
Dominic Sayers
http://isemail.info
"␇"@iana.org
ISEMAIL_DEPREC
ISEMAIL_DEPREC_QTEXT
Dominic Sayers
http://isemail.info
"\␇"@iana.org
ISEMAIL_DEPREC
ISEMAIL_DEPREC_QP
Dominic Sayers
http://isemail.info
(␇)test@iana.org
ISEMAIL_DEPREC
ISEMAIL_DEPREC_CTEXT
Dominic Sayers
http://isemail.info
␍␊test@iana.org
Not FWS because no actual white space
ISEMAIL_ERR
ISEMAIL_ERR_FWS_CRLF_END
Dominic Sayers
http://isemail.info
␍␊ ␍␊test@iana.org
Not obs-FWS because there must be white space on each "fold"
ISEMAIL_ERR
ISEMAIL_ERR_FWS_CRLF_END
Dominic Sayers
http://isemail.info
␍␊test@iana.org
Not FWS because no white space after the fold
ISEMAIL_ERR
ISEMAIL_ERR_FWS_CRLF_END
Dominic Sayers
http://isemail.info
␍␊ test@iana.org
FWS
ISEMAIL_CFWS
ISEMAIL_CFWS_FWS
Dominic Sayers
http://isemail.info
␍␊ ␍␊test@iana.org
Not FWS because no white space after the second fold
ISEMAIL_ERR
ISEMAIL_ERR_FWS_CRLF_END
Dominic Sayers
http://isemail.info
␍␊␍␊test@iana.org
Not FWS because no white space after either fold
ISEMAIL_ERR
ISEMAIL_ERR_FWS_CRLF_X2
Dominic Sayers
http://isemail.info
␍␊␍␊ test@iana.org
Not FWS because no white space after the first fold
ISEMAIL_ERR
ISEMAIL_ERR_FWS_CRLF_X2
Dominic Sayers
http://isemail.info
test@iana.org␍␊
FWS
ISEMAIL_CFWS
ISEMAIL_CFWS_FWS
Dominic Sayers
http://isemail.info
test@iana.org␍␊ ␍␊
FWS with one line composed entirely of WSP -- only allowed as obsolete FWS (someone might allow only non-obsolete FWS)
ISEMAIL_DEPREC
ISEMAIL_DEPREC_FWS
Dominic Sayers
http://isemail.info
test@iana.org␍␊
Not FWS because no actual white space
ISEMAIL_ERR
ISEMAIL_ERR_FWS_CRLF_END
Dominic Sayers
http://isemail.info
test@iana.org␍␊ ␍␊
Not obs-FWS because there must be white space on each "fold"
ISEMAIL_ERR
ISEMAIL_ERR_FWS_CRLF_END
Dominic Sayers
http://isemail.info
test@iana.org ␍␊
Not FWS because no white space after the fold
ISEMAIL_ERR
ISEMAIL_ERR_FWS_CRLF_END
Dominic Sayers
http://isemail.info
test@iana.org ␍␊
FWS
ISEMAIL_CFWS
ISEMAIL_CFWS_FWS
Dominic Sayers
http://isemail.info
test@iana.org ␍␊ ␍␊
Not FWS because no white space after the second fold
ISEMAIL_ERR
ISEMAIL_ERR_FWS_CRLF_END
Dominic Sayers
http://isemail.info
test@iana.org ␍␊␍␊
Not FWS because no white space after either fold
ISEMAIL_ERR
ISEMAIL_ERR_FWS_CRLF_X2
Dominic Sayers
http://isemail.info
test@iana.org ␍␊␍␊
Not FWS because no white space after the first fold
ISEMAIL_ERR
ISEMAIL_ERR_FWS_CRLF_X2
Dominic Sayers
http://isemail.info
test@iana.org
ISEMAIL_CFWS
ISEMAIL_CFWS_FWS
Dominic Sayers
http://isemail.info
test@iana.org
ISEMAIL_CFWS
ISEMAIL_CFWS_FWS
Dominic Sayers
http://isemail.info
test@[IPv6:1::2:]
ISEMAIL_RFC5322
ISEMAIL_RFC5322_IPV6_COLONEND
Dominic Sayers
http://isemail.info
"test\©"@iana.org
ISEMAIL_ERR
ISEMAIL_ERR_EXPECTING_QPAIR
Dominic Sayers
http://isemail.info
test@iana/icann.org
ISEMAIL_RFC5322
ISEMAIL_RFC5322_DOMAIN
Dominic Sayers
http://isemail.info
test.(comment)test@iana.org
ISEMAIL_DEPREC
ISEMAIL_DEPREC_COMMENT
Dominic Sayers
http://isemail.info
test@org
ISEMAIL_RFC5321
ISEMAIL_RFC5321_TLD
Dominic Sayers
http://isemail.info
test@test.com
test.com has an A-record but not an MX-record
ISEMAIL_DNSWARN
ISEMAIL_DNSWARN_NO_MX_RECORD
Dominic Sayers
http://isemail.info
test@nic.no
nic.no currently has no MX-records or A-records (Feb 2011). If you are seeing an A-record for nic.io then try setting your DNS server to 8.8.8.8 (the Google DNS server) - your DNS server may be faking an A-record (OpenDNS does this, for instance).
ISEMAIL_DNSWARN
ISEMAIL_DNSWARN_NO_RECORD
Dominic Sayers
http://isemail.info
Tests/EmailValidator/Validation/RFCValidationTest.php 0000666 00000026257 13436750351 0016662 0 ustar 00 validator = new RFCValidation();
$this->lexer = new EmailLexer();
}
protected function tearDown()
{
$this->validator = null;
}
/**
* @dataProvider getValidEmails
*/
public function testValidEmails($email)
{
$this->assertTrue($this->validator->isValid($email, $this->lexer));
}
public function getValidEmails()
{
return array(
['â@iana.org'],
['fabien@symfony.com'],
['example@example.co.uk'],
['fabien_potencier@example.fr'],
['example@localhost'],
['fab\'ien@symfony.com'],
['fab\ ien@symfony.com'],
['example((example))@fakedfake.co.uk'],
['example@faked(fake).co.uk'],
['fabien+@symfony.com'],
['инфо@письмо.рф'],
['"username"@example.com'],
['"user,name"@example.com'],
['"user name"@example.com'],
['"user@name"@example.com'],
['"user\"name"@example.com'],
['"\a"@iana.org'],
['"test\ test"@iana.org'],
['""@iana.org'],
['"\""@iana.org'],
['müller@möller.de'],
['test@email*'],
['test@email!'],
['test@email&'],
['test@email^'],
['test@email%'],
['test@email$'],
["1500111@профи-инвест.рф"],
);
}
public function testInvalidUTF8Email()
{
$email = "\x80\x81\x82@\x83\x84\x85.\x86\x87\x88";
$this->assertFalse($this->validator->isValid($email, $this->lexer));
}
/**
* @dataProvider getInvalidEmails
*/
public function testInvalidEmails($email)
{
$this->assertFalse($this->validator->isValid($email, $this->lexer));
}
public function getInvalidEmails()
{
return [
['test@example.com test'],
['user name@example.com'],
['user name@example.com'],
['example.@example.co.uk'],
['example@example@example.co.uk'],
['(test_exampel@example.fr]'],
['example(example]example@example.co.uk'],
['.example@localhost'],
['ex\ample@localhost'],
['example@local\host'],
['example@localhost\\'],
['example@localhost.'],
['user name@example.com'],
['username@ example . com'],
['example@(fake].com'],
['example@(fake.com'],
['username@example,com'],
['usern,ame@example.com'],
['user[na]me@example.com'],
['"""@iana.org'],
['"\"@iana.org'],
['"test"test@iana.org'],
['"test""test"@iana.org'],
['"test"."test"@iana.org'],
['"test".test@iana.org'],
['"test"' . chr(0) . '@iana.org'],
['"test\"@iana.org'],
[chr(226) . '@iana.org'],
['test@' . chr(226) . '.org'],
['\r\ntest@iana.org'],
['\r\n test@iana.org'],
['\r\n \r\ntest@iana.org'],
['\r\n \r\ntest@iana.org'],
['\r\n \r\n test@iana.org'],
['test@iana.org \r\n'],
['test@iana.org \r\n '],
['test@iana.org \r\n \r\n'],
['test@iana.org \r\n\r\n'],
['test@iana.org \r\n\r\n '],
['test@iana/icann.org'],
['test@foo;bar.com'],
['test;123@foobar.com'],
['test@example..com'],
['email.email@email."'],
['test@email>'],
['test@email<'],
['test@email{'],
];
}
/**
* @dataProvider getInvalidEmailsWithErrors
*/
public function testInvalidEmailsWithErrorsCheck($error, $email)
{
$this->assertFalse($this->validator->isValid($email, $this->lexer));
$this->assertEquals($error, $this->validator->getError());
}
public function getInvalidEmailsWithErrors()
{
return [
[new NoLocalPart(), '@example.co.uk'],
[new NoDomainPart(), 'example@'],
[new DomainHyphened(), 'example@example-.co.uk'],
[new DomainHyphened(), 'example@example-'],
[new ConsecutiveAt(), 'example@@example.co.uk'],
[new ConsecutiveDot(), 'example..example@example.co.uk'],
[new ConsecutiveDot(), 'example@example..co.uk'],
[new ExpectingATEXT(), '@example.fr'],
[new DotAtStart(), '.example@localhost'],
[new DotAtStart(), 'example@.localhost'],
[new DotAtEnd(), 'example@localhost.'],
[new DotAtEnd(), 'example.@example.co.uk'],
[new UnclosedComment(), '(example@localhost'],
[new UnclosedQuotedString(), '"example@localhost'],
[new ExpectingATEXT(), 'exa"mple@localhost'],
[new UnclosedComment(), '(example@localhost'],
[new UnopenedComment(), 'comment)example@localhost'],
[new UnopenedComment(), 'example(comment))@localhost'],
[new UnopenedComment(), 'example@comment)localhost'],
[new UnopenedComment(), 'example@localhost(comment))'],
[new UnopenedComment(), 'example@(comment))example.com'],
//This was the original. But atext is not allowed after \n
//array(EmailValidator::ERR_EXPECTING_ATEXT, "exampl\ne@example.co.uk"),
[new AtextAfterCFWS(), "exampl\ne@example.co.uk"],
[new ExpectingDTEXT(), "example@[[]"],
[new AtextAfterCFWS(), "exampl\te@example.co.uk"],
[new CRNoLF(), "example@exa\rmple.co.uk"],
[new CRNoLF(), "example@[\r]"],
[new CRNoLF(), "exam\rple@example.co.uk"],
];
}
/**
* @dataProvider getInvalidEmailsWithWarnings
*/
public function testInvalidEmailsWithWarningsCheck($expectedWarnings, $email)
{
$this->assertTrue($this->validator->isValid($email, $this->lexer));
$warnings = $this->validator->getWarnings();
$this->assertTrue(
count($warnings) === count($expectedWarnings),
"Expected: " . implode(",", $expectedWarnings) . " and got " . implode(",", $warnings)
);
foreach ($warnings as $warning) {
$this->assertTrue(isset($expectedWarnings[$warning->code()]));
}
}
public function getInvalidEmailsWithWarnings()
{
return [
[[CFWSNearAt::CODE], 'example @invalid.example.com'],
[[CFWSNearAt::CODE], 'example@ invalid.example.com'],
[[Comment::CODE], 'example@invalid.example(examplecomment).com'],
[[Comment::CODE,CFWSNearAt::CODE], 'example(examplecomment)@invalid.example.com'],
[[QuotedString::CODE, CFWSWithFWS::CODE,], "\"\t\"@invalid.example.com"],
[[QuotedString::CODE, CFWSWithFWS::CODE,], "\"\r\"@invalid.example.com"],
[[AddressLiteral::CODE,], 'example@[127.0.0.1]'],
[[AddressLiteral::CODE,], 'example@[IPv6:2001:0db8:85a3:0000:0000:8a2e:0370:7334]'],
[[AddressLiteral::CODE, IPV6Deprecated::CODE], 'example@[IPv6:2001:0db8:85a3:0000:0000:8a2e:0370::]'],
[[AddressLiteral::CODE, IPV6MaxGroups::CODE,], 'example@[IPv6:2001:0db8:85a3:0000:0000:8a2e:0370:7334::]'],
[[AddressLiteral::CODE, IPV6DoubleColon::CODE,], 'example@[IPv6:1::1::1]'],
[[ObsoleteDTEXT::CODE, DomainLiteral::CODE,], "example@[\n]"],
[[DomainLiteral::CODE,], 'example@[::1]'],
[[DomainLiteral::CODE,], 'example@[::123.45.67.178]'],
[
[IPV6ColonStart::CODE, AddressLiteral::CODE, IPV6GroupCount::CODE,],
'example@[IPv6::2001:0db8:85a3:0000:0000:8a2e:0370:7334]'
],
[
[AddressLiteral::CODE, IPV6BadChar::CODE,],
'example@[IPv6:z001:0db8:85a3:0000:0000:8a2e:0370:7334]'
],
[
[AddressLiteral::CODE, IPV6ColonEnd::CODE,],
'example@[IPv6:2001:0db8:85a3:0000:0000:8a2e:0370:]'
],
[[QuotedString::CODE,], '"example"@invalid.example.com'],
[
[LocalTooLong::CODE,],
'too_long_localpart_too_long_localpart_too_long_localpart_too_long_localpart@invalid.example.com'
],
[
[LabelTooLong::CODE,],
'example@toolonglocalparttoolonglocalparttoolonglocalparttoolonglocalpart.co.uk'
],
[
[DomainTooLong::CODE, LabelTooLong::CODE,],
'example2@toolonglocalparttoolonglocalparttoolonglocalparttoolonglocalparttoolonglocalparttoolonglocal'.
'parttoolonglocalparttoolonglocalparttoolonglocalparttoolonglocalparttoolonglocalparttoolonglocalpart'.
'toolonglocalparttoolonglocalparttoolonglocalparttoolonglocalpart'
],
[
[DomainTooLong::CODE, LabelTooLong::CODE,],
'example@toolonglocalparttoolonglocalparttoolonglocalparttoolonglocalparttoolonglocalparttoolonglocal'.
'parttoolonglocalparttoolonglocalparttoolonglocalparttoolonglocalparttoolonglocalparttoolonglocalpart'.
'toolonglocalparttoolonglocalparttoolonglocalparttoolonglocalpar'
],
];
}
}
Tests/EmailValidator/Validation/SpoofCheckValidationTest.php 0000666 00000002472 13436750351 0020265 0 ustar 00 markTestSkipped("Skipped for Travis CI since it is failing on this test for unknown reasons.");
$validation = new SpoofCheckValidation();
$this->assertTrue($validation->isValid($email, new EmailLexer()));
}
public function testEmailWithSpoofsIsInvalid()
{
$validation = new SpoofCheckValidation();
$this->assertFalse($validation->isValid("Кириллица"."latin漢字"."ひらがな"."カタカナ", new EmailLexer()));
}
public function validUTF8EmailsProvider()
{
return [
// Cyrillic
['Кириллица@Кириллица'],
// Latin + Han + Hiragana + Katakana
["latin漢字"."ひらがな"."カタカナ"."@example.com"],
// Latin + Han + Hangul
["latin"."漢字"."조선말"."@example.com"],
// Latin + Han + Bopomofo
["latin"."漢字"."ㄅㄆㄇㄈ"."@example.com"]
];
}
}
Tests/EmailValidator/Validation/MultipleValidationWitAndTest.php 0000666 00000007556 13436750351 0021153 0 ustar 00 getMock("Egulias\\EmailValidator\\EmailLexer");
$validationTrue = $this->getMock("Egulias\\EmailValidator\\Validation\\EmailValidation");
$validationTrue->expects($this->any())->method("isValid")->willReturn(true);
$validationTrue->expects($this->any())->method("getWarnings")->willReturn([]);
$validationFalse = $this->getMock("Egulias\\EmailValidator\\Validation\\EmailValidation");
$validationFalse->expects($this->any())->method("isValid")->willReturn(false);
$validationFalse->expects($this->any())->method("getWarnings")->willReturn([]);
$multipleValidation = new MultipleValidationWithAnd([$validationTrue, $validationFalse]);
$this->assertFalse($multipleValidation->isValid("exmpale@example.com", $lexer));
}
/**
* @expectedException Egulias\EmailValidator\Validation\Exception\EmptyValidationList
*/
public function testEmptyListIsNotAllowed()
{
new MultipleValidationWithAnd([]);
}
public function testAccumulatesWarnings()
{
$warnings1 = [
AddressLiteral::CODE => new AddressLiteral()
];
$warnings2 = [
DomainLiteral::CODE => new DomainLiteral()
];
$expectedResult = array_merge($warnings1, $warnings2);
$lexer = $this->getMock("Egulias\\EmailValidator\\EmailLexer");
$validation1 = $this->getMock("Egulias\\EmailValidator\\Validation\\EmailValidation");
$validation1->expects($this->any())->method("isValid")->willReturn(true);
$validation1->expects($this->once())->method("getWarnings")->willReturn($warnings1);
$validation2 = $this->getMock("Egulias\\EmailValidator\\Validation\\EmailValidation");
$validation2->expects($this->any())->method("isValid")->willReturn(false);
$validation2->expects($this->once())->method("getWarnings")->willReturn($warnings2);
$multipleValidation = new MultipleValidationWithAnd([$validation1, $validation2]);
$multipleValidation->isValid("example@example.com", $lexer);
$this->assertEquals($expectedResult, $multipleValidation->getWarnings());
}
public function testGathersAllTheErrors()
{
$error1 = new CommaInDomain();
$error2 = new NoDomainPart();
$expectedResult = new MultipleErrors([$error1, $error2]);
$lexer = $this->getMock("Egulias\\EmailValidator\\EmailLexer");
$validation1 = $this->getMock("Egulias\\EmailValidator\\Validation\\EmailValidation");
$validation1->expects($this->any())->method("isValid")->willReturn(true);
$validation1->expects($this->once())->method("getWarnings")->willReturn([]);
$validation1->expects($this->once())->method("getError")->willReturn($error1);
$validation2 = $this->getMock("Egulias\\EmailValidator\\Validation\\EmailValidation");
$validation2->expects($this->any())->method("isValid")->willReturn(false);
$validation2->expects($this->once())->method("getWarnings")->willReturn([]);
$validation2->expects($this->once())->method("getError")->willReturn($error2);
$multipleValidation = new MultipleValidationWithAnd([$validation1, $validation2]);
$multipleValidation->isValid("example@example.com", $lexer);
$this->assertEquals($expectedResult, $multipleValidation->getError());
}
}
Tests/EmailValidator/Validation/IsEmailFunctionTests.php 0000666 00000002426 13436750351 0017441 0 ustar 00 assertFalse($validator->isValid($email, $validations), "Tested email " . $email);
}
public function isEmailTestSuite()
{
$testSuite = dirname(__FILE__) . '/../../resources/is_email_tests.xml';
$document = new \DOMDocument();
$document->load($testSuite);
$elements = $document->getElementsByTagName('test');
$tests = [];
foreach($elements as $testElement) {
$childNode = $testElement->childNodes;
$tests[][] = ($childNode->item(1)->getAttribute('value'));
}
return $tests;
}
}
Tests/EmailValidator/Validation/NoWarningsRFCValidationTest.php 0000666 00000001237 13436750351 0020657 0 ustar 00 assertFalse($validation->isValid('examp"l"e@example.com', new EmailLexer()));
}
public function testEmailWithoutWarningsIsValid()
{
$validation = new NoRFCWarningsValidation();
$this->assertTrue($validation->isValid('example@example.com', new EmailLexer()));
}
}
Tests/EmailValidator/Validation/DNSCheckValidationTest.php 0000666 00000002473 13436750351 0017624 0 ustar 00 assertTrue($validation->isValid("example@example.com", new EmailLexer()));
}
public function testInvalidDNS()
{
$validation = new DNSCheckValidation();
$this->assertFalse($validation->isValid("example@invalid.example.com", new EmailLexer()));
}
public function testDNSWarnings()
{
$validation = new DNSCheckValidation();
$expectedWarnings = [NoDNSMXRecord::CODE => new NoDNSMXRecord()];
$validation->isValid("example@invalid.example.com", new EmailLexer());
$this->assertEquals($expectedWarnings, $validation->getWarnings());
}
public function testNoDNSError()
{
$validation = new DNSCheckValidation();
$expectedError = new NoDNSRecord();
$validation->isValid("example@invalid.example.com", new EmailLexer());
$this->assertEquals($expectedError, $validation->getError());
}
}
Tests/EmailValidator/EmailLexerTest.php 0000666 00000012057 13436750351 0014163 0 ustar 00 assertInstanceOf('Doctrine\Common\Lexer\AbstractLexer', $lexer);
}
/**
* @dataProvider getTokens
*
*/
public function testLexerTokens($str, $token)
{
$lexer = new EmailLexer();
$lexer->setInput($str);
$lexer->moveNext();
$lexer->moveNext();
$this->assertEquals($token, $lexer->token['type']);
}
public function testLexerParsesMultipleSpaces()
{
$lexer = new EmailLexer();
$lexer->setInput(' ');
$lexer->moveNext();
$lexer->moveNext();
$this->assertEquals(EmailLexer::S_SP, $lexer->token['type']);
$lexer->moveNext();
$this->assertEquals(EmailLexer::S_SP, $lexer->token['type']);
}
/**
* @dataProvider invalidUTF8CharsProvider
*/
public function testLexerParsesInvalidUTF8($char)
{
$lexer = new EmailLexer();
$lexer->setInput($char);
$lexer->moveNext();
$lexer->moveNext();
$this->assertEquals(EmailLexer::INVALID, $lexer->token['type']);
}
public function invalidUTF8CharsProvider()
{
$chars = array();
for ($i = 0; $i < 0x100; ++$i) {
$c = $this->utf8Chr($i);
if (preg_match('/(?=\p{Cc})(?=[^\t\n\n\r])/u', $c) && !preg_match('/\x{0000}/u', $c)) {
$chars[] = array($c);
}
}
return $chars;
}
protected function utf8Chr($code_point)
{
if ($code_point < 0 || 0x10FFFF < $code_point || (0xD800 <= $code_point && $code_point <= 0xDFFF)) {
return '';
}
if ($code_point < 0x80) {
$hex[0] = $code_point;
$ret = chr($hex[0]);
} elseif ($code_point < 0x800) {
$hex[0] = 0x1C0 | $code_point >> 6;
$hex[1] = 0x80 | $code_point & 0x3F;
$ret = chr($hex[0]).chr($hex[1]);
} elseif ($code_point < 0x10000) {
$hex[0] = 0xE0 | $code_point >> 12;
$hex[1] = 0x80 | $code_point >> 6 & 0x3F;
$hex[2] = 0x80 | $code_point & 0x3F;
$ret = chr($hex[0]).chr($hex[1]).chr($hex[2]);
} else {
$hex[0] = 0xF0 | $code_point >> 18;
$hex[1] = 0x80 | $code_point >> 12 & 0x3F;
$hex[2] = 0x80 | $code_point >> 6 & 0x3F;
$hex[3] = 0x80 | $code_point & 0x3F;
$ret = chr($hex[0]).chr($hex[1]).chr($hex[2]).chr($hex[3]);
}
return $ret;
}
public function testLexerForTab()
{
$lexer = new EmailLexer();
$lexer->setInput("foo\tbar");
$lexer->moveNext();
$lexer->skipUntil(EmailLexer::S_HTAB);
$lexer->moveNext();
$this->assertEquals(EmailLexer::S_HTAB, $lexer->token['type']);
}
public function testLexerForUTF8()
{
$lexer = new EmailLexer();
$lexer->setInput("áÇ@bar.com");
$lexer->moveNext();
$lexer->moveNext();
$this->assertEquals(EmailLexer::GENERIC, $lexer->token['type']);
$lexer->moveNext();
$this->assertEquals(EmailLexer::GENERIC, $lexer->token['type']);
}
public function testLexerSearchToken()
{
$lexer = new EmailLexer();
$lexer->setInput("foo\tbar");
$lexer->moveNext();
$this->assertTrue($lexer->find(EmailLexer::S_HTAB));
}
public function getTokens()
{
return array(
array("foo", EmailLexer::GENERIC),
array("\r", EmailLexer::S_CR),
array("\t", EmailLexer::S_HTAB),
array("\r\n", EmailLexer::CRLF),
array("\n", EmailLexer::S_LF),
array(" ", EmailLexer::S_SP),
array("@", EmailLexer::S_AT),
array("IPv6", EmailLexer::S_IPV6TAG),
array("::", EmailLexer::S_DOUBLECOLON),
array(":", EmailLexer::S_COLON),
array(".", EmailLexer::S_DOT),
array("\"", EmailLexer::S_DQUOTE),
array("-", EmailLexer::S_HYPHEN),
array("\\", EmailLexer::S_BACKSLASH),
array("/", EmailLexer::S_SLASH),
array("(", EmailLexer::S_OPENPARENTHESIS),
array(")", EmailLexer::S_CLOSEPARENTHESIS),
array('<', EmailLexer::S_LOWERTHAN),
array('>', EmailLexer::S_GREATERTHAN),
array('[', EmailLexer::S_OPENBRACKET),
array(']', EmailLexer::S_CLOSEBRACKET),
array(';', EmailLexer::S_SEMICOLON),
array(',', EmailLexer::S_COMMA),
array('<', EmailLexer::S_LOWERTHAN),
array('>', EmailLexer::S_GREATERTHAN),
array('{', EmailLexer::S_OPENQBRACKET),
array('}', EmailLexer::S_CLOSEQBRACKET),
array('', EmailLexer::S_EMPTY),
array(chr(31), EmailLexer::INVALID),
array(chr(226), EmailLexer::GENERIC),
array(chr(0), EmailLexer::C_NUL)
);
}
}
Tests/EmailValidator/EmailValidatorTest.php 0000666 00000002501 13436750351 0015022 0 ustar 00 getMock("Egulias\\EmailValidator\\Validation\\EmailValidation");
$validation->expects($this->once())->method("isValid")->willReturn(true);
$validation->expects($this->once())->method("getWarnings")->willReturn([]);
$validation->expects($this->once())->method("getError")->willReturn(null);
$this->assertTrue($validator->isValid("example@example.com", $validation));
}
public function testMultipleValidation()
{
$validator = new EmailValidator();
$validation = $this->getMock("Egulias\\EmailValidator\\Validation\\EmailValidation");
$validation->expects($this->once())->method("isValid")->willReturn(true);
$validation->expects($this->once())->method("getWarnings")->willReturn([]);
$validation->expects($this->once())->method("getError")->willReturn(null);
$multiple = new MultipleValidationWithAnd([$validation]);
$this->assertTrue($validator->isValid("example@example.com", $multiple));
}
}
Tests/Performance/AgainstOldIsemail.php 0000666 00000001777 13436750351 0014200 0 ustar 00 isValid($testingMail, new \Egulias\EmailValidator\Validation\RFCValidation());
}
$b = microtime(true);
echo ($b - $a) . ' seconds with EmailValidator + instantiation' . PHP_EOL;
$a = microtime(true);
$validator = new EmailValidator();
for ($i = 0; $i < $iterations; $i++) {
$isValid = $validator->isValid($testingMail, new \Egulias\EmailValidator\Validation\RFCValidation());
}
$b = microtime(true);
echo ($b - $a) . ' seconds with EmailValidator once instanced' . PHP_EOL;
Tests/Performance/AgainstFilterVar.php 0000666 00000002032 13436750351 0014035 0 ustar 00 isValid($testingMail, new \Egulias\EmailValidator\Validation\RFCValidation());
}
$b = microtime(true);
echo ($b - $a) . ' seconds with EmailValidator + instantiation' . PHP_EOL;
$a = microtime(true);
$validator = new EmailValidator();
for ($i = 0; $i < $iterations; $i++) {
$isValid = $validator->isValid($testingMail, new \Egulias\EmailValidator\Validation\RFCValidation());
}
$b = microtime(true);
echo ($b - $a) . ' seconds with EmailValidator once instanced' . PHP_EOL;
.gitignore 0000666 00000000020 13436750351 0006537 0 ustar 00 report/
vendor/