mirror of
https://github.com/mozilla/gecko-dev.git
synced 2025-02-24 11:27:49 +00:00
Bug 1345767 - Part 4: Factor HasTypeMismatch() out of HTMLInputElement. r=smaug
MozReview-Commit-ID: 7kW0Ojnp2OE --HG-- extra : rebase_source : a4107eecb5e41c886b71adf55f91f0e2b19d047b
This commit is contained in:
parent
ee7fa8727c
commit
ea4dea7a00
@ -51,7 +51,6 @@
|
||||
#include "nsIServiceManager.h"
|
||||
#include "nsError.h"
|
||||
#include "nsIEditor.h"
|
||||
#include "nsIIOService.h"
|
||||
#include "nsDocument.h"
|
||||
#include "nsAttrValueOrString.h"
|
||||
#include "nsDateTimeControlFrame.h"
|
||||
@ -86,8 +85,6 @@
|
||||
#include "mozilla/dom/File.h"
|
||||
#include "mozilla/dom/FileList.h"
|
||||
#include "nsIFile.h"
|
||||
#include "nsNetCID.h"
|
||||
#include "nsNetUtil.h"
|
||||
#include "nsDirectoryServiceDefs.h"
|
||||
#include "nsIContentPrefService.h"
|
||||
#include "nsIMIMEService.h"
|
||||
@ -7550,40 +7547,7 @@ HTMLInputElement::IsValueMissing() const
|
||||
bool
|
||||
HTMLInputElement::HasTypeMismatch() const
|
||||
{
|
||||
if (mType != NS_FORM_INPUT_EMAIL && mType != NS_FORM_INPUT_URL) {
|
||||
return false;
|
||||
}
|
||||
|
||||
nsAutoString value;
|
||||
GetNonFileValueInternal(value);
|
||||
|
||||
if (value.IsEmpty()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (mType == NS_FORM_INPUT_EMAIL) {
|
||||
return HasAttr(kNameSpaceID_None, nsGkAtoms::multiple)
|
||||
? !IsValidEmailAddressList(value) : !IsValidEmailAddress(value);
|
||||
} else if (mType == NS_FORM_INPUT_URL) {
|
||||
/**
|
||||
* TODO:
|
||||
* The URL is not checked as the HTML5 specifications want it to be because
|
||||
* there is no code to check for a valid URI/IRI according to 3986 and 3987
|
||||
* RFC's at the moment, see bug 561586.
|
||||
*
|
||||
* RFC 3987 (IRI) implementation: bug 42899
|
||||
*
|
||||
* HTML5 specifications:
|
||||
* http://dev.w3.org/html5/spec/infrastructure.html#valid-url
|
||||
*/
|
||||
nsCOMPtr<nsIIOService> ioService = do_GetIOService();
|
||||
nsCOMPtr<nsIURI> uri;
|
||||
|
||||
return !NS_SUCCEEDED(ioService->NewURI(NS_ConvertUTF16toUTF8(value), nullptr,
|
||||
nullptr, getter_AddRefs(uri)));
|
||||
}
|
||||
|
||||
return false;
|
||||
return mInputType->HasTypeMismatch();
|
||||
}
|
||||
|
||||
bool
|
||||
@ -8159,88 +8123,6 @@ HTMLInputElement::GetValidationMessage(nsAString& aValidationMessage,
|
||||
return rv;
|
||||
}
|
||||
|
||||
//static
|
||||
bool
|
||||
HTMLInputElement::IsValidEmailAddressList(const nsAString& aValue)
|
||||
{
|
||||
HTMLSplitOnSpacesTokenizer tokenizer(aValue, ',');
|
||||
|
||||
while (tokenizer.hasMoreTokens()) {
|
||||
if (!IsValidEmailAddress(tokenizer.nextToken())) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return !tokenizer.separatorAfterCurrentToken();
|
||||
}
|
||||
|
||||
//static
|
||||
bool
|
||||
HTMLInputElement::IsValidEmailAddress(const nsAString& aValue)
|
||||
{
|
||||
// Email addresses can't be empty and can't end with a '.' or '-'.
|
||||
if (aValue.IsEmpty() || aValue.Last() == '.' || aValue.Last() == '-') {
|
||||
return false;
|
||||
}
|
||||
|
||||
uint32_t atPos;
|
||||
nsAutoCString value;
|
||||
if (!PunycodeEncodeEmailAddress(aValue, value, &atPos) ||
|
||||
atPos == (uint32_t)kNotFound || atPos == 0 || atPos == value.Length() - 1) {
|
||||
// Could not encode, or "@" was not found, or it was at the start or end
|
||||
// of the input - in all cases, not a valid email address.
|
||||
return false;
|
||||
}
|
||||
|
||||
uint32_t length = value.Length();
|
||||
uint32_t i = 0;
|
||||
|
||||
// Parsing the username.
|
||||
for (; i < atPos; ++i) {
|
||||
char16_t c = value[i];
|
||||
|
||||
// The username characters have to be in this list to be valid.
|
||||
if (!(nsCRT::IsAsciiAlpha(c) || nsCRT::IsAsciiDigit(c) ||
|
||||
c == '.' || c == '!' || c == '#' || c == '$' || c == '%' ||
|
||||
c == '&' || c == '\''|| c == '*' || c == '+' || c == '-' ||
|
||||
c == '/' || c == '=' || c == '?' || c == '^' || c == '_' ||
|
||||
c == '`' || c == '{' || c == '|' || c == '}' || c == '~' )) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Skip the '@'.
|
||||
++i;
|
||||
|
||||
// The domain name can't begin with a dot or a dash.
|
||||
if (value[i] == '.' || value[i] == '-') {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Parsing the domain name.
|
||||
for (; i < length; ++i) {
|
||||
char16_t c = value[i];
|
||||
|
||||
if (c == '.') {
|
||||
// A dot can't follow a dot or a dash.
|
||||
if (value[i-1] == '.' || value[i-1] == '-') {
|
||||
return false;
|
||||
}
|
||||
} else if (c == '-'){
|
||||
// A dash can't follow a dot.
|
||||
if (value[i-1] == '.') {
|
||||
return false;
|
||||
}
|
||||
} else if (!(nsCRT::IsAsciiAlpha(c) || nsCRT::IsAsciiDigit(c) ||
|
||||
c == '-')) {
|
||||
// The domain characters have to be in this list to be valid.
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP_(bool)
|
||||
HTMLInputElement::IsSingleLineTextControl() const
|
||||
{
|
||||
|
@ -924,28 +924,6 @@ protected:
|
||||
VALUE_MODE_FILENAME
|
||||
};
|
||||
|
||||
/**
|
||||
* This helper method returns true if aValue is a valid email address.
|
||||
* This is following the HTML5 specification:
|
||||
* http://dev.w3.org/html5/spec/forms.html#valid-e-mail-address
|
||||
*
|
||||
* @param aValue the email address to check.
|
||||
* @result whether the given string is a valid email address.
|
||||
*/
|
||||
static bool IsValidEmailAddress(const nsAString& aValue);
|
||||
|
||||
/**
|
||||
* This helper method returns true if aValue is a valid email address list.
|
||||
* Email address list is a list of email address separated by comas (,) which
|
||||
* can be surrounded by space charecters.
|
||||
* This is following the HTML5 specification:
|
||||
* http://dev.w3.org/html5/spec/forms.html#valid-e-mail-address-list
|
||||
*
|
||||
* @param aValue the email address list to check.
|
||||
* @result whether the given string is a valid email address list.
|
||||
*/
|
||||
static bool IsValidEmailAddressList(const nsAString& aValue);
|
||||
|
||||
/**
|
||||
* This helper method convert a sub-string that contains only digits to a
|
||||
* number (unsigned int given that it can't contain a minus sign).
|
||||
|
@ -114,6 +114,12 @@ InputType::IsValueEmpty() const
|
||||
return mInputElement->IsValueEmpty();
|
||||
}
|
||||
|
||||
void
|
||||
InputType::GetNonFileValueInternal(nsAString& aValue) const
|
||||
{
|
||||
return mInputElement->GetNonFileValueInternal(aValue);
|
||||
}
|
||||
|
||||
void
|
||||
InputType::DropReference()
|
||||
{
|
||||
@ -138,3 +144,9 @@ InputType::IsValueMissing() const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
InputType::HasTypeMismatch() const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
@ -9,6 +9,7 @@
|
||||
|
||||
#include <stdint.h>
|
||||
#include "mozilla/UniquePtr.h"
|
||||
#include "nsString.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
@ -38,6 +39,7 @@ public:
|
||||
virtual bool IsTooLong() const;
|
||||
virtual bool IsTooShort() const;
|
||||
virtual bool IsValueMissing() const;
|
||||
virtual bool HasTypeMismatch() const;
|
||||
|
||||
protected:
|
||||
explicit InputType(mozilla::dom::HTMLInputElement* aInputElement)
|
||||
@ -62,6 +64,10 @@ protected:
|
||||
*/
|
||||
bool IsValueEmpty() const;
|
||||
|
||||
// A getter for callers that know we're not dealing with a file input, so they
|
||||
// don't have to think about the caller type.
|
||||
void GetNonFileValueInternal(nsAString& aValue) const;
|
||||
|
||||
mozilla::dom::HTMLInputElement* mInputElement;
|
||||
};
|
||||
|
||||
|
@ -8,6 +8,12 @@
|
||||
|
||||
#include "mozilla/dom/HTMLInputElement.h"
|
||||
#include "mozilla/dom/BindingDeclarations.h"
|
||||
#include "HTMLSplitOnSpacesTokenizer.h"
|
||||
#include "nsCRTGlue.h"
|
||||
#include "nsIIDNService.h"
|
||||
#include "nsIIOService.h"
|
||||
#include "nsNetCID.h"
|
||||
#include "nsNetUtil.h"
|
||||
|
||||
bool
|
||||
SingleLineTextInputTypeBase::IsMutable() const
|
||||
@ -61,3 +67,166 @@ SingleLineTextInputTypeBase::IsValueMissing() const
|
||||
|
||||
return IsValueEmpty();
|
||||
}
|
||||
|
||||
/* input type=url */
|
||||
|
||||
bool
|
||||
URLInputType::HasTypeMismatch() const
|
||||
{
|
||||
nsAutoString value;
|
||||
GetNonFileValueInternal(value);
|
||||
|
||||
if (value.IsEmpty()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* TODO:
|
||||
* The URL is not checked as the HTML5 specifications want it to be because
|
||||
* there is no code to check for a valid URI/IRI according to 3986 and 3987
|
||||
* RFC's at the moment, see bug 561586.
|
||||
*
|
||||
* RFC 3987 (IRI) implementation: bug 42899
|
||||
*
|
||||
* HTML5 specifications:
|
||||
* http://dev.w3.org/html5/spec/infrastructure.html#valid-url
|
||||
*/
|
||||
nsCOMPtr<nsIIOService> ioService = do_GetIOService();
|
||||
nsCOMPtr<nsIURI> uri;
|
||||
|
||||
return !NS_SUCCEEDED(ioService->NewURI(NS_ConvertUTF16toUTF8(value), nullptr,
|
||||
nullptr, getter_AddRefs(uri)));
|
||||
|
||||
}
|
||||
|
||||
/* input type=email */
|
||||
|
||||
bool
|
||||
EmailInputType::HasTypeMismatch() const
|
||||
{
|
||||
nsAutoString value;
|
||||
GetNonFileValueInternal(value);
|
||||
|
||||
if (value.IsEmpty()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return mInputElement->HasAttr(kNameSpaceID_None, nsGkAtoms::multiple) ?
|
||||
!IsValidEmailAddressList(value) : !IsValidEmailAddress(value);
|
||||
}
|
||||
|
||||
/* static */ bool
|
||||
EmailInputType::IsValidEmailAddressList(const nsAString& aValue)
|
||||
{
|
||||
HTMLSplitOnSpacesTokenizer tokenizer(aValue, ',');
|
||||
|
||||
while (tokenizer.hasMoreTokens()) {
|
||||
if (!IsValidEmailAddress(tokenizer.nextToken())) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return !tokenizer.separatorAfterCurrentToken();
|
||||
}
|
||||
|
||||
/* static */ bool
|
||||
EmailInputType::IsValidEmailAddress(const nsAString& aValue)
|
||||
{
|
||||
// Email addresses can't be empty and can't end with a '.' or '-'.
|
||||
if (aValue.IsEmpty() || aValue.Last() == '.' || aValue.Last() == '-') {
|
||||
return false;
|
||||
}
|
||||
|
||||
uint32_t atPos;
|
||||
nsAutoCString value;
|
||||
if (!PunycodeEncodeEmailAddress(aValue, value, &atPos) ||
|
||||
atPos == (uint32_t)kNotFound || atPos == 0 || atPos == value.Length() - 1) {
|
||||
// Could not encode, or "@" was not found, or it was at the start or end
|
||||
// of the input - in all cases, not a valid email address.
|
||||
return false;
|
||||
}
|
||||
|
||||
uint32_t length = value.Length();
|
||||
uint32_t i = 0;
|
||||
|
||||
// Parsing the username.
|
||||
for (; i < atPos; ++i) {
|
||||
char16_t c = value[i];
|
||||
|
||||
// The username characters have to be in this list to be valid.
|
||||
if (!(nsCRT::IsAsciiAlpha(c) || nsCRT::IsAsciiDigit(c) ||
|
||||
c == '.' || c == '!' || c == '#' || c == '$' || c == '%' ||
|
||||
c == '&' || c == '\''|| c == '*' || c == '+' || c == '-' ||
|
||||
c == '/' || c == '=' || c == '?' || c == '^' || c == '_' ||
|
||||
c == '`' || c == '{' || c == '|' || c == '}' || c == '~' )) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Skip the '@'.
|
||||
++i;
|
||||
|
||||
// The domain name can't begin with a dot or a dash.
|
||||
if (value[i] == '.' || value[i] == '-') {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Parsing the domain name.
|
||||
for (; i < length; ++i) {
|
||||
char16_t c = value[i];
|
||||
|
||||
if (c == '.') {
|
||||
// A dot can't follow a dot or a dash.
|
||||
if (value[i-1] == '.' || value[i-1] == '-') {
|
||||
return false;
|
||||
}
|
||||
} else if (c == '-'){
|
||||
// A dash can't follow a dot.
|
||||
if (value[i-1] == '.') {
|
||||
return false;
|
||||
}
|
||||
} else if (!(nsCRT::IsAsciiAlpha(c) || nsCRT::IsAsciiDigit(c) ||
|
||||
c == '-')) {
|
||||
// The domain characters have to be in this list to be valid.
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/* static */ bool
|
||||
EmailInputType::PunycodeEncodeEmailAddress(const nsAString& aEmail,
|
||||
nsAutoCString& aEncodedEmail,
|
||||
uint32_t* aIndexOfAt)
|
||||
{
|
||||
nsAutoCString value = NS_ConvertUTF16toUTF8(aEmail);
|
||||
*aIndexOfAt = (uint32_t)value.FindChar('@');
|
||||
|
||||
if (*aIndexOfAt == (uint32_t)kNotFound ||
|
||||
*aIndexOfAt == value.Length() - 1) {
|
||||
aEncodedEmail = value;
|
||||
return true;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIIDNService> idnSrv = do_GetService(NS_IDNSERVICE_CONTRACTID);
|
||||
if (!idnSrv) {
|
||||
NS_ERROR("nsIIDNService isn't present!");
|
||||
return false;
|
||||
}
|
||||
|
||||
uint32_t indexOfDomain = *aIndexOfAt + 1;
|
||||
|
||||
const nsDependentCSubstring domain = Substring(value, indexOfDomain);
|
||||
bool ace;
|
||||
if (NS_SUCCEEDED(idnSrv->IsACE(domain, &ace)) && !ace) {
|
||||
nsAutoCString domainACE;
|
||||
if (NS_FAILED(idnSrv->ConvertUTF8toACE(domain, domainACE))) {
|
||||
return false;
|
||||
}
|
||||
value.Replace(indexOfDomain, domain.Length(), domainACE);
|
||||
}
|
||||
|
||||
aEncodedEmail = value;
|
||||
return true;
|
||||
}
|
||||
|
@ -85,6 +85,8 @@ public:
|
||||
return new (aMemory) URLInputType(aInputElement);
|
||||
}
|
||||
|
||||
bool HasTypeMismatch() const override;
|
||||
|
||||
private:
|
||||
explicit URLInputType(mozilla::dom::HTMLInputElement* aInputElement)
|
||||
: SingleLineTextInputTypeBase(aInputElement)
|
||||
@ -101,10 +103,54 @@ public:
|
||||
return new (aMemory) EmailInputType(aInputElement);
|
||||
}
|
||||
|
||||
bool HasTypeMismatch() const override;
|
||||
|
||||
private:
|
||||
explicit EmailInputType(mozilla::dom::HTMLInputElement* aInputElement)
|
||||
: SingleLineTextInputTypeBase(aInputElement)
|
||||
{}
|
||||
|
||||
/**
|
||||
* This helper method returns true if aValue is a valid email address.
|
||||
* This is following the HTML5 specification:
|
||||
* http://dev.w3.org/html5/spec/forms.html#valid-e-mail-address
|
||||
*
|
||||
* @param aValue the email address to check.
|
||||
* @result whether the given string is a valid email address.
|
||||
*/
|
||||
static bool IsValidEmailAddress(const nsAString& aValue);
|
||||
|
||||
/**
|
||||
* This helper method returns true if aValue is a valid email address list.
|
||||
* Email address list is a list of email address separated by comas (,) which
|
||||
* can be surrounded by space charecters.
|
||||
* This is following the HTML5 specification:
|
||||
* http://dev.w3.org/html5/spec/forms.html#valid-e-mail-address-list
|
||||
*
|
||||
* @param aValue the email address list to check.
|
||||
* @result whether the given string is a valid email address list.
|
||||
*/
|
||||
static bool IsValidEmailAddressList(const nsAString& aValue);
|
||||
|
||||
/**
|
||||
* Takes aEmail and attempts to convert everything after the first "@"
|
||||
* character (if anything) to punycode before returning the complete result
|
||||
* via the aEncodedEmail out-param. The aIndexOfAt out-param is set to the
|
||||
* index of the "@" character.
|
||||
*
|
||||
* If no "@" is found in aEmail, aEncodedEmail is simply set to aEmail and
|
||||
* the aIndexOfAt out-param is set to kNotFound.
|
||||
*
|
||||
* Returns true in all cases unless an attempt to punycode encode fails. If
|
||||
* false is returned, aEncodedEmail has not been set.
|
||||
*
|
||||
* This function exists because ConvertUTF8toACE() splits on ".", meaning that
|
||||
* for 'user.name@sld.tld' it would treat "name@sld" as a label. We want to
|
||||
* encode the domain part only.
|
||||
*/
|
||||
static bool PunycodeEncodeEmailAddress(const nsAString& aEmail,
|
||||
nsAutoCString& aEncodedEmail,
|
||||
uint32_t* aIndexOfAt);
|
||||
};
|
||||
|
||||
// input type=password
|
||||
|
Loading…
x
Reference in New Issue
Block a user