1
0
mirror of https://github.com/django/django.git synced 2025-02-04 22:47:53 +00:00

Fixed issue where IDNA 2008 encoded domains were not validated

This commit is contained in:
Chaitanya Rahalkar 2024-12-17 23:17:17 -06:00
parent 7e41a7a47d
commit 78e5cb0941
3 changed files with 37 additions and 4 deletions

View File

@ -6,7 +6,7 @@ from urllib.parse import urlsplit
from django.core.exceptions import ValidationError
from django.utils.deconstruct import deconstructible
from django.utils.encoding import punycode
from django.utils.encoding import idna2008_encode
from django.utils.ipv6 import is_valid_ipv6_address
from django.utils.regex_helper import _lazy_re_compile
from django.utils.translation import gettext_lazy as _
@ -254,7 +254,8 @@ class EmailValidator:
):
# Try for possible IDN domain-part
try:
domain_part = punycode(domain_part)
domain_part = idna2008_encode(domain_part)
except UnicodeError:
pass
else:
@ -679,4 +680,4 @@ class ProhibitNullCharactersValidator:
isinstance(other, self.__class__)
and self.message == other.message
and self.code == other.code
)
)

View File

@ -4,7 +4,7 @@ import locale
from decimal import Decimal
from types import NoneType
from urllib.parse import quote
import unicodedata
from django.utils.functional import Promise
@ -209,6 +209,22 @@ def punycode(domain):
"""Return the Punycode of the given domain if it's non-ASCII."""
return domain.encode("idna").decode("ascii")
def idna2008_encode(domain):
"""
Encode a domain name according to IDNA 2008 (simplified version).
"""
def encode_label(label):
if all(ord(c) < 128 for c in label):
# Label contains only ASCII characters
return label
# Normalize and encode to Punycode
normalized_label = unicodedata.normalize('NFC', label)
return f"xn--{normalized_label.encode('punycode').decode('ascii')}"
labels = domain.split(".")
ascii_labels = [encode_label(label) for label in labels]
return ".".join(ascii_labels)
def repercent_broken_unicode(path):
"""

View File

@ -319,6 +319,22 @@ TEST_DATA = [
(validate_email, "example@inv-.alid-.com", ValidationError),
(validate_email, "example@inv-.-alid.com", ValidationError),
(validate_email, 'test@example.com\n\n<script src="x.js">', ValidationError),
(validate_email, 'email@domain.com', None),
(validate_email, 'email@xn--4ca9at.com', None),
(validate_email, 'email@öäü.com', None),
(validate_email, 'email@עִתוֹן.example.il', None),
(validate_email, 'email@މިހާރު.example.mv', None),
(validate_email, 'email@漢字.example.com', None),
(validate_email, "editor@މިހާރު.example.mv", None),
(validate_email, 'email@', ValidationError),
(validate_email, '@domain.com', ValidationError),
(validate_email, 'email.domain.com', ValidationError),
(validate_email, 'email@domain@domain.com', ValidationError),
(validate_email, 'email@domain..com', ValidationError),
(validate_email, 'email@.domain.com', ValidationError),
(validate_email, 'email@-domain.com', ValidationError),
(validate_email, 'email@domain-.com', ValidationError),
(validate_email, 'email@domain.com-', ValidationError),
# Quoted-string format (CR not allowed)
(validate_email, '"\\\011"@here.com', None),
(validate_email, '"\\\012"@here.com', ValidationError),