diff --git a/content/html/content/src/nsHTMLInputElement.cpp b/content/html/content/src/nsHTMLInputElement.cpp index 0c862a57b98..8110770129c 100644 --- a/content/html/content/src/nsHTMLInputElement.cpp +++ b/content/html/content/src/nsHTMLInputElement.cpp @@ -121,6 +121,8 @@ #include "mozilla/LookAndFeel.h" #include "mozilla/Util.h" // DebugOnly +#include "nsIIDNService.h" + using namespace mozilla; using namespace mozilla::dom; @@ -3918,18 +3920,34 @@ nsHTMLInputElement::IsValidEmailAddressList(const nsAString& aValue) bool nsHTMLInputElement::IsValidEmailAddress(const nsAString& aValue) { + nsCAutoString value = NS_ConvertUTF16toUTF8(aValue); PRUint32 i = 0; - PRUint32 length = aValue.Length(); + PRUint32 length = value.Length(); + + // Puny-encode the string if needed before running the validation algorithm. + nsCOMPtr idnSrv = do_GetService(NS_IDNSERVICE_CONTRACTID); + if (idnSrv) { + bool ace; + if (NS_SUCCEEDED(idnSrv->IsACE(value, &ace)) && !ace) { + nsCAutoString punyCodedValue; + if (NS_SUCCEEDED(idnSrv->ConvertUTF8toACE(value, punyCodedValue))) { + value = punyCodedValue; + length = value.Length(); + } + } + } else { + NS_ERROR("nsIIDNService isn't present!"); + } // If the email address is empty, begins with a '@' or ends with a '.', // we know it's invalid. - if (length == 0 || aValue[0] == '@' || aValue[length-1] == '.') { + if (length == 0 || value[0] == '@' || value[length-1] == '.') { return false; } // Parsing the username. - for (; i < length && aValue[i] != '@'; ++i) { - PRUnichar c = aValue[i]; + for (; i < length && value[i] != '@'; ++i) { + PRUnichar c = value[i]; // The username characters have to be in this list to be valid. if (!(nsCRT::IsAsciiAlpha(c) || nsCRT::IsAsciiDigit(c) || @@ -3948,17 +3966,17 @@ nsHTMLInputElement::IsValidEmailAddress(const nsAString& aValue) } // The domain name can't begin with a dot. - if (aValue[i] == '.') { + if (value[i] == '.') { return false; } // Parsing the domain name. for (; i < length; ++i) { - PRUnichar c = aValue[i]; + PRUnichar c = value[i]; if (c == '.') { // A dot can't follow a dot. - if (aValue[i-1] == '.') { + if (value[i-1] == '.') { return false; } } else if (!(nsCRT::IsAsciiAlpha(c) || nsCRT::IsAsciiDigit(c) || diff --git a/content/html/content/test/forms/test_input_email.html b/content/html/content/test/forms/test_input_email.html index 8b2b2fe7bd4..e6d16d4f0b3 100644 --- a/content/html/content/test/forms/test_input_email.html +++ b/content/html/content/test/forms/test_input_email.html @@ -87,6 +87,7 @@ var values = [ [ 'f\noo@bar.com', true ], [ 'f\roo@bar.com', true ], [ 'f\r\noo@bar.com', true ], + [ 'fü@foo.com', true ], // Some checks for the domain part. [ 'foo@bar', true ], [ 'foo@b', true ], @@ -104,6 +105,11 @@ var values = [ [ 'foo@b\rar.com', true ], [ 'foo@b\r\nar.com', true ], [ 'foo@.', false ], + [ 'foo@fü.com', true ], + [ 'foo@fu.cüm', true ], + // Long strings with UTF-8. + [ 'this.is.email.should.be.longer.than.sixty.four.characters.föö@mözillä.tld', true ], + [ 'this-is-email-should-be-longer-than-sixty-four-characters-föö@mözillä.tld', true, true ], ]; // Multiple values, we don't check e-mail validity, only multiple stuff. @@ -170,8 +176,13 @@ for each (c in illegalCharacters) { values.push(['foo@foo.ba' + c + 'r', false]); } -values.forEach(function([value, valid]) { - testEmailAddress(email, value, false, valid); +values.forEach(function([value, valid, todo]) { + if (todo === true) { + email.value = value; + todo_is(email.validity.valid, true, "value should be valid"); + } else { + testEmailAddress(email, value, false, valid); + } }); multipleValues.forEach(function([value, valid]) { diff --git a/content/html/content/test/test_formSubmission.html b/content/html/content/test/test_formSubmission.html index db7dfdac2b0..a5a0a17c9a7 100644 --- a/content/html/content/test/test_formSubmission.html +++ b/content/html/content/test/test_formSubmission.html @@ -240,6 +240,19 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=523771 + + <input type='email'> + + + + + + + + + +

@@ -472,6 +485,12 @@ var expectedSub = [ { name: "n19_3", value: "" }, { name: "n19_7_\r\n_\r\n_\r\n__\"", value: "http://v19_7_____\"" }, { name: "n19_8", value: "http://m\xf3zill\xe4.\xf3rg" }, + // + { name: "n20_1", value: "v20_1@bar" }, + { name: "n20_2", value: "" }, + { name: "n20_3", value: "" }, + { name: "n20_7_\r\n_\r\n_\r\n__\"", value: "v20_7_____\"@bar" }, + { name: "n20_8", value: "foo@mózillä.órg" }, // Default button // Submit button // Button button @@ -612,7 +631,8 @@ function utf8encode(s) { function checkURLSubmission(sub, expected) { function urlEscape(s) { return escape(utf8encode(s)).replace("%20", "+", "g") - .replace("/", "%2F", "g"); + .replace("/", "%2F", "g") + .replace("@", "%40", "g"); } subItems = sub.split("&");