From: Bob Halley Date: Sun, 6 Jan 2019 21:22:25 +0000 (-0800) Subject: If there are no non-ASCII codepoints in the input, treat the name as X-Git-Tag: v2.0.0rc1~377 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=dda972af4c15baf963e42c2869b1114a5cf5e31f;p=thirdparty%2Fdnspython.git If there are no non-ASCII codepoints in the input, treat the name as an ordinary domain name in from_text and do NOT apply any IDNA. This makes non-Unicode binary names like \150\151\152\153\154\155\156\157\158\159. work properly again. [Issue #270] --- diff --git a/dns/name.py b/dns/name.py index cd465cd5..a9fc177b 100644 --- a/dns/name.py +++ b/dns/name.py @@ -111,12 +111,6 @@ class IDNACodec(object): def is_idna(self, label): return label.lower().startswith(b'xn--') - def is_all_ascii(self, label): - for c in label: - if ord(c) > 0x7f: - return False - return True - def encode(self, label): raise NotImplementedError @@ -204,7 +198,7 @@ class IDNA2008Codec(IDNACodec): def encode(self, label): if label == '': return b'' - if self.allow_pure_ascii and self.is_all_ascii(label): + if self.allow_pure_ascii and is_all_ascii(label): return label.encode('ascii') if not have_idna_2008: raise NoIDNA2008 @@ -868,6 +862,11 @@ def from_unicode(text, origin=root, idna_codec=None): labels.extend(list(origin.labels)) return Name(labels) +def is_all_ascii(text): + for c in text: + if ord(c) > 0x7f: + return False + return True def from_text(text, origin=root, idna_codec=None): """Convert text into a Name object. @@ -885,7 +884,18 @@ def from_text(text, origin=root, idna_codec=None): """ if isinstance(text, str): - return from_unicode(text, origin, idna_codec) + if not is_all_ascii(text): + # Some codepoint in the input text is > 127, so IDNA applies. + return from_unicode(text, origin, idna_codec) + # The input is all ASCII, so treat this like an ordinary non-IDNA + # domain name. Note that "all ASCII" is about the input text, + # not the codepoints in the domain name. E.g. if text has value + # + # r'\150\151\152\153\154\155\156\157\158\159' + # + # then it's still "all ASCII" even though the domain name has + # codepoints > 127. + text = text.encode('ascii') if not isinstance(text, bytes): raise ValueError("input to from_text() must be a string") if not (origin is None or isinstance(origin, Name)): diff --git a/tests/test_name.py b/tests/test_name.py index 02a67c28..bea30a2d 100644 --- a/tests/test_name.py +++ b/tests/test_name.py @@ -260,6 +260,18 @@ class NameTestCase(unittest.TestCase): t = n.to_unicode() self.assertEqual(t, r'a\.b.c.') + def testToText13(self): + n = dns.name.from_text(r'\150\151\152\153\154\155\156\157\158\159.') + t = n.to_text() + self.assertEqual(t, r'\150\151\152\153\154\155\156\157\158\159.') + + def testToText14(self): + # You can't send this to_unicode() as it wasn't unicode to begin with. + def bad(): + n = dns.name.from_text(r'\150\151\152\153\154\155\156\157\158\159.') + t = n.to_unicode() + self.failUnlessRaises(UnicodeDecodeError, bad) + def testSlice1(self): n = dns.name.from_text(r'a.b.c.', origin=None) s = n[:]