Add a function to convert a domain name to punycode.

This commit is contained in:
Emmanuel Gil Peyrot 2015-08-20 20:03:32 +01:00 committed by Emmanuel Gil Peyrot
parent a721084f6e
commit 041bd63864
2 changed files with 35 additions and 1 deletions

View file

@ -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.')

View file

@ -19,7 +19,8 @@ from libc.stdlib cimport free
# Those are Cython declarations for the C function well 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