Skip to content

Commit

Permalink
Merge branch 'master' into master
Browse files Browse the repository at this point in the history
  • Loading branch information
chriso authored May 3, 2018
2 parents 8944b70 + 92ed4d0 commit 9e1f629
Show file tree
Hide file tree
Showing 16 changed files with 213 additions and 9 deletions.
9 changes: 9 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,12 @@
#### HEAD

- Added an `isRFC3339()` validator
([#816](https://github.com/chriso/validator.js/pull/816))
- Disallow GMail addresses with multiple consecutive dots
([#820](https://github.com/chriso/validator.js/pull/820))
- New locales
([#803](https://github.com/chriso/validator.js/pull/803))

#### 9.4.1

- Patched a [REDOS](https://en.wikipedia.org/wiki/ReDoS) vulnerability in `isDataURI`
Expand Down
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,7 @@ Validator | Description
**isISSN(str [, options])** | check if the string is an [ISSN](https://en.wikipedia.org/wiki/International_Standard_Serial_Number).<br/><br/>`options` is an object which defaults to `{ case_sensitive: false, require_hyphen: false }`. If `case_sensitive` is true, ISSNs with a lowercase `'x'` as the check digit are rejected.
**isISIN(str)** | check if the string is an [ISIN][ISIN] (stock/security identifier).
**isISO8601(str)** | check if the string is a valid [ISO 8601](https://en.wikipedia.org/wiki/ISO_8601) date.
**isRFC3339(str)** | check if the string is a valid [RFC 3339](https://tools.ietf.org/html/rfc3339) date.
**isISO31661Alpha2(str)** | check if the string is a valid [ISO 3166-1 alpha-2](https://en.wikipedia.org/wiki/ISO_3166-1_alpha-2) officially assigned country code.
**isISRC(str)** | check if the string is a [ISRC](https://en.wikipedia.org/wiki/International_Standard_Recording_Code).
**isIn(str, values)** | check if the string is in a array of allowed values.
Expand Down
5 changes: 5 additions & 0 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -204,6 +204,10 @@ var _isISO = require('./lib/isISO8601');

var _isISO2 = _interopRequireDefault(_isISO);

var _isRFC = require('./lib/isRFC3339');

var _isRFC2 = _interopRequireDefault(_isRFC);

var _isISO31661Alpha = require('./lib/isISO31661Alpha2');

var _isISO31661Alpha2 = _interopRequireDefault(_isISO31661Alpha);
Expand Down Expand Up @@ -329,6 +333,7 @@ var validator = {
isPostalCode: _isPostalCode2.default,
isCurrency: _isCurrency2.default,
isISO8601: _isISO2.default,
isRFC3339: _isRFC2.default,
isISO31661Alpha2: _isISO31661Alpha2.default,
isBase64: _isBase2.default,
isDataURI: _isDataURI2.default,
Expand Down
10 changes: 9 additions & 1 deletion lib/isEmail.js
Original file line number Diff line number Diff line change
Expand Up @@ -58,8 +58,16 @@ function isEmail(str, options) {
var user = parts.join('@');

var lower_domain = domain.toLowerCase();

if (lower_domain === 'gmail.com' || lower_domain === 'googlemail.com') {
user = user.replace(/\./g, '').toLowerCase();
/*
Previously we removed dots for gmail addresses before validating.
This was removed because it allows `multiple..dots@gmail.com`
to be reported as valid, but it is not.
Gmail only normalizes single dots, removing them from here is pointless,
should be done in normalizeEmail
*/
user = user.toLowerCase();
}

if (!(0, _isByteLength2.default)(user, { max: 64 }) || !(0, _isByteLength2.default)(domain, { max: 254 })) {
Expand Down
1 change: 1 addition & 0 deletions lib/isPostalCode.js
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ var patterns = {
RU: sixDigit,
SA: fiveDigit,
SE: /^\d{3}\s?\d{2}$/,
SK: /^\d{3}\s?\d{2}$/,
TW: /^\d{3}(\d{2})?$/,
US: /^\d{5}(-\d{4})?$/,
ZA: fourDigit,
Expand Down
39 changes: 39 additions & 0 deletions lib/isRFC3339.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
'use strict';

Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = isRFC3339;

var _assertString = require('./util/assertString');

var _assertString2 = _interopRequireDefault(_assertString);

function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }

/* Based on https://tools.ietf.org/html/rfc3339#section-5.6 */

var dateFullYear = /[0-9]{4}/;
var dateMonth = /(0[1-9]|1[0-2])/;
var dateMDay = /([12]\d|0[1-9]|3[01])/;

var timeHour = /([01][0-9]|2[0-3])/;
var timeMinute = /[0-5][0-9]/;
var timeSecond = /([0-5][0-9]|60)/;

var timeSecFrac = /(\.[0-9]+)?/;
var timeNumOffset = new RegExp('[-+]' + timeHour.source + ':' + timeMinute.source);
var timeOffset = new RegExp('([zZ]|' + timeNumOffset.source + ')');

var partialTime = new RegExp(timeHour.source + ':' + timeMinute.source + ':' + timeSecond.source + timeSecFrac.source);

var fullDate = new RegExp(dateFullYear.source + '-' + dateMonth.source + '-' + dateMDay.source);
var fullTime = new RegExp('' + partialTime.source + timeOffset.source);

var rfc3339 = new RegExp(fullDate.source + '[ tT]' + fullTime.source);

function isRFC3339(str) {
(0, _assertString2.default)(str);
return rfc3339.test(str);
}
module.exports = exports['default'];
11 changes: 10 additions & 1 deletion lib/normalizeEmail.js
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,14 @@ var outlookdotcom_domains = ['hotmail.at', 'hotmail.be', 'hotmail.ca', 'hotmail.
// This list is likely incomplete
var yahoo_domains = ['rocketmail.com', 'yahoo.ca', 'yahoo.co.uk', 'yahoo.com', 'yahoo.de', 'yahoo.fr', 'yahoo.in', 'yahoo.it', 'ymail.com'];

// replace single dots, but not multiple consecutive dots
function dotsReplacer(match) {
if (match.length > 1) {
return match;
}
return '';
}

function normalizeEmail(email, options) {
options = (0, _merge2.default)(options, default_normalize_email_options);

Expand All @@ -77,7 +85,8 @@ function normalizeEmail(email, options) {
parts[0] = parts[0].split('+')[0];
}
if (options.gmail_remove_dots) {
parts[0] = parts[0].replace(/\./g, '');
// this does not replace consecutive dots like example..email@gmail.com
parts[0] = parts[0].replace(/\.+/g, dotsReplacer);
}
if (!parts[0].length) {
return false;
Expand Down
2 changes: 2 additions & 0 deletions src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@ import isMobilePhone from './lib/isMobilePhone';
import isCurrency from './lib/isCurrency';

import isISO8601 from './lib/isISO8601';
import isRFC3339 from './lib/isRFC3339';
import isISO31661Alpha2 from './lib/isISO31661Alpha2';

import isBase64 from './lib/isBase64';
Expand Down Expand Up @@ -144,6 +145,7 @@ const validator = {
isPostalCode,
isCurrency,
isISO8601,
isRFC3339,
isISO31661Alpha2,
isBase64,
isDataURI,
Expand Down
10 changes: 9 additions & 1 deletion src/lib/isEmail.js
Original file line number Diff line number Diff line change
Expand Up @@ -39,8 +39,16 @@ export default function isEmail(str, options) {
let user = parts.join('@');

const lower_domain = domain.toLowerCase();

if (lower_domain === 'gmail.com' || lower_domain === 'googlemail.com') {
user = user.replace(/\./g, '').toLowerCase();
/*
Previously we removed dots for gmail addresses before validating.
This was removed because it allows `multiple..dots@gmail.com`
to be reported as valid, but it is not.
Gmail only normalizes single dots, removing them from here is pointless,
should be done in normalizeEmail
*/
user = user.toLowerCase();
}

if (!isByteLength(user, { max: 64 }) ||
Expand Down
1 change: 1 addition & 0 deletions src/lib/isPostalCode.js
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ const patterns = {
RU: sixDigit,
SA: fiveDigit,
SE: /^\d{3}\s?\d{2}$/,
SK: /^\d{3}\s?\d{2}$/,
TW: /^\d{3}(\d{2})?$/,
US: /^\d{5}(-\d{4})?$/,
ZA: fourDigit,
Expand Down
27 changes: 27 additions & 0 deletions src/lib/isRFC3339.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import assertString from './util/assertString';

/* Based on https://tools.ietf.org/html/rfc3339#section-5.6 */

const dateFullYear = /[0-9]{4}/;
const dateMonth = /(0[1-9]|1[0-2])/;
const dateMDay = /([12]\d|0[1-9]|3[01])/;

const timeHour = /([01][0-9]|2[0-3])/;
const timeMinute = /[0-5][0-9]/;
const timeSecond = /([0-5][0-9]|60)/;

const timeSecFrac = /(\.[0-9]+)?/;
const timeNumOffset = new RegExp(`[-+]${timeHour.source}:${timeMinute.source}`);
const timeOffset = new RegExp(`([zZ]|${timeNumOffset.source})`);

const partialTime = new RegExp(`${timeHour.source}:${timeMinute.source}:${timeSecond.source}${timeSecFrac.source}`);

const fullDate = new RegExp(`${dateFullYear.source}-${dateMonth.source}-${dateMDay.source}`);
const fullTime = new RegExp(`${partialTime.source}${timeOffset.source}`);

const rfc3339 = new RegExp(`${fullDate.source}[ tT]${fullTime.source}`);

export default function isRFC3339(str) {
assertString(str);
return rfc3339.test(str);
}
11 changes: 10 additions & 1 deletion src/lib/normalizeEmail.js
Original file line number Diff line number Diff line change
Expand Up @@ -145,6 +145,14 @@ const yahoo_domains = [
'ymail.com',
];

// replace single dots, but not multiple consecutive dots
function dotsReplacer(match) {
if (match.length > 1) {
return match;
}
return '';
}

export default function normalizeEmail(email, options) {
options = merge(options, default_normalize_email_options);

Expand All @@ -162,7 +170,8 @@ export default function normalizeEmail(email, options) {
parts[0] = parts[0].split('+')[0];
}
if (options.gmail_remove_dots) {
parts[0] = parts[0].replace(/\./g, '');
// this does not replace consecutive dots like example..email@gmail.com
parts[0] = parts[0].replace(/\.+/g, dotsReplacer);
}
if (!parts[0].length) {
return false;
Expand Down
4 changes: 3 additions & 1 deletion test/sanitizers.js
Original file line number Diff line number Diff line change
Expand Up @@ -235,7 +235,8 @@ describe('Sanitizers', function () {
'some.name.midd.leNa.me.+extension@GoogleMail.com': 'somenamemiddlename@gmail.com',
'some.name+extension@unknown.com': 'some.name+extension@unknown.com',
'hans@m端ller.com': 'hans@m端ller.com',
'some.name.midd..leNa...me...+extension@GoogleMail.com': 'somenamemiddlename@gmail.com',
'some.name.midd..leNa...me...+extension@GoogleMail.com': 'somenamemidd..lena...me...@gmail.com',
'matthew..example@gmail.com': 'matthew..example@gmail.com',
'"foo@bar"@baz.com': '"foo@bar"@baz.com',
},
});
Expand Down Expand Up @@ -326,6 +327,7 @@ describe('Sanitizers', function () {
expect: {
'SOME.name@GMAIL.com': 'somename@gmail.com',
'SOME.name+me@GMAIL.com': 'somename@gmail.com',
'some.name..multiple@gmail.com': 'somename..multiple@gmail.com',
'my.self@foo.com': 'my.self@foo.com',
},
});
Expand Down
40 changes: 39 additions & 1 deletion test/validators.js
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,6 @@ describe('Validators', function () {
'test|123@m端ller.com',
'test+ext@gmail.com',
'some.name.midd.leNa.me.+extension@GoogleMail.com',
'gmail...ignores...dots...@gmail.com',
'"foobar"@example.com',
'" foo m端ller "@example.com',
'"foo\\@bar"@example.com',
Expand Down Expand Up @@ -84,6 +83,9 @@ describe('Validators', function () {
'test11@invalid.co m',
'test12@invalid.co m',
'test13@invalid.co m',
'gmail...ignores...dots...@gmail.com',
'multiple..dots@gmail.com',
'multiple..dots@stillinvalid.com',
],
});
});
Expand Down Expand Up @@ -162,6 +164,7 @@ describe('Validators', function () {
'Some Name <foo@bar.co.uk.',
'Some Name < foo@bar.co.uk >',
'Name foo@bar.co.uk',
'Some Name <some..name@gmail.com>',
],
});
});
Expand Down Expand Up @@ -5075,6 +5078,41 @@ describe('Validators', function () {
});
});

it('should validate RFC 3339 dates', function () {
test({
validator: 'isRFC3339',
valid: [
'2009-05-19 14:39:22-06:00',
'2009-05-19 14:39:22+06:00',
'2009-05-19 14:39:22Z',
'2009-05-19T14:39:22-06:00',
'2009-05-19T14:39:22Z',
'2010-02-18T16:23:48.3-06:00',
'2010-02-18t16:23:33+06:00',
'2010-02-18t16:23:33+06:00',
'2010-02-18t16:12:23.23334444z',
'2010-02-18T16:23:55.2283Z',
'2009-05-19 14:39:22.500Z',
'2009-05-19 14:39:55Z',
'2009-05-31 14:39:55Z',
'2009-05-31 14:53:60Z',
'2010-02-18t00:23:23.33+06:00',
'2010-02-18t00:23:32.33+00:00',
'2010-02-18t00:23:32.33+23:00',
],
invalid: [
'2010-02-18t00:23:32.33+24:00',
'2009-05-31 14:60:55Z',
'2010-02-18t24:23.33+0600',
'2009-05-00 1439,55Z',
'2009-13-19 14:39:22-06:00',
'2009-05-00 14:39:22+0600',
'2009-00-1 14:39:22Z',
'2009-05-19T14:39:22',
],
});
});

it('should validate ISO 3166-1 alpha 2 country codes', function () {
// from https://en.wikipedia.org/wiki/ISO_3166-1_alpha-2
test({
Expand Down
Loading

0 comments on commit 9e1f629

Please sign in to comment.