From ae8731544d2190aae954b2dd14c1f476ffcd7992 Mon Sep 17 00:00:00 2001 From: mirabilos Date: Mon, 6 Jun 2016 14:52:40 +0200 Subject: [PATCH 1/7] Fix eMail address local-part validation MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit A period (‘.’) may not begin or end a local-part cf. http://www.mirbsd.org/cvs.cgi/contrib/hosted/tg/mailfrom.php?rev=HEAD and RFC 822 / 5321 --- src/ng/directive/input.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ng/directive/input.js b/src/ng/directive/input.js index 408160521271..32f90d34a9a3 100644 --- a/src/ng/directive/input.js +++ b/src/ng/directive/input.js @@ -24,7 +24,7 @@ var ISO_DATE_REGEXP = /^\d{4,}-[01]\d-[0-3]\dT[0-2]\d:[0-5]\d:[0-5]\d\.\d+(?:[+- // 9. Fragment // 1111111111111111 222 333333 44444 555555555555555555555555 666 77777777 8888888 999 var URL_REGEXP = /^[a-z][a-z\d.+-]*:\/*(?:[^:@]+(?::[^@]+)?@)?(?:[^\s:/?#]+|\[[a-f\d:]+\])(?::\d+)?(?:\/[^?#]*)?(?:\?[^#]*)?(?:#.*)?$/i; -var EMAIL_REGEXP = /^[a-z0-9!#$%&'*+\/=?^_`{|}~.-]+@[a-z0-9]([a-z0-9-]*[a-z0-9])?(\.[a-z0-9]([a-z0-9-]*[a-z0-9])?)*$/i; +var EMAIL_REGEXP = /^[-!#-'*+\/-9=?A-Z^-~]+(\.[-!#-'*+\/-9=?A-Z^-~]+)*@[a-z0-9]([a-z0-9-]*[a-z0-9])?(\.[a-z0-9]([a-z0-9-]*[a-z0-9])?)*$/i; var NUMBER_REGEXP = /^\s*(\-|\+)?(\d+|(\d*(\.\d*)))([eE][+-]?\d+)?\s*$/; var DATE_REGEXP = /^(\d{4,})-(\d{2})-(\d{2})$/; var DATETIMELOCAL_REGEXP = /^(\d{4,})-(\d\d)-(\d\d)T(\d\d):(\d\d)(?::(\d\d)(\.\d{1,3})?)?$/; From baf0fa707801d98a085dbf54deb14b1bc9144b62 Mon Sep 17 00:00:00 2001 From: mirabilos Date: Mon, 6 Jun 2016 14:53:08 +0200 Subject: [PATCH 2/7] Limit eMail address individual host part length MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit A “label” (each of the things between the dots (‘.’) after the ‘@’ in the eMail address) MUST NOT be longer than 63 characters. cf. http://www.mirbsd.org/cvs.cgi/contrib/hosted/tg/mailfrom.php?rev=HEAD and RFC 1035 §2.3.4 --- src/ng/directive/input.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ng/directive/input.js b/src/ng/directive/input.js index 32f90d34a9a3..f40de82cb932 100644 --- a/src/ng/directive/input.js +++ b/src/ng/directive/input.js @@ -24,7 +24,7 @@ var ISO_DATE_REGEXP = /^\d{4,}-[01]\d-[0-3]\dT[0-2]\d:[0-5]\d:[0-5]\d\.\d+(?:[+- // 9. Fragment // 1111111111111111 222 333333 44444 555555555555555555555555 666 77777777 8888888 999 var URL_REGEXP = /^[a-z][a-z\d.+-]*:\/*(?:[^:@]+(?::[^@]+)?@)?(?:[^\s:/?#]+|\[[a-f\d:]+\])(?::\d+)?(?:\/[^?#]*)?(?:\?[^#]*)?(?:#.*)?$/i; -var EMAIL_REGEXP = /^[-!#-'*+\/-9=?A-Z^-~]+(\.[-!#-'*+\/-9=?A-Z^-~]+)*@[a-z0-9]([a-z0-9-]*[a-z0-9])?(\.[a-z0-9]([a-z0-9-]*[a-z0-9])?)*$/i; +var EMAIL_REGEXP = /^[-!#-'*+\/-9=?A-Z^-~]+(\.[-!#-'*+\/-9=?A-Z^-~]+)*@[a-z0-9]([a-z0-9-]{0,61}[a-z0-9])?(\.[a-z0-9]([a-z0-9-]{0,61}[a-z0-9])?)*$/i; var NUMBER_REGEXP = /^\s*(\-|\+)?(\d+|(\d*(\.\d*)))([eE][+-]?\d+)?\s*$/; var DATE_REGEXP = /^(\d{4,})-(\d{2})-(\d{2})$/; var DATETIMELOCAL_REGEXP = /^(\d{4,})-(\d\d)-(\d\d)T(\d\d):(\d\d)(?::(\d\d)(\.\d{1,3})?)?$/; From 215a60f2a3e9c75d539287c795c657962401ec1c Mon Sep 17 00:00:00 2001 From: mirabilos Date: Mon, 6 Jun 2016 14:54:33 +0200 Subject: [PATCH 3/7] Limit eMail address total host part length MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit RFC 1035 §2.3.4 imposes a maximum length for any DNS object; RFC 5321 §2.3.5 references this (and requires FQDNs, but there have been cases where a TLD had an MX RR and thus eMail addresses like “localpart@tld” are valid). Credits: Natureshadow --- src/ng/directive/input.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ng/directive/input.js b/src/ng/directive/input.js index f40de82cb932..4036c0178f35 100644 --- a/src/ng/directive/input.js +++ b/src/ng/directive/input.js @@ -24,7 +24,7 @@ var ISO_DATE_REGEXP = /^\d{4,}-[01]\d-[0-3]\dT[0-2]\d:[0-5]\d:[0-5]\d\.\d+(?:[+- // 9. Fragment // 1111111111111111 222 333333 44444 555555555555555555555555 666 77777777 8888888 999 var URL_REGEXP = /^[a-z][a-z\d.+-]*:\/*(?:[^:@]+(?::[^@]+)?@)?(?:[^\s:/?#]+|\[[a-f\d:]+\])(?::\d+)?(?:\/[^?#]*)?(?:\?[^#]*)?(?:#.*)?$/i; -var EMAIL_REGEXP = /^[-!#-'*+\/-9=?A-Z^-~]+(\.[-!#-'*+\/-9=?A-Z^-~]+)*@[a-z0-9]([a-z0-9-]{0,61}[a-z0-9])?(\.[a-z0-9]([a-z0-9-]{0,61}[a-z0-9])?)*$/i; +var EMAIL_REGEXP = /^[-!#-'*+\/-9=?A-Z^-~]+(\.[-!#-'*+\/-9=?A-Z^-~]+)*@(?=.{1,255}$)[a-z0-9]([a-z0-9-]{0,61}[a-z0-9])?(\.[a-z0-9]([a-z0-9-]{0,61}[a-z0-9])?)*$/i; var NUMBER_REGEXP = /^\s*(\-|\+)?(\d+|(\d*(\.\d*)))([eE][+-]?\d+)?\s*$/; var DATE_REGEXP = /^(\d{4,})-(\d{2})-(\d{2})$/; var DATETIMELOCAL_REGEXP = /^(\d{4,})-(\d\d)-(\d\d)T(\d\d):(\d\d)(?::(\d\d)(\.\d{1,3})?)?$/; From 28292fdfd6ea3464f6f275560307ae17510088dc Mon Sep 17 00:00:00 2001 From: mirabilos Date: Mon, 6 Jun 2016 14:58:59 +0200 Subject: [PATCH 4/7] Optimise eMail address regex for speed There is no need to make it case-insensitive; the local-part already catches the entire range, and the host part is easily done. Furthermore, this makes the regex locale-independent, avoiding issues with e.g. turkish case conversions. cf. http://www.mirbsd.org/cvs.cgi/contrib/hosted/tg/mailfrom.php?rev=HEAD --- src/ng/directive/input.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ng/directive/input.js b/src/ng/directive/input.js index 4036c0178f35..2b86163c10a7 100644 --- a/src/ng/directive/input.js +++ b/src/ng/directive/input.js @@ -24,7 +24,7 @@ var ISO_DATE_REGEXP = /^\d{4,}-[01]\d-[0-3]\dT[0-2]\d:[0-5]\d:[0-5]\d\.\d+(?:[+- // 9. Fragment // 1111111111111111 222 333333 44444 555555555555555555555555 666 77777777 8888888 999 var URL_REGEXP = /^[a-z][a-z\d.+-]*:\/*(?:[^:@]+(?::[^@]+)?@)?(?:[^\s:/?#]+|\[[a-f\d:]+\])(?::\d+)?(?:\/[^?#]*)?(?:\?[^#]*)?(?:#.*)?$/i; -var EMAIL_REGEXP = /^[-!#-'*+\/-9=?A-Z^-~]+(\.[-!#-'*+\/-9=?A-Z^-~]+)*@(?=.{1,255}$)[a-z0-9]([a-z0-9-]{0,61}[a-z0-9])?(\.[a-z0-9]([a-z0-9-]{0,61}[a-z0-9])?)*$/i; +var EMAIL_REGEXP = /^[-!#-'*+\/-9=?A-Z^-~]+(\.[-!#-'*+\/-9=?A-Z^-~]+)*@(?=.{1,255}$)[A-Za-z0-9]([A-Za-z0-9-]{0,61}[A-Za-z0-9])?(\.[A-Za-z0-9]([A-Za-z0-9-]{0,61}[A-Za-z0-9])?)*$/; var NUMBER_REGEXP = /^\s*(\-|\+)?(\d+|(\d*(\.\d*)))([eE][+-]?\d+)?\s*$/; var DATE_REGEXP = /^(\d{4,})-(\d{2})-(\d{2})$/; var DATETIMELOCAL_REGEXP = /^(\d{4,})-(\d\d)-(\d\d)T(\d\d):(\d\d)(?::(\d\d)(\.\d{1,3})?)?$/; From f3e01164d87f9c560bb770c22fdfbe80f8d86827 Mon Sep 17 00:00:00 2001 From: mirabilos Date: Mon, 6 Jun 2016 23:13:06 +0200 Subject: [PATCH 5/7] expand ranges in regex character class to improve legibility MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit requested by Georgios Kalpakas in #14719 (let’s hope all the special characters are accepted by JS as-is…) --- src/ng/directive/input.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ng/directive/input.js b/src/ng/directive/input.js index 2b86163c10a7..deb0316e8e30 100644 --- a/src/ng/directive/input.js +++ b/src/ng/directive/input.js @@ -24,7 +24,7 @@ var ISO_DATE_REGEXP = /^\d{4,}-[01]\d-[0-3]\dT[0-2]\d:[0-5]\d:[0-5]\d\.\d+(?:[+- // 9. Fragment // 1111111111111111 222 333333 44444 555555555555555555555555 666 77777777 8888888 999 var URL_REGEXP = /^[a-z][a-z\d.+-]*:\/*(?:[^:@]+(?::[^@]+)?@)?(?:[^\s:/?#]+|\[[a-f\d:]+\])(?::\d+)?(?:\/[^?#]*)?(?:\?[^#]*)?(?:#.*)?$/i; -var EMAIL_REGEXP = /^[-!#-'*+\/-9=?A-Z^-~]+(\.[-!#-'*+\/-9=?A-Z^-~]+)*@(?=.{1,255}$)[A-Za-z0-9]([A-Za-z0-9-]{0,61}[A-Za-z0-9])?(\.[A-Za-z0-9]([A-Za-z0-9-]{0,61}[A-Za-z0-9])?)*$/; +var EMAIL_REGEXP = /^[-!#$%&'*+\/0-9=?A-Z^_`a-z{|}~]+(\.[-!#$%&'*+\/0-9=?A-Z^_`a-z{|}~]+)*@(?=.{1,255}$)[A-Za-z0-9]([A-Za-z0-9-]{0,61}[A-Za-z0-9])?(\.[A-Za-z0-9]([A-Za-z0-9-]{0,61}[A-Za-z0-9])?)*$/; var NUMBER_REGEXP = /^\s*(\-|\+)?(\d+|(\d*(\.\d*)))([eE][+-]?\d+)?\s*$/; var DATE_REGEXP = /^(\d{4,})-(\d{2})-(\d{2})$/; var DATETIMELOCAL_REGEXP = /^(\d{4,})-(\d\d)-(\d\d)T(\d\d):(\d\d)(?::(\d\d)(\.\d{1,3})?)?$/; From 8720cff5ddc513697c2a95dbfd18cadba5ca18e9 Mon Sep 17 00:00:00 2001 From: mirabilos Date: Mon, 6 Jun 2016 23:10:49 +0200 Subject: [PATCH 6/7] Comprehensive eMail addr-spec testsuite --- test/ng/directive/inputSpec.js | 86 ++++++++++++++++++++++++++++++++++ 1 file changed, 86 insertions(+) diff --git a/test/ng/directive/inputSpec.js b/test/ng/directive/inputSpec.js index db53047ec6cc..d3d969470ef8 100644 --- a/test/ng/directive/inputSpec.js +++ b/test/ng/directive/inputSpec.js @@ -2784,14 +2784,100 @@ describe('input', function() { describe('EMAIL_REGEXP', function() { /* global EMAIL_REGEXP: false */ it('should validate email', function() { + /* basic functionality */ expect(EMAIL_REGEXP.test('a@b.com')).toBe(true); expect(EMAIL_REGEXP.test('a@b.museum')).toBe(true); expect(EMAIL_REGEXP.test('a@B.c')).toBe(true); + /* domain label separation, hyphen-minus, syntax */ + expect(EMAIL_REGEXP.test('a@b.c.')).toBe(false); expect(EMAIL_REGEXP.test('a@.b.c')).toBe(false); expect(EMAIL_REGEXP.test('a@-b.c')).toBe(false); expect(EMAIL_REGEXP.test('a@b-.c')).toBe(false); + expect(EMAIL_REGEXP.test('a@b-c')).toBe(true); + expect(EMAIL_REGEXP.test('a@-')).toBe(false); + expect(EMAIL_REGEXP.test('a@.')).toBe(false); + expect(EMAIL_REGEXP.test('a@host_name')).toBe(false); + /* leading or sole digit */ expect(EMAIL_REGEXP.test('a@3b.c')).toBe(true); + expect(EMAIL_REGEXP.test('a@3')).toBe(true); + /* TLD eMail address */ expect(EMAIL_REGEXP.test('a@b')).toBe(true); + /* domain valid characters */ + expect(EMAIL_REGEXP.test('a@abcdefghijklmnopqrstuvwxyz-ABCDEFGHIJKLMNOPQRSTUVWXYZ.0123456789')).toBe(true); + /* domain invalid characters */ + expect(EMAIL_REGEXP.test('a@')).toBe(false); + expect(EMAIL_REGEXP.test('a@ ')).toBe(false); + expect(EMAIL_REGEXP.test('a@!')).toBe(false); + expect(EMAIL_REGEXP.test('a@"')).toBe(false); + expect(EMAIL_REGEXP.test('a@#')).toBe(false); + expect(EMAIL_REGEXP.test('a@$')).toBe(false); + expect(EMAIL_REGEXP.test('a@%')).toBe(false); + expect(EMAIL_REGEXP.test('a@&')).toBe(false); + expect(EMAIL_REGEXP.test("a@'")).toBe(false); + expect(EMAIL_REGEXP.test('a@(')).toBe(false); + expect(EMAIL_REGEXP.test('a@)')).toBe(false); + expect(EMAIL_REGEXP.test('a@*')).toBe(false); + expect(EMAIL_REGEXP.test('a@+')).toBe(false); + expect(EMAIL_REGEXP.test('a@,')).toBe(false); + expect(EMAIL_REGEXP.test('a@/')).toBe(false); + expect(EMAIL_REGEXP.test('a@:')).toBe(false); + expect(EMAIL_REGEXP.test('a@;')).toBe(false); + expect(EMAIL_REGEXP.test('a@<')).toBe(false); + expect(EMAIL_REGEXP.test('a@=')).toBe(false); + expect(EMAIL_REGEXP.test('a@>')).toBe(false); + expect(EMAIL_REGEXP.test('a@?')).toBe(false); + expect(EMAIL_REGEXP.test('a@@')).toBe(false); + expect(EMAIL_REGEXP.test('a@[')).toBe(false); + expect(EMAIL_REGEXP.test('a@\\')).toBe(false); + expect(EMAIL_REGEXP.test('a@]')).toBe(false); + expect(EMAIL_REGEXP.test('a@^')).toBe(false); + expect(EMAIL_REGEXP.test('a@_')).toBe(false); + expect(EMAIL_REGEXP.test('a@`')).toBe(false); + expect(EMAIL_REGEXP.test('a@{')).toBe(false); + expect(EMAIL_REGEXP.test('a@|')).toBe(false); + expect(EMAIL_REGEXP.test('a@}')).toBe(false); + expect(EMAIL_REGEXP.test('a@~')).toBe(false); + expect(EMAIL_REGEXP.test('a@İ')).toBe(false); + expect(EMAIL_REGEXP.test('a@ı')).toBe(false); + /* domain length, label and total */ + expect(EMAIL_REGEXP.test('a@xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx')).toBe(true); + expect(EMAIL_REGEXP.test('a@xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx')).toBe(false); + /* jshint maxlen:320 */ + expect(EMAIL_REGEXP.test('a@xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx.xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx.xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx.xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx')).toBe(true); + expect(EMAIL_REGEXP.test('a@xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx.xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx.xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx.xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx.x')).toBe(true); + expect(EMAIL_REGEXP.test('a@xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx.xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx.xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx.xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx.xx')).toBe(false); + /* jshint maxlen:200 */ + /* local-part valid characters and dot-atom syntax */ + expect(EMAIL_REGEXP.test("'@x")).toBe(true); + expect(EMAIL_REGEXP.test('-!#$%&*+/0123456789=?ABCDEFGHIJKLMNOPQRSTUVWXYZ^_`abcdefghijklmnopqrstuvwxyz{|}~@x')).toBe(true); + /* jshint maxlen:320 */ + expect(EMAIL_REGEXP.test('-!#$%&*+/0123456789=?ABCDEFGHIJKLMNOPQRSTUVWXYZ^_`abcdefghijklmnopqrstuvwxyz{|}~.-!#$%&*+/0123456789=?ABCDEFGHIJKLMNOPQRSTUVWXYZ^_`abcdefghijklmnopqrstuvwxyz{|}~.-!#$%&*+/0123456789=?ABCDEFGHIJKLMNOPQRSTUVWXYZ^_`abcdefghijklmnopqrstuvwxyz{|}~@x')).toBe(true); + /* jshint maxlen:200 */ + expect(EMAIL_REGEXP.test(".@x")).toBe(false); + expect(EMAIL_REGEXP.test("'.@x")).toBe(false); + expect(EMAIL_REGEXP.test(".'@x")).toBe(false); + expect(EMAIL_REGEXP.test("'.'@x")).toBe(true); + /* local-part invalid characters */ + expect(EMAIL_REGEXP.test('@x')).toBe(false); + expect(EMAIL_REGEXP.test(' @x')).toBe(false); + expect(EMAIL_REGEXP.test('"@x')).toBe(false); + expect(EMAIL_REGEXP.test('(@x')).toBe(false); + expect(EMAIL_REGEXP.test(')@x')).toBe(false); + expect(EMAIL_REGEXP.test(',@x')).toBe(false); + expect(EMAIL_REGEXP.test(':@x')).toBe(false); + expect(EMAIL_REGEXP.test(';@x')).toBe(false); + expect(EMAIL_REGEXP.test('<@x')).toBe(false); + expect(EMAIL_REGEXP.test('>@x')).toBe(false); + expect(EMAIL_REGEXP.test('@@x')).toBe(false); + expect(EMAIL_REGEXP.test('[@x')).toBe(false); + expect(EMAIL_REGEXP.test('\\@x')).toBe(false); + expect(EMAIL_REGEXP.test(']@x')).toBe(false); + expect(EMAIL_REGEXP.test('İ@x')).toBe(false); + expect(EMAIL_REGEXP.test('ı@x')).toBe(false); + /* content (local-part + ‘@’ + domain) is required */ + expect(EMAIL_REGEXP.test('')).toBe(false); + expect(EMAIL_REGEXP.test('a')).toBe(false); + expect(EMAIL_REGEXP.test('aa')).toBe(false); }); }); }); From c4104131e4f5bd9a6845437dc3211b98e5ff2c36 Mon Sep 17 00:00:00 2001 From: mirabilos Date: Tue, 7 Jun 2016 00:07:46 +0200 Subject: [PATCH 7/7] Limit size of local-part and total path size in eMail addresses MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit RFC 5321 §4.5.3.1.1 ⇒ local-part can have up to 64 octets RFC 5321 §4.5.3.1.3 ⇒ path “including the punctuation and element separators” can have up to 256 octets RFC 5321 §4.1.2 specifies path as ‘<’ + mailbox¹ + ‘>’ in the best case, leaving us 254 octets The limitation of the total path size to 254 octets leaves at most 252 octets (one local-part, one ‘@’) for the domain, which means we don’t need to explicitly check the domain size any more (removing the assertion after the ‘@’). ① RFC 821/5321 “mailbox” is the same as RFC 822 “addr-spec” --- src/ng/directive/input.js | 4 +++- test/ng/directive/inputSpec.js | 17 ++++++++++------- 2 files changed, 13 insertions(+), 8 deletions(-) diff --git a/src/ng/directive/input.js b/src/ng/directive/input.js index deb0316e8e30..93211f96dd84 100644 --- a/src/ng/directive/input.js +++ b/src/ng/directive/input.js @@ -24,7 +24,9 @@ var ISO_DATE_REGEXP = /^\d{4,}-[01]\d-[0-3]\dT[0-2]\d:[0-5]\d:[0-5]\d\.\d+(?:[+- // 9. Fragment // 1111111111111111 222 333333 44444 555555555555555555555555 666 77777777 8888888 999 var URL_REGEXP = /^[a-z][a-z\d.+-]*:\/*(?:[^:@]+(?::[^@]+)?@)?(?:[^\s:/?#]+|\[[a-f\d:]+\])(?::\d+)?(?:\/[^?#]*)?(?:\?[^#]*)?(?:#.*)?$/i; -var EMAIL_REGEXP = /^[-!#$%&'*+\/0-9=?A-Z^_`a-z{|}~]+(\.[-!#$%&'*+\/0-9=?A-Z^_`a-z{|}~]+)*@(?=.{1,255}$)[A-Za-z0-9]([A-Za-z0-9-]{0,61}[A-Za-z0-9])?(\.[A-Za-z0-9]([A-Za-z0-9-]{0,61}[A-Za-z0-9])?)*$/; +/* jshint maxlen:220 */ +var EMAIL_REGEXP = /^(?=.{1,254}$)(?=.{1,64}@)[-!#$%&'*+\/0-9=?A-Z^_`a-z{|}~]+(\.[-!#$%&'*+\/0-9=?A-Z^_`a-z{|}~]+)*@[A-Za-z0-9]([A-Za-z0-9-]{0,61}[A-Za-z0-9])?(\.[A-Za-z0-9]([A-Za-z0-9-]{0,61}[A-Za-z0-9])?)*$/; +/* jshint maxlen:200 */ var NUMBER_REGEXP = /^\s*(\-|\+)?(\d+|(\d*(\.\d*)))([eE][+-]?\d+)?\s*$/; var DATE_REGEXP = /^(\d{4,})-(\d{2})-(\d{2})$/; var DATETIMELOCAL_REGEXP = /^(\d{4,})-(\d\d)-(\d\d)T(\d\d):(\d\d)(?::(\d\d)(\.\d{1,3})?)?$/; diff --git a/test/ng/directive/inputSpec.js b/test/ng/directive/inputSpec.js index d3d969470ef8..736d9b268165 100644 --- a/test/ng/directive/inputSpec.js +++ b/test/ng/directive/inputSpec.js @@ -2843,16 +2843,16 @@ describe('input', function() { expect(EMAIL_REGEXP.test('a@xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx')).toBe(true); expect(EMAIL_REGEXP.test('a@xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx')).toBe(false); /* jshint maxlen:320 */ - expect(EMAIL_REGEXP.test('a@xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx.xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx.xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx.xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx')).toBe(true); - expect(EMAIL_REGEXP.test('a@xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx.xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx.xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx.xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx.x')).toBe(true); - expect(EMAIL_REGEXP.test('a@xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx.xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx.xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx.xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx.xx')).toBe(false); + expect(EMAIL_REGEXP.test('a@xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx.xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx.xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx.xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx')).toBe(true); + expect(EMAIL_REGEXP.test('a@xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx.xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx.xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx.xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx.x')).toBe(true); + expect(EMAIL_REGEXP.test('a@xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx.xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx.xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx.xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx.xx')).toBe(false); + expect(EMAIL_REGEXP.test('aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa@xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx.xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx.xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx.xx')).toBe(true); + expect(EMAIL_REGEXP.test('aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa@xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx.xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx.xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx.xxx')).toBe(false); /* jshint maxlen:200 */ /* local-part valid characters and dot-atom syntax */ expect(EMAIL_REGEXP.test("'@x")).toBe(true); - expect(EMAIL_REGEXP.test('-!#$%&*+/0123456789=?ABCDEFGHIJKLMNOPQRSTUVWXYZ^_`abcdefghijklmnopqrstuvwxyz{|}~@x')).toBe(true); - /* jshint maxlen:320 */ - expect(EMAIL_REGEXP.test('-!#$%&*+/0123456789=?ABCDEFGHIJKLMNOPQRSTUVWXYZ^_`abcdefghijklmnopqrstuvwxyz{|}~.-!#$%&*+/0123456789=?ABCDEFGHIJKLMNOPQRSTUVWXYZ^_`abcdefghijklmnopqrstuvwxyz{|}~.-!#$%&*+/0123456789=?ABCDEFGHIJKLMNOPQRSTUVWXYZ^_`abcdefghijklmnopqrstuvwxyz{|}~@x')).toBe(true); - /* jshint maxlen:200 */ + expect(EMAIL_REGEXP.test('-!#$%&*+/0123456789=?ABCDEFGHIJKLMNOPQRSTUVWXYZ@x')).toBe(true); + expect(EMAIL_REGEXP.test('^_`abcdefghijklmnopqrstuvwxyz{|}~@x')).toBe(true); expect(EMAIL_REGEXP.test(".@x")).toBe(false); expect(EMAIL_REGEXP.test("'.@x")).toBe(false); expect(EMAIL_REGEXP.test(".'@x")).toBe(false); @@ -2874,6 +2874,9 @@ describe('input', function() { expect(EMAIL_REGEXP.test(']@x')).toBe(false); expect(EMAIL_REGEXP.test('İ@x')).toBe(false); expect(EMAIL_REGEXP.test('ı@x')).toBe(false); + /* local-part size limit */ + expect(EMAIL_REGEXP.test('xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx@x')).toBe(true); + expect(EMAIL_REGEXP.test('xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx@x')).toBe(false); /* content (local-part + ‘@’ + domain) is required */ expect(EMAIL_REGEXP.test('')).toBe(false); expect(EMAIL_REGEXP.test('a')).toBe(false);