Universal Acceptance Update (2/3)

This commit is contained in:
Pinga 2024-11-01 13:19:43 +02:00
parent 4fa1289334
commit f60b59b00b
4 changed files with 53 additions and 18 deletions

View file

@ -227,7 +227,7 @@ class ContactsController extends Controller
$fax = $normalizedFax['success']; $fax = $normalizedFax['success'];
} }
if (!filter_var($email, FILTER_VALIDATE_EMAIL)) { if (!validateUniversalEmail($email)) {
$this->container->get('flash')->addMessage('error', 'Unable to create contact: Email address failed check'); $this->container->get('flash')->addMessage('error', 'Unable to create contact: Email address failed check');
return $response->withHeader('Location', '/contact/create')->withStatus(302); return $response->withHeader('Location', '/contact/create')->withStatus(302);
} }
@ -959,7 +959,7 @@ class ContactsController extends Controller
return $response->withHeader('Location', '/contact/update/'.$identifier)->withStatus(302); return $response->withHeader('Location', '/contact/update/'.$identifier)->withStatus(302);
} }
if (!filter_var($email, FILTER_VALIDATE_EMAIL)) { if (!validateUniversalEmail($email)) {
$this->container->get('flash')->addMessage('error', 'Unable to update contact: Email address failed check'); $this->container->get('flash')->addMessage('error', 'Unable to update contact: Email address failed check');
return $response->withHeader('Location', '/contact/update/'.$identifier)->withStatus(302); return $response->withHeader('Location', '/contact/update/'.$identifier)->withStatus(302);
} }

View file

@ -542,3 +542,38 @@ function validateLocField($input, $minLength = 5, $maxLength = 255) {
mb_strlen($input) <= $maxLength && mb_strlen($input) <= $maxLength &&
preg_match($locRegex, $input); preg_match($locRegex, $input);
} }
function validateUniversalEmail($email) {
// Normalize the email to NFC form to ensure consistency
$email = \Normalizer::normalize($email, \Normalizer::FORM_C);
// Remove any control characters
$email = preg_replace('/[\p{C}]/u', '', $email);
// Split email into local and domain parts
$parts = explode('@', $email, 2);
if (count($parts) !== 2) {
return false; // Invalid email format
}
list($localPart, $domainPart) = $parts;
// Convert the domain part to Punycode if it contains non-ASCII characters
if (preg_match('/[^\x00-\x7F]/', $domainPart)) {
$punycodeDomain = idn_to_ascii($domainPart, IDNA_DEFAULT, INTL_IDNA_VARIANT_UTS46);
if ($punycodeDomain === false) {
return false; // Invalid domain part, failed conversion
}
} else {
$punycodeDomain = $domainPart;
}
// Reconstruct the email with the Punycode domain part (if converted)
$emailToValidate = $localPart . '@' . $punycodeDomain;
// Updated regex for both ASCII and IDN email validation
$emailPattern = '/^[\p{L}\p{N}\p{M}._%+-]+@([a-zA-Z0-9-]+|\bxn--[a-zA-Z0-9-]+)(\.([a-zA-Z0-9-]+|\bxn--[a-zA-Z0-9-]+))+$/u';
// Validate using regex
return preg_match($emailPattern, $emailToValidate);
}

View file

@ -37,7 +37,7 @@
<!-- Internationalized Name --> <!-- Internationalized Name -->
<div class="mb-3"> <div class="mb-3">
<label for="intName" class="form-label required">{{ __('Name') }}</label> <label for="intName" class="form-label required">{{ __('Name') }}</label>
<input type="text" class="form-control" id="intName" name="intName" required="required"> <input type="text" class="form-control" id="intName" name="intName">
<label class="form-check form-switch mt-1"> <label class="form-check form-switch mt-1">
<input class="form-check-input" type="checkbox" id="discloseNameInt" name="disclose_name_int"> <input class="form-check-input" type="checkbox" id="discloseNameInt" name="disclose_name_int">
<span class="form-check-label" for="discloseNameInt">{{ __('Disclose in WHOIS') }}</span> <span class="form-check-label" for="discloseNameInt">{{ __('Disclose in WHOIS') }}</span>
@ -47,7 +47,7 @@
{% if registrars and not registrar %} {% if registrars and not registrar %}
<div class="form-group mb-3"> <div class="form-group mb-3">
<label for="registrarDropdown" class="form-label required">{{ __('Select Registrar') }}</label> <label for="registrarDropdown" class="form-label required">{{ __('Select Registrar') }}</label>
<select id="registrarDropdown" name="registrar" class="form-control"> <select id="registrarDropdown" name="registrar" class="form-control" required="required">
{% for registrar in registrars %} {% for registrar in registrars %}
<option value="{{ registrar.id }}">{{ registrar.name }}</option> <option value="{{ registrar.id }}">{{ registrar.name }}</option>
{% endfor %} {% endfor %}
@ -68,7 +68,7 @@
<!-- Internationalized Address: Street Details --> <!-- Internationalized Address: Street Details -->
<div class="mb-3"> <div class="mb-3">
<label for="street1" class="form-label required">{{ __('Street') }} 1</label> <label for="street1" class="form-label required">{{ __('Street') }} 1</label>
<input type="text" class="form-control" id="street1" name="street1" required="required"> <input type="text" class="form-control" id="street1" name="street1">
</div> </div>
<div class="mb-3"> <div class="mb-3">
<label for="street2" class="form-label">{{ __('Street') }} 2</label> <label for="street2" class="form-label">{{ __('Street') }} 2</label>
@ -82,7 +82,7 @@
<!-- Internationalized Address: City, SP, PC, CC --> <!-- Internationalized Address: City, SP, PC, CC -->
<div class="mb-3"> <div class="mb-3">
<label for="city" class="form-label required">{{ __('City') }}</label> <label for="city" class="form-label required">{{ __('City') }}</label>
<input type="text" class="form-control" id="city" name="city" required="required"> <input type="text" class="form-control" id="city" name="city">
</div> </div>
<div class="mb-3"> <div class="mb-3">
<label for="sp" class="form-label">{{ __('State/Province') }}</label> <label for="sp" class="form-label">{{ __('State/Province') }}</label>
@ -94,7 +94,7 @@
</div> </div>
<div class="mb-3"> <div class="mb-3">
<label for="cc" class="form-label required">{{ __('Country') }}</label> <label for="cc" class="form-label required">{{ __('Country') }}</label>
<select class="form-select" id="cc" name="cc" required="required"> <select class="form-select" id="cc" name="cc">
{% for country in countries %} {% for country in countries %}
<option value="{{ country.alpha2|lower }}">{{ country.name }}</option> <option value="{{ country.alpha2|lower }}">{{ country.name }}</option>
{% endfor %} {% endfor %}
@ -140,7 +140,7 @@
<!-- Email --> <!-- Email -->
<div class="mb-3"> <div class="mb-3">
<label for="email" class="form-label required">{{ __('Email') }}</label> <label for="email" class="form-label required">{{ __('Email') }}</label>
<input type="email" class="form-control" id="email" name="email" required="required" autocapitalize="none"> <input type="text" class="form-control" id="email" name="email" required="required" autocapitalize="none">
<label class="form-check form-switch mt-1"> <label class="form-check form-switch mt-1">
<input class="form-check-input" type="checkbox" id="discloseEmail" name="disclose_email"> <input class="form-check-input" type="checkbox" id="discloseEmail" name="disclose_email">
<span class="form-check-label" for="discloseEmail">{{ __('Disclose in WHOIS') }}</span> <span class="form-check-label" for="discloseEmail">{{ __('Disclose in WHOIS') }}</span>

View file

@ -46,8 +46,8 @@
<!-- Internationalized Name --> <!-- Internationalized Name -->
<div class="mb-3"> <div class="mb-3">
<label for="intName" class="form-label required">{{ __('Name') }}</label> <label for="intName" class="form-label{% if not postal_loc.name %} required{% endif %}">{{ __('Name') }}</label>
<input type="text" class="form-control" id="intName" name="intName" required="required" value="{{ postal_int.name }}"> <input type="text" class="form-control" id="intName" name="intName"{% if not postal_loc.name %} required="required" {% endif %}value="{{ postal_int.name }}">
<label class="form-check form-switch mt-1"> <label class="form-check form-switch mt-1">
<input class="form-check-input" type="checkbox" id="discloseNameInt" name="disclose_name_int" {% if postal_int.disclose_name_int == '1' %}checked{% endif %}> <input class="form-check-input" type="checkbox" id="discloseNameInt" name="disclose_name_int" {% if postal_int.disclose_name_int == '1' %}checked{% endif %}>
<span class="form-check-label" for="discloseNameInt">{{ __('Disclose in WHOIS') }}</span> <span class="form-check-label" for="discloseNameInt">{{ __('Disclose in WHOIS') }}</span>
@ -66,8 +66,8 @@
<!-- Internationalized Address: Street Details --> <!-- Internationalized Address: Street Details -->
<div class="mb-3"> <div class="mb-3">
<label for="street1" class="form-label required">{{ __('Street') }} 1</label> <label for="street1" class="form-label{% if not postal_loc.street1 %} required{% endif %}">{{ __('Street') }} 1</label>
<input type="text" class="form-control" id="street1" name="street1" required="required" value="{{ postal_int.street1 }}"> <input type="text" class="form-control" id="street1" name="street1"{% if not postal_loc.street1 %} required="required" {% endif %}value="{{ postal_int.street1 }}">
</div> </div>
<div class="mb-3"> <div class="mb-3">
<label for="street2" class="form-label">{{ __('Street') }} 2</label> <label for="street2" class="form-label">{{ __('Street') }} 2</label>
@ -80,8 +80,8 @@
<!-- Internationalized Address: City, SP, PC, CC --> <!-- Internationalized Address: City, SP, PC, CC -->
<div class="mb-3"> <div class="mb-3">
<label for="city" class="form-label required">{{ __('City') }}</label> <label for="city" class="form-label{% if not postal_loc.city %} required{% endif %}">{{ __('City') }}</label>
<input type="text" class="form-control" id="city" name="city" required="required" value="{{ postal_int.city }}"> <input type="text" class="form-control" id="city" name="city"{% if not postal_loc.city %} required="required" {% endif %}value="{{ postal_int.city }}">
</div> </div>
<div class="mb-3"> <div class="mb-3">
<label for="sp" class="form-label">{{ __('State/Province') }}</label> <label for="sp" class="form-label">{{ __('State/Province') }}</label>
@ -92,8 +92,8 @@
<input type="text" class="form-control" id="pc" name="pc" value="{{ postal_int.pc }}"> <input type="text" class="form-control" id="pc" name="pc" value="{{ postal_int.pc }}">
</div> </div>
<div class="mb-3"> <div class="mb-3">
<label for="cc" class="form-label required">{{ __('Country') }}</label> <label for="cc" class="form-label{% if not postal_loc.cc %} required{% endif %}">{{ __('Country') }}</label>
<select class="form-select" id="cc" name="cc" required="required"> <select class="form-select" id="cc" name="cc"{% if not postal_loc.cc %} required="required"{% endif %}>
{% for country in countries %} {% for country in countries %}
<option value="{{ country.alpha2|lower }}" {% if postal_int.cc|lower == country.alpha2|lower %}selected{% endif %}>{{ country.name }}</option> <option value="{{ country.alpha2|lower }}" {% if postal_int.cc|lower == country.alpha2|lower %}selected{% endif %}>{{ country.name }}</option>
{% endfor %} {% endfor %}
@ -132,7 +132,7 @@
<!-- Email --> <!-- Email -->
<div class="mb-3"> <div class="mb-3">
<label for="email" class="form-label required">{{ __('Email') }}</label> <label for="email" class="form-label required">{{ __('Email') }}</label>
<input type="email" class="form-control" id="email" name="email" required="required" autocapitalize="none" value="{{ contact.email }}"> <input type="text" class="form-control" id="email" name="email" required="required" autocapitalize="none" value="{{ contact.email }}">
<label class="form-check form-switch mt-1"> <label class="form-check form-switch mt-1">
<input class="form-check-input" type="checkbox" id="discloseEmail" name="disclose_email" {% if contact.disclose_email == '1' %}checked{% endif %}> <input class="form-check-input" type="checkbox" id="discloseEmail" name="disclose_email" {% if contact.disclose_email == '1' %}checked{% endif %}>
<span class="form-check-label" for="discloseEmail">{{ __('Disclose in WHOIS') }}</span> <span class="form-check-label" for="discloseEmail">{{ __('Disclose in WHOIS') }}</span>