import sys
import copy
import encodings.idna
+try:
+ import idna
+ have_idna_2008 = True
+except ImportError:
+ have_idna_2008 = False
import dns.exception
import dns.wiredata
text += u'\\%03d' % ord(c)
return text
+def _idna_encode(label, uts46, std3_rules, transitional):
+ if label == '':
+ return b''
+ if have_idna_2008:
+ if uts46:
+ label = idna.uts46_remap(label, std3_rules, transitional)
+ label = idna.alabel(label)
+ else:
+ try:
+ label = encodings.idna.ToASCII(label)
+ except UnicodeError:
+ raise LabelTooLong
+ return label
+
+def _idna_decode(label, uts46, std3_rules):
+ if label == b'':
+ return u''
+ if have_idna_2008:
+ if uts46:
+ label = idna.uts46_remap(label, std3_rules, False)
+ label = idna.ulabel(label)
+ else:
+ label = encodings.idna.ToUnicode(label)
+ return _escapify(label, True)
def _validate_labels(labels):
"""Check for empty labels in the middle of a label sequence,
s = b'.'.join(map(_escapify, l))
return s
- def to_unicode(self, omit_final_dot=False):
+ def to_unicode(self, omit_final_dot=False, uts46=False,
+ std3_rules=False):
"""Convert name to Unicode text format.
IDN ACE labels are converted to Unicode.
l = self.labels[:-1]
else:
l = self.labels
- s = u'.'.join([_escapify(encodings.idna.ToUnicode(x), True)
- for x in l])
- return s
+ return u'.'.join([_idna_decode(x, uts46, std3_rules) for x in l])
def to_digestable(self, origin=None):
"""Convert name to a format suitable for digesting in hashes.
empty = Name([])
-def from_unicode(text, origin=root):
+def from_unicode(text, origin=root, uts46=False, std3_rules=False,
+ transitional=False):
"""Convert unicode text into a Name object.
Labels are encoded in IDN ACE form.
elif c in [u'.', u'\u3002', u'\uff0e', u'\uff61']:
if len(label) == 0:
raise EmptyLabel
- try:
- labels.append(encodings.idna.ToASCII(label))
- except UnicodeError:
- raise LabelTooLong
+ labels.append(_idna_encode(label, uts46, std3_rules,
+ transitional))
label = u''
elif c == u'\\':
escaping = True
if escaping:
raise BadEscape
if len(label) > 0:
- try:
- labels.append(encodings.idna.ToASCII(label))
- except UnicodeError:
- raise LabelTooLong
+ labels.append(_idna_encode(label, uts46, std3_rules,
+ transitional))
else:
labels.append(b'')
return Name(labels)
-def from_text(text, origin=root):
+def from_text(text, origin=root, uts46=False, std3_rules=False,
+ transitional=False):
"""Convert text into a Name object.
@rtype: dns.name.Name object
"""
if isinstance(text, text_type):
- return from_unicode(text, origin)
+ return from_unicode(text, origin, uts46, std3_rules, transitional)
if not isinstance(text, binary_type):
raise ValueError("input to from_text() must be a string")
if not (origin is None or isinstance(origin, Name)):
+# -*- coding: utf-8
# Copyright (C) 2003-2007, 2009-2011 Nominum, Inc.
#
# Permission to use, copy, modify, and distribute this software and its
import dns.reversename
import dns.e164
+if dns.name.have_idna_2008:
+ import idna
+dns.name.have_idna_2008 = False # XXXRTH
+
# pylint: disable=line-too-long
def testToText9(self):
n = dns.name.from_text('FOO bar', origin=None)
- t = n.to_unicode()
- self.assertEqual(t, r'FOO\032bar')
+ if dns.name.have_idna_2008:
+ def bad():
+ return n.to_unicode()
+ self.failUnlessRaises(idna.InvalidCodepoint, bad)
+ else:
+ t = n.to_unicode()
+ self.assertEqual(t, r'FOO\032bar')
def testToText10(self):
t = dns.name.empty.to_unicode()
n = dns.name.from_text(u'foo\uff61bar')
self.assertEqual(n.labels, (b'foo', b'bar', b''))
+ def testFromUnicodeIDNA2008(self):
+ if dns.name.have_idna_2008:
+ t = u'Königsgäßchen'
+ def bad():
+ return dns.name.from_unicode(t)
+ self.failUnlessRaises(idna.InvalidCodepoint, bad)
+ e1 = dns.name.from_unicode(t, uts46=True)
+ self.assertEqual(str(e1), b'xn--knigsgchen-b4a3dun.')
+ e2 = dns.name.from_unicode(t, uts46=True, transitional=True)
+ self.assertEqual(str(e2), b'xn--knigsgsschen-lcb0w.')
+
def testToUnicode1(self):
n = dns.name.from_text(u'foo.bar')
s = n.to_unicode()
s = n.to_unicode()
self.assertEqual(s, u'foo.bar.')
+ def testToUnicode4(self):
+ if dns.name.have_idna_2008:
+ n = dns.name.from_text(u'ドメイン.テスト')
+ s = n.to_unicode()
+ self.assertEqual(str(n), b'xn--eckwd4c7c.xn--zckzah.')
+ self.assertEqual(s, u'ドメイン.テスト.')
+
def testReverseIPv4(self):
e = dns.name.from_text('1.0.0.127.in-addr.arpa.')
n = dns.reversename.from_address('127.0.0.1')