Add a function to convert a domain name to punycode.
This commit is contained in:
parent
a721084f6e
commit
041bd63864
2 changed files with 35 additions and 1 deletions
|
@ -101,5 +101,21 @@ def idna(domain):
|
|||
domain_parts.append(label)
|
||||
return '.'.join(domain_parts)
|
||||
|
||||
def punycode(domain):
|
||||
domain_parts = []
|
||||
for label in domain.split('.'):
|
||||
try:
|
||||
label = encodings.idna.nameprep(label)
|
||||
encodings.idna.ToASCII(label)
|
||||
except UnicodeError:
|
||||
raise StringprepError
|
||||
|
||||
for char in label:
|
||||
if char in ILLEGAL_CHARS:
|
||||
raise StringprepError
|
||||
|
||||
domain_parts.append(label)
|
||||
return b'.'.join(domain_parts)
|
||||
|
||||
logging.getLogger(__name__).warning('Using slower stringprep, consider '
|
||||
'compiling the faster cython/libidn one.')
|
||||
|
|
|
@ -19,7 +19,8 @@ from libc.stdlib cimport free
|
|||
# Those are Cython declarations for the C function we’ll be using.
|
||||
|
||||
cdef extern from "stringprep.h" nogil:
|
||||
int stringprep_profile(const char* in_, char** out, const char* profile, int flags)
|
||||
int stringprep_profile(const char* in_, char** out, const char* profile,
|
||||
int flags)
|
||||
|
||||
cdef extern from "idna.h" nogil:
|
||||
int idna_to_ascii_8z(const char* in_, char** out, int flags)
|
||||
|
@ -40,16 +41,19 @@ cdef str _stringprep(str in_, const char* profile):
|
|||
free(out)
|
||||
return unicode_out
|
||||
|
||||
|
||||
def nodeprep(str node):
|
||||
"""The nodeprep profile of stringprep used to validate the local, or
|
||||
username, portion of a JID."""
|
||||
return _stringprep(node, 'Nodeprep')
|
||||
|
||||
|
||||
def resourceprep(str resource):
|
||||
"""The resourceprep profile of stringprep, which is used to validate the
|
||||
resource portion of a JID."""
|
||||
return _stringprep(resource, 'Resourceprep')
|
||||
|
||||
|
||||
def idna(str domain):
|
||||
"""The idna conversion functions, which are used to validate the domain
|
||||
portion of a JID."""
|
||||
|
@ -69,3 +73,17 @@ def idna(str domain):
|
|||
unicode_domain = utf8_domain.decode('utf-8')
|
||||
free(utf8_domain)
|
||||
return unicode_domain
|
||||
|
||||
|
||||
def punycode(str domain):
|
||||
"""Converts a domain name to its punycode representation."""
|
||||
|
||||
cdef char* ascii_domain
|
||||
cdef bytes bytes_domain
|
||||
|
||||
ret = idna_to_ascii_8z(domain.encode('utf-8'), &ascii_domain, 0)
|
||||
if ret != 0:
|
||||
raise StringprepError(ret)
|
||||
bytes_domain = ascii_domain
|
||||
free(ascii_domain)
|
||||
return bytes_domain
|
||||
|
|
Loading…
Reference in a new issue