From bcc088c348abb15d8daae18d6431e5367869fb47 Mon Sep 17 00:00:00 2001 From: Romain Derie Date: Thu, 8 Feb 2018 15:48:50 +0100 Subject: [PATCH] [FIX] web, web_editor: Better email validation with regex (JS) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This commit improves link creation in web editor. Before this commit, anything with a @​ would be considered as valid email which is obviously not the case. It would then be prefixed by 'mailto:'. This was causing 2 issues: - URL with @​ symbol in it would have 'mailto:' added as prefix, like google maps coordinates. eg: mailto:http://www.google.com/maps/whatever/@​312211.22,321321 - Incorrect emails would go through (eg: @​@​@​, ko@​k@​k@​, mail@​mail) Now, we will try to detect and identify valid emails from invalid emails from URLs. It will also handle 'mailto:' directly typed in the input. This commit comes with it's counterpart in enterprise https://github.com/odoo/enterprise/pull/1859 This closes #11984, closes #22936 Note that there is a WIP in master to use this new is_email function everywhere we try to validate emails. It will aim to uniformize email validation in odoo's javascript that are often performed with different mean here and there, some more permissive than others, some only checking for @​. --- addons/web/static/src/js/framework/utils.js | 11 +++++++++++ addons/web_editor/static/src/js/widgets.js | 13 ++++++++++--- 2 files changed, 21 insertions(+), 3 deletions(-) diff --git a/addons/web/static/src/js/framework/utils.js b/addons/web/static/src/js/framework/utils.js index 3e9bd87f8de..cfb9d16af22 100644 --- a/addons/web/static/src/js/framework/utils.js +++ b/addons/web/static/src/js/framework/utils.js @@ -418,6 +418,16 @@ function swap(array, elem1, elem2) { array[i1] = elem2; } +function is_email(value, allow_mailto) { + // http://stackoverflow.com/questions/46155/validate-email-address-in-javascript + var re; + if (allow_mailto) { + re = /^(mailto:)?(([^<>()\[\]\.,;:\s@\"]+(\.[^<>()\[\]\.,;:\s@\"]+)*)|(\".+\"))@(([^<>()[\]\.,;:\s@\"]+\.)+[^<>()[\]\.,;:\s@\"]{2,})$/i; + } else { + re = /^(([^<>()\[\]\.,;:\s@\"]+(\.[^<>()\[\]\.,;:\s@\"]+)*)|(\".+\"))@(([^<>()[\]\.,;:\s@\"]+\.)+[^<>()[\]\.,;:\s@\"]{2,})$/i; + } + return re.test(value); +} return { divmod: divmod, @@ -445,6 +455,7 @@ return { xor: xor, DropMisordered: DropMisordered, swap: swap, + is_email: is_email, }; }); diff --git a/addons/web_editor/static/src/js/widgets.js b/addons/web_editor/static/src/js/widgets.js index bf72f25bc74..f23e196997a 100644 --- a/addons/web_editor/static/src/js/widgets.js +++ b/addons/web_editor/static/src/js/widgets.js @@ -4,6 +4,7 @@ odoo.define('web_editor.widget', function (require) { var core = require('web.core'); var ajax = require('web.ajax'); var Widget = require('web.Widget'); +var utils = require('web.utils'); var base = require('web_editor.base'); var rte = require('web_editor.rte'); @@ -1050,6 +1051,7 @@ var LinkDialog = Dialog.extend({ if (!$e.length) { $e = this.$('input.url-source:first'); } + $e.closest('.form-group').removeClass('has-error'); var val = $e.val(); var label = this.$('#link-text').val() || val; @@ -1070,8 +1072,7 @@ var LinkDialog = Dialog.extend({ var size = this.$("input[name='link-style-size']:checked").val() || ''; var classes = (this.data.className || "") + (style && style.length ? " btn " : "") + style + " " + size; var isNewWindow = this.$('input.window-new').prop('checked'); - - if ($e.hasClass('email-address') && $e.val().indexOf("@") !== -1) { + if ($e.hasClass('email-address') && (_.str.startsWith(val, 'mailto:') || (val.indexOf("@") !== -1 && !_.str.startsWith(val, 'http') && !_.str.startsWith(val, 'www')))) { self.get_data_buy_mail(def, $e, isNewWindow, label, classes, test); } else { self.get_data_buy_url(def, $e, isNewWindow, label, classes, test); @@ -1080,7 +1081,13 @@ var LinkDialog = Dialog.extend({ }, get_data_buy_mail: function (def, $e, isNewWindow, label, classes, test) { var val = $e.val(); - def.resolve(val.indexOf("mailto:") === 0 ? val : 'mailto:' + val, isNewWindow, label, classes); + if (utils.is_email(val, true)) { + def.resolve(val.indexOf("mailto:") === 0 ? val : 'mailto:' + val, isNewWindow, label, classes); + } else { + $e.closest('.form-group').addClass('has-error'); + $e.focus(); + def.reject(); + } }, get_data_buy_url: function (def, $e, isNewWindow, label, classes, test) { def.resolve($e.val(), isNewWindow, label, classes);