diff options
Diffstat (limited to 'eventlet')
35 files changed, 289 insertions, 116 deletions
diff --git a/eventlet/support/dns/entropy.py b/eventlet/support/dns/entropy.py index 7a2d87d..de7a70a 100644 --- a/eventlet/support/dns/entropy.py +++ b/eventlet/support/dns/entropy.py @@ -70,14 +70,14 @@ class EntropyPool(object): if not self.seeded or self.seed_pid != os.getpid(): try: seed = os.urandom(16) - except: + except Exception: try: r = open('/dev/urandom', 'rb', 0) try: seed = r.read(16) finally: r.close() - except: + except Exception: seed = str(time.time()) self.seeded = True self.seed_pid = os.getpid() @@ -125,7 +125,7 @@ pool = EntropyPool() try: system_random = random.SystemRandom() -except: +except Exception: system_random = None def random_16(): diff --git a/eventlet/support/dns/exception.py b/eventlet/support/dns/exception.py index 151f584..6c0b1f4 100644 --- a/eventlet/support/dns/exception.py +++ b/eventlet/support/dns/exception.py @@ -23,14 +23,14 @@ class DNSException(Exception): It supports two basic modes of operation: a) Old/compatible mode is used if __init__ was called with - empty **kwargs. + empty **kwargs. In compatible mode all *args are passed to standard Python Exception class as before and all *args are printed by standard __str__ implementation. Class variable msg (or doc string if msg is None) is returned from str() if *args is empty. b) New/parametrized mode is used if __init__ was called with - non-empty **kwargs. + non-empty **kwargs. In the new mode *args has to be empty and all kwargs has to exactly match set in class variable self.supp_kwargs. All kwargs are stored inside self.kwargs and used in new __str__ implementation to construct diff --git a/eventlet/support/dns/inet.py b/eventlet/support/dns/inet.py index cc22e64..73490a9 100644 --- a/eventlet/support/dns/inet.py +++ b/eventlet/support/dns/inet.py @@ -85,7 +85,7 @@ def af_for_address(text): try: dns.ipv4.inet_aton(text) return AF_INET - except: + except Exception: try: dns.ipv6.inet_aton(text) return AF_INET6 @@ -103,9 +103,9 @@ def is_multicast(text): try: first = ord(dns.ipv4.inet_aton(text)[0]) return first >= 224 and first <= 239 - except: + except Exception: try: first = ord(dns.ipv6.inet_aton(text)[0]) return first == 255 - except: + except Exception: raise ValueError diff --git a/eventlet/support/dns/message.py b/eventlet/support/dns/message.py index ff0ea81..a0df18e 100644 --- a/eventlet/support/dns/message.py +++ b/eventlet/support/dns/message.py @@ -898,7 +898,7 @@ class _TextReader(object): raise dns.exception.SyntaxError except dns.exception.SyntaxError: raise dns.exception.SyntaxError - except: + except Exception: rdclass = dns.rdataclass.IN # Type rdtype = dns.rdatatype.from_text(token.value) @@ -931,7 +931,7 @@ class _TextReader(object): raise dns.exception.SyntaxError except dns.exception.SyntaxError: raise dns.exception.SyntaxError - except: + except Exception: ttl = 0 # Class try: @@ -944,7 +944,7 @@ class _TextReader(object): rdclass = self.zone_rdclass except dns.exception.SyntaxError: raise dns.exception.SyntaxError - except: + except Exception: rdclass = dns.rdataclass.IN # Type rdtype = dns.rdatatype.from_text(token.value) diff --git a/eventlet/support/dns/name.py b/eventlet/support/dns/name.py index ef812cf..758a394 100644 --- a/eventlet/support/dns/name.py +++ b/eventlet/support/dns/name.py @@ -26,6 +26,11 @@ import struct 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 @@ -34,7 +39,7 @@ from ._compat import long, binary_type, text_type, unichr try: maxint = sys.maxint -except: +except AttributeError: maxint = (1 << (8 * struct.calcsize("P"))) // 2 - 1 NAMERELN_NONE = 0 @@ -91,8 +96,115 @@ class NoParent(dns.exception.DNSException): """An attempt was made to get the parent of the root name or the empty name.""" +class NoIDNA2008(dns.exception.DNSException): + + """IDNA 2008 processing was requested but the idna module is not + available.""" + + +class IDNAException(dns.exception.DNSException): + + """IDNA 2008 processing raised an exception.""" + + supp_kwargs = set(['idna_exception']) + fmt = "IDNA processing exception: {idna_exception}" + +class IDNACodec(object): + + """Abstract base class for IDNA encoder/decoders.""" + + def encode(self, label): + raise NotImplementedError + + def decode(self, label): + raise NotImplementedError + +class IDNA2003Codec(IDNACodec): + + """IDNA 2003 encoder/decoder.""" + + def encode(self, label): + if label == '': + return b'' + try: + return encodings.idna.ToASCII(label) + except UnicodeError: + raise LabelTooLong + + def decode(self, label): + if label == b'': + return u'' + return _escapify(encodings.idna.ToUnicode(label), True) + +class IDNA2008Codec(IDNACodec): + + """IDNA 2008 encoder/decoder.""" + + def __init__(self, uts_46=False, transitional=False, + allow_pure_ascii=False): + """Initialize the IDNA 2008 encoder/decoder. + @param uts_46: If True, apply Unicode IDNA compatibility processing + as described in Unicode Technical Standard #46 + (U{http://unicode.org/reports/tr46/}). This parameter is only + meaningful if IDNA 2008 is in use. If False, do not apply + the mapping. The default is False + @type uts_46: bool + @param transitional: If True, use the "transitional" mode described + in Unicode Technical Standard #46. This parameter is only + meaningful if IDNA 2008 is in use. The default is False. + @type transitional: bool + @param allow_pure_ascii: If True, then a label which + consists of only ASCII characters is allowed. This is less strict + than regular IDNA 2008, but is also necessary for mixed names, + e.g. a name with starting with "_sip._tcp." and ending in an IDN + suffixm which would otherwise be disallowed. The default is False + @type allow_pure_ascii: bool + """ + self.uts_46 = uts_46 + self.transitional = transitional + self.allow_pure_ascii = allow_pure_ascii + + def is_all_ascii(self, label): + for c in label: + if ord(c) > 0x7f: + return False + return True + + def encode(self, label): + if label == '': + return b'' + if self.allow_pure_ascii and self.is_all_ascii(label): + return label.encode('ascii') + if not have_idna_2008: + raise NoIDNA2008 + try: + if self.uts_46: + label = idna.uts46_remap(label, False, self.transitional) + return idna.alabel(label) + except idna.IDNAError as e: + raise IDNAException(idna_exception=e) + + def decode(self, label): + if label == b'': + return u'' + if not have_idna_2008: + raise NoIDNA2008 + try: + if self.uts_46: + label = idna.uts46_remap(label, False, False) + return _escapify(idna.ulabel(label), True) + except idna.IDNAError as e: + raise IDNAException(idna_exception=e) + + _escaped = bytearray(b'"().;\\@$') +IDNA_2003 = IDNA2003Codec() +IDNA_2008_Practical = IDNA2008Codec(True, False, True) +IDNA_2008_UTS_46 = IDNA2008Codec(True, False, False) +IDNA_2008_Strict = IDNA2008Codec(False, False, False) +IDNA_2008_Transitional = IDNA2008Codec(True, True, False) +IDNA_2008 = IDNA_2008_Practical def _escapify(label, unicode_mode=False): """Escape the characters in label which need it. @@ -126,7 +238,6 @@ def _escapify(label, unicode_mode=False): text += u'\\%03d' % ord(c) return text - def _validate_labels(labels): """Check for empty labels in the middle of a label sequence, labels that are too long, and for too many labels. @@ -375,13 +486,18 @@ class Name(object): s = b'.'.join(map(_escapify, l)) return s - def to_unicode(self, omit_final_dot=False): + def to_unicode(self, omit_final_dot=False, idna_codec=None): """Convert name to Unicode text format. IDN ACE labels are converted to Unicode. @param omit_final_dot: If True, don't emit the final dot (denoting the root label) for absolute names. The default is False. + @type omit_final_dot: bool + @param: idna_codec: IDNA encoder/decoder. If None, the default IDNA + 2003 + encoder/decoder is used. + @type idna_codec: dns.name.IDNA @rtype: string """ @@ -393,9 +509,9 @@ class Name(object): l = self.labels[:-1] else: l = self.labels - s = u'.'.join([_escapify(encodings.idna.ToUnicode(x), True) - for x in l]) - return s + if idna_codec is None: + idna_codec = IDNA_2003 + return u'.'.join([idna_codec.decode(x) for x in l]) def to_digestable(self, origin=None): """Convert name to a format suitable for digesting in hashes. @@ -488,9 +604,6 @@ class Name(object): def __getitem__(self, index): return self.labels[index] - def __getslice__(self, start, stop): - return self.labels[start:stop] - def __add__(self, other): return self.concatenate(other) @@ -583,11 +696,18 @@ root = Name([b'']) empty = Name([]) -def from_unicode(text, origin=root): +def from_unicode(text, origin=root, idna_codec=None): """Convert unicode text into a Name object. Labels are encoded in IDN ACE form. + @param text: The text to convert into a name. + @type text: Unicode string + @param origin: The origin to append to non-absolute names. + @type origin: dns.name.Name + @param: idna_codec: IDNA encoder/decoder. If None, the default IDNA 2003 + encoder/decoder is used. + @type idna_codec: dns.name.IDNA @rtype: dns.name.Name object """ @@ -600,6 +720,8 @@ def from_unicode(text, origin=root): escaping = False edigits = 0 total = 0 + if idna_codec is None: + idna_codec = IDNA_2003 if text == u'@': text = u'' if text: @@ -626,10 +748,7 @@ def from_unicode(text, origin=root): 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_codec.encode(label)) label = u'' elif c == u'\\': escaping = True @@ -640,10 +759,7 @@ def from_unicode(text, origin=root): if escaping: raise BadEscape if len(label) > 0: - try: - labels.append(encodings.idna.ToASCII(label)) - except UnicodeError: - raise LabelTooLong + labels.append(idna_codec.encode(label)) else: labels.append(b'') @@ -652,13 +768,21 @@ def from_unicode(text, origin=root): return Name(labels) -def from_text(text, origin=root): +def from_text(text, origin=root, idna_codec=None): """Convert text into a Name object. + + @param text: The text to convert into a name. + @type text: string + @param origin: The origin to append to non-absolute names. + @type origin: dns.name.Name + @param: idna_codec: IDNA encoder/decoder. If None, the default IDNA 2003 + encoder/decoder is used. + @type idna_codec: dns.name.IDNA @rtype: dns.name.Name object """ if isinstance(text, text_type): - return from_unicode(text, origin) + return from_unicode(text, origin, idna_codec) 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)): diff --git a/eventlet/support/dns/query.py b/eventlet/support/dns/query.py index 6b76b42..bfecd43 100644 --- a/eventlet/support/dns/query.py +++ b/eventlet/support/dns/query.py @@ -176,7 +176,7 @@ def _destination_and_source(af, where, port, source, source_port): if af is None: try: af = dns.inet.af_for_address(where) - except: + except Exception: af = dns.inet.AF_INET if af == dns.inet.AF_INET: destination = (where, port) diff --git a/eventlet/support/dns/rdatatype.py b/eventlet/support/dns/rdatatype.py index cde1a0a..15284f6 100644 --- a/eventlet/support/dns/rdatatype.py +++ b/eventlet/support/dns/rdatatype.py @@ -96,6 +96,7 @@ MAILA = 254 ANY = 255 URI = 256 CAA = 257 +AVC = 258 TA = 32768 DLV = 32769 @@ -166,6 +167,7 @@ _by_text = { 'ANY': ANY, 'URI': URI, 'CAA': CAA, + 'AVC': AVC, 'TA': TA, 'DLV': DLV, } diff --git a/eventlet/support/dns/rdtypes/ANY/AVC.py b/eventlet/support/dns/rdtypes/ANY/AVC.py new file mode 100644 index 0000000..137c9de --- /dev/null +++ b/eventlet/support/dns/rdtypes/ANY/AVC.py @@ -0,0 +1,23 @@ +# Copyright (C) 2016 Nominum, Inc. +# +# Permission to use, copy, modify, and distribute this software and its +# documentation for any purpose with or without fee is hereby granted, +# provided that the above copyright notice and this permission notice +# appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT +# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +import dns.rdtypes.txtbase + + +class AVC(dns.rdtypes.txtbase.TXTBase): + + """AVC record + + @see: U{http://www.iana.org/assignments/dns-parameters/AVC/avc-completed-template}""" diff --git a/eventlet/support/dns/rdtypes/ANY/CAA.py b/eventlet/support/dns/rdtypes/ANY/CAA.py index e80d469..f2e41ad 100644 --- a/eventlet/support/dns/rdtypes/ANY/CAA.py +++ b/eventlet/support/dns/rdtypes/ANY/CAA.py @@ -71,4 +71,3 @@ class CAA(dns.rdata.Rdata): tag = wire[current: current + l] value = wire[current + l:current + rdlen - 2] return cls(rdclass, rdtype, flags, tag, value) - diff --git a/eventlet/support/dns/rdtypes/ANY/CERT.py b/eventlet/support/dns/rdtypes/ANY/CERT.py index b745440..1c35c23 100644 --- a/eventlet/support/dns/rdtypes/ANY/CERT.py +++ b/eventlet/support/dns/rdtypes/ANY/CERT.py @@ -119,4 +119,3 @@ class CERT(dns.rdata.Rdata): certificate = wire[current: current + rdlen].unwrap() return cls(rdclass, rdtype, certificate_type, key_tag, algorithm, certificate) - diff --git a/eventlet/support/dns/rdtypes/ANY/HINFO.py b/eventlet/support/dns/rdtypes/ANY/HINFO.py index 52298bc..e5a1bea 100644 --- a/eventlet/support/dns/rdtypes/ANY/HINFO.py +++ b/eventlet/support/dns/rdtypes/ANY/HINFO.py @@ -82,4 +82,3 @@ class HINFO(dns.rdata.Rdata): raise dns.exception.FormError os = wire[current: current + l].unwrap() return cls(rdclass, rdtype, cpu, os) - diff --git a/eventlet/support/dns/rdtypes/ANY/ISDN.py b/eventlet/support/dns/rdtypes/ANY/ISDN.py index 01284a8..da2ae3a 100644 --- a/eventlet/support/dns/rdtypes/ANY/ISDN.py +++ b/eventlet/support/dns/rdtypes/ANY/ISDN.py @@ -95,4 +95,3 @@ class ISDN(dns.rdata.Rdata): else: subaddress = '' return cls(rdclass, rdtype, address, subaddress) - diff --git a/eventlet/support/dns/rdtypes/ANY/LOC.py b/eventlet/support/dns/rdtypes/ANY/LOC.py index f2544c3..b433da9 100644 --- a/eventlet/support/dns/rdtypes/ANY/LOC.py +++ b/eventlet/support/dns/rdtypes/ANY/LOC.py @@ -138,16 +138,12 @@ class LOC(dns.rdata.Rdata): def to_text(self, origin=None, relativize=True, **kw): if self.latitude[4] > 0: lat_hemisphere = 'N' - lat_degrees = self.latitude[0] else: lat_hemisphere = 'S' - lat_degrees = -1 * self.latitude[0] if self.longitude[4] > 0: long_hemisphere = 'E' - long_degrees = self.longitude[0] else: long_hemisphere = 'W' - long_degrees = -1 * self.longitude[0] text = "%d %d %d.%03d %s %d %d %d.%03d %s %0.2fm" % ( self.latitude[0], self.latitude[1], self.latitude[2], self.latitude[3], lat_hemisphere, diff --git a/eventlet/support/dns/rdtypes/ANY/NSEC3.py b/eventlet/support/dns/rdtypes/ANY/NSEC3.py index 3982f4b..9a15687 100644 --- a/eventlet/support/dns/rdtypes/ANY/NSEC3.py +++ b/eventlet/support/dns/rdtypes/ANY/NSEC3.py @@ -189,4 +189,3 @@ class NSEC3(dns.rdata.Rdata): windows.append((window, bitmap)) return cls(rdclass, rdtype, algorithm, flags, iterations, salt, next, windows) - diff --git a/eventlet/support/dns/rdtypes/ANY/NSEC3PARAM.py b/eventlet/support/dns/rdtypes/ANY/NSEC3PARAM.py index b506282..36bf740 100644 --- a/eventlet/support/dns/rdtypes/ANY/NSEC3PARAM.py +++ b/eventlet/support/dns/rdtypes/ANY/NSEC3PARAM.py @@ -86,4 +86,3 @@ class NSEC3PARAM(dns.rdata.Rdata): if rdlen != 0: raise dns.exception.FormError return cls(rdclass, rdtype, algorithm, flags, iterations, salt) - diff --git a/eventlet/support/dns/rdtypes/ANY/SSHFP.py b/eventlet/support/dns/rdtypes/ANY/SSHFP.py index b6ed396..7e846b3 100644 --- a/eventlet/support/dns/rdtypes/ANY/SSHFP.py +++ b/eventlet/support/dns/rdtypes/ANY/SSHFP.py @@ -75,4 +75,3 @@ class SSHFP(dns.rdata.Rdata): rdlen -= 2 fingerprint = wire[current: current + rdlen].unwrap() return cls(rdclass, rdtype, header[0], header[1], fingerprint) - diff --git a/eventlet/support/dns/rdtypes/ANY/TLSA.py b/eventlet/support/dns/rdtypes/ANY/TLSA.py index 23f4e94..790a93b 100644 --- a/eventlet/support/dns/rdtypes/ANY/TLSA.py +++ b/eventlet/support/dns/rdtypes/ANY/TLSA.py @@ -80,4 +80,3 @@ class TLSA(dns.rdata.Rdata): rdlen -= 3 cert = wire[current: current + rdlen].unwrap() return cls(rdclass, rdtype, header[0], header[1], header[2], cert) - diff --git a/eventlet/support/dns/rdtypes/ANY/URI.py b/eventlet/support/dns/rdtypes/ANY/URI.py index 0c121d2..b5595b5 100644 --- a/eventlet/support/dns/rdtypes/ANY/URI.py +++ b/eventlet/support/dns/rdtypes/ANY/URI.py @@ -78,4 +78,3 @@ class URI(dns.rdata.Rdata): current += rdlen return cls(rdclass, rdtype, priority, weight, target) - diff --git a/eventlet/support/dns/rdtypes/ANY/X25.py b/eventlet/support/dns/rdtypes/ANY/X25.py index f5cca11..8732ccf 100644 --- a/eventlet/support/dns/rdtypes/ANY/X25.py +++ b/eventlet/support/dns/rdtypes/ANY/X25.py @@ -62,4 +62,3 @@ class X25(dns.rdata.Rdata): raise dns.exception.FormError address = wire[current: current + l].unwrap() return cls(rdclass, rdtype, address) - diff --git a/eventlet/support/dns/rdtypes/IN/A.py b/eventlet/support/dns/rdtypes/IN/A.py index 42faf9b..3775548 100644 --- a/eventlet/support/dns/rdtypes/IN/A.py +++ b/eventlet/support/dns/rdtypes/IN/A.py @@ -50,4 +50,3 @@ class A(dns.rdata.Rdata): def from_wire(cls, rdclass, rdtype, wire, current, rdlen, origin=None): address = dns.ipv4.inet_ntoa(wire[current: current + rdlen]).decode() return cls(rdclass, rdtype, address) - diff --git a/eventlet/support/dns/rdtypes/IN/AAAA.py b/eventlet/support/dns/rdtypes/IN/AAAA.py index d2c65c6..4352404 100644 --- a/eventlet/support/dns/rdtypes/IN/AAAA.py +++ b/eventlet/support/dns/rdtypes/IN/AAAA.py @@ -51,4 +51,3 @@ class AAAA(dns.rdata.Rdata): address = dns.inet.inet_ntop(dns.inet.AF_INET6, wire[current: current + rdlen]) return cls(rdclass, rdtype, address) - diff --git a/eventlet/support/dns/rdtypes/IN/APL.py b/eventlet/support/dns/rdtypes/IN/APL.py index 698dde7..57ef6c0 100644 --- a/eventlet/support/dns/rdtypes/IN/APL.py +++ b/eventlet/support/dns/rdtypes/IN/APL.py @@ -159,4 +159,3 @@ class APL(dns.rdata.Rdata): item = APLItem(header[0], negation, address, header[1]) items.append(item) return cls(rdclass, rdtype, items) - diff --git a/eventlet/support/dns/rdtypes/IN/DHCID.py b/eventlet/support/dns/rdtypes/IN/DHCID.py index 06a850a..5b8626a 100644 --- a/eventlet/support/dns/rdtypes/IN/DHCID.py +++ b/eventlet/support/dns/rdtypes/IN/DHCID.py @@ -57,4 +57,3 @@ class DHCID(dns.rdata.Rdata): def from_wire(cls, rdclass, rdtype, wire, current, rdlen, origin=None): data = wire[current: current + rdlen].unwrap() return cls(rdclass, rdtype, data) - diff --git a/eventlet/support/dns/rdtypes/IN/IPSECKEY.py b/eventlet/support/dns/rdtypes/IN/IPSECKEY.py index 4f07bd0..c673e83 100644 --- a/eventlet/support/dns/rdtypes/IN/IPSECKEY.py +++ b/eventlet/support/dns/rdtypes/IN/IPSECKEY.py @@ -146,4 +146,3 @@ class IPSECKEY(dns.rdata.Rdata): key = wire[current: current + rdlen].unwrap() return cls(rdclass, rdtype, header[0], gateway_type, header[2], gateway, key) - diff --git a/eventlet/support/dns/rdtypes/IN/NSAP.py b/eventlet/support/dns/rdtypes/IN/NSAP.py index 6dbe5af..05d0745 100644 --- a/eventlet/support/dns/rdtypes/IN/NSAP.py +++ b/eventlet/support/dns/rdtypes/IN/NSAP.py @@ -56,4 +56,3 @@ class NSAP(dns.rdata.Rdata): def from_wire(cls, rdclass, rdtype, wire, current, rdlen, origin=None): address = wire[current: current + rdlen].unwrap() return cls(rdclass, rdtype, address) - diff --git a/eventlet/support/dns/rdtypes/IN/WKS.py b/eventlet/support/dns/rdtypes/IN/WKS.py index da2a2d8..1d4012c 100644 --- a/eventlet/support/dns/rdtypes/IN/WKS.py +++ b/eventlet/support/dns/rdtypes/IN/WKS.py @@ -103,4 +103,3 @@ class WKS(dns.rdata.Rdata): rdlen -= 5 bitmap = wire[current: current + rdlen].unwrap() return cls(rdclass, rdtype, address, protocol, bitmap) - diff --git a/eventlet/support/dns/rdtypes/dsbase.py b/eventlet/support/dns/rdtypes/dsbase.py index 80f792a..1ee28e4 100644 --- a/eventlet/support/dns/rdtypes/dsbase.py +++ b/eventlet/support/dns/rdtypes/dsbase.py @@ -81,4 +81,3 @@ class DSBase(dns.rdata.Rdata): rdlen -= 4 digest = wire[current: current + rdlen].unwrap() return cls(rdclass, rdtype, header[0], header[1], header[2], digest) - diff --git a/eventlet/support/dns/rdtypes/euibase.py b/eventlet/support/dns/rdtypes/euibase.py index c7d0045..cc5fdaa 100644 --- a/eventlet/support/dns/rdtypes/euibase.py +++ b/eventlet/support/dns/rdtypes/euibase.py @@ -69,4 +69,3 @@ class EUIBase(dns.rdata.Rdata): def from_wire(cls, rdclass, rdtype, wire, current, rdlen, origin=None): eui = wire[current:current + rdlen].unwrap() return cls(rdclass, rdtype, eui) - diff --git a/eventlet/support/dns/rdtypes/txtbase.py b/eventlet/support/dns/rdtypes/txtbase.py index 54d7e6f..352b027 100644 --- a/eventlet/support/dns/rdtypes/txtbase.py +++ b/eventlet/support/dns/rdtypes/txtbase.py @@ -88,4 +88,3 @@ class TXTBase(dns.rdata.Rdata): rdlen -= l strings.append(s) return cls(rdclass, rdtype, strings) - diff --git a/eventlet/support/dns/resolver.py b/eventlet/support/dns/resolver.py index 5bd1e8d..abc431d 100644 --- a/eventlet/support/dns/resolver.py +++ b/eventlet/support/dns/resolver.py @@ -135,8 +135,9 @@ class NoNameservers(dns.exception.DNSException): """All nameservers failed to answer the query. - @param errors: list of servers and respective errors - @type errors: [(server ip address, any object convertible to string)] + errors: list of servers and respective errors + The type of errors is + [(server ip address, any object convertible to string)]. Non-empty errors list will add explanatory message () """ @@ -271,10 +272,10 @@ class Answer(object): raise AttributeError(attr) def __len__(self): - return len(self.rrset) + return self.rrset and len(self.rrset) or 0 def __iter__(self): - return iter(self.rrset) + return self.rrset and iter(self.rrset) or iter(tuple()) def __getitem__(self, i): return self.rrset[i] @@ -282,9 +283,6 @@ class Answer(object): def __delitem__(self, i): del self.rrset[i] - def __getslice__(self, i, j): - return self.rrset[i:j] - class Cache(object): @@ -434,7 +432,7 @@ class LRUCache(object): """Initialize a DNS cache. @param max_size: The maximum number of nodes to cache; the default is - 100000. Must be > 1. + 100,000. Must be greater than 1. @type max_size: int """ self.data = {} @@ -581,6 +579,24 @@ class Resolver(object): POSIX systems and from the registry on Windows systems.) @type configure: bool""" + self.domain = None + self.nameservers = None + self.nameserver_ports = None + self.port = None + self.search = None + self.timeout = None + self.lifetime = None + self.keyring = None + self.keyname = None + self.keyalgorithm = None + self.edns = None + self.ednsflags = None + self.payload = None + self.cache = None + self.flags = None + self.retry_servfail = False + self.rotate = False + self.reset() if configure: if sys.platform == 'win32': @@ -901,12 +917,13 @@ class Resolver(object): all_nxdomain = True nxdomain_responses = {} start = time.time() + _qname = None # make pylint happy for _qname in qnames_to_try: if self.cache: answer = self.cache.get((_qname, rdtype, rdclass)) if answer is not None: if answer.rrset is None and raise_on_no_answer: - raise NoAnswer + raise NoAnswer(response=answer.response) else: return answer request = dns.message.make_query(_qname, rdtype, rdclass) @@ -1032,10 +1049,10 @@ class Resolver(object): break if all_nxdomain: raise NXDOMAIN(qnames=qnames_to_try, responses=nxdomain_responses) - answer = Answer(qname, rdtype, rdclass, response, + answer = Answer(_qname, rdtype, rdclass, response, raise_on_no_answer) if self.cache: - self.cache.put((qname, rdtype, rdclass), answer) + self.cache.put((_qname, rdtype, rdclass), answer) return answer def use_tsig(self, keyring, keyname=None, @@ -1194,13 +1211,13 @@ def _getaddrinfo(host=None, service=None, family=socket.AF_UNSPEC, socktype=0, addr = dns.ipv6.inet_aton(ahost) v6addrs.append(host) canonical_name = host - except: + except Exception: try: # Is it a V4 address literal? addr = dns.ipv4.inet_aton(host) v4addrs.append(host) canonical_name = host - except: + except Exception: if flags & socket.AI_NUMERICHOST == 0: try: if family == socket.AF_INET6 or family == socket.AF_UNSPEC: @@ -1232,11 +1249,11 @@ def _getaddrinfo(host=None, service=None, family=socket.AF_UNSPEC, socktype=0, port = 0 else: port = int(service) - except: + except Exception: if flags & socket.AI_NUMERICSERV == 0: try: port = socket.getservbyname(service) - except: + except Exception: pass if port is None: raise socket.gaierror(socket.EAI_NONAME) @@ -1311,7 +1328,7 @@ def _getfqdn(name=None): name = socket.gethostname() try: return _getnameinfo(_getaddrinfo(name, 80)[0][4])[0] - except: + except Exception: return name @@ -1336,7 +1353,7 @@ def _gethostbyaddr(ip): dns.ipv6.inet_aton(ip) sockaddr = (ip, 80, 0, 0) family = socket.AF_INET6 - except: + except Exception: sockaddr = (ip, 80) family = socket.AF_INET (name, port) = _getnameinfo(sockaddr, socket.NI_NAMEREQD) diff --git a/eventlet/support/dns/reversename.py b/eventlet/support/dns/reversename.py index a27e705..9ea9395 100644 --- a/eventlet/support/dns/reversename.py +++ b/eventlet/support/dns/reversename.py @@ -51,7 +51,7 @@ def from_address(text): else: parts = [x for x in str(binascii.hexlify(v6).decode())] origin = ipv6_reverse_domain - except: + except Exception: parts = ['%d' % byte for byte in bytearray(dns.ipv4.inet_aton(text))] origin = ipv4_reverse_domain diff --git a/eventlet/support/dns/rrset.py b/eventlet/support/dns/rrset.py index 6ad71da..d0f8f93 100644 --- a/eventlet/support/dns/rrset.py +++ b/eventlet/support/dns/rrset.py @@ -119,7 +119,8 @@ class RRset(dns.rdataset.Rdataset): return dns.rdataset.from_rdata_list(self.ttl, list(self)) -def from_text_list(name, ttl, rdclass, rdtype, text_rdatas): +def from_text_list(name, ttl, rdclass, rdtype, text_rdatas, + idna_codec=None): """Create an RRset with the specified name, TTL, class, and type, and with the specified list of rdatas in text format. @@ -127,7 +128,7 @@ def from_text_list(name, ttl, rdclass, rdtype, text_rdatas): """ if isinstance(name, string_types): - name = dns.name.from_text(name, None) + name = dns.name.from_text(name, None, idna_codec=idna_codec) if isinstance(rdclass, string_types): rdclass = dns.rdataclass.from_text(rdclass) if isinstance(rdtype, string_types): @@ -150,7 +151,7 @@ def from_text(name, ttl, rdclass, rdtype, *text_rdatas): return from_text_list(name, ttl, rdclass, rdtype, text_rdatas) -def from_rdata_list(name, ttl, rdatas): +def from_rdata_list(name, ttl, rdatas, idna_codec=None): """Create an RRset with the specified name and TTL, and with the specified list of rdata objects. @@ -158,7 +159,7 @@ def from_rdata_list(name, ttl, rdatas): """ if isinstance(name, string_types): - name = dns.name.from_text(name, None) + name = dns.name.from_text(name, None, idna_codec=idna_codec) if len(rdatas) == 0: raise ValueError("rdata list must not be empty") diff --git a/eventlet/support/dns/set.py b/eventlet/support/dns/set.py index 0efc7d9..ef7fd29 100644 --- a/eventlet/support/dns/set.py +++ b/eventlet/support/dns/set.py @@ -232,9 +232,6 @@ class Set(object): def __delitem__(self, i): del self.items[i] - def __getslice__(self, i, j): - return self.items[i:j] - def issubset(self, other): """Is I{self} a subset of I{other}? diff --git a/eventlet/support/dns/wiredata.py b/eventlet/support/dns/wiredata.py index b381f7b..ccef595 100644 --- a/eventlet/support/dns/wiredata.py +++ b/eventlet/support/dns/wiredata.py @@ -15,6 +15,7 @@ """DNS Wire Data Helper""" +import sys import dns.exception from ._compat import binary_type, string_types @@ -26,12 +27,16 @@ from ._compat import binary_type, string_types # out what constant Python will use. -class _SliceUnspecifiedBound(str): +class _SliceUnspecifiedBound(binary_type): - def __getslice__(self, i, j): - return j + def __getitem__(self, key): + return key.stop + + if sys.version_info < (3,): + def __getslice__(self, i, j): # pylint: disable=getslice-method + return self.__getitem__(slice(i, j)) -_unspecified_bound = _SliceUnspecifiedBound('')[1:] +_unspecified_bound = _SliceUnspecifiedBound()[1:] class WireData(binary_type): @@ -40,26 +45,40 @@ class WireData(binary_type): def __getitem__(self, key): try: if isinstance(key, slice): - return WireData(super(WireData, self).__getitem__(key)) + # make sure we are not going outside of valid ranges, + # do stricter control of boundaries than python does + # by default + start = key.start + stop = key.stop + + if sys.version_info < (3,): + if stop == _unspecified_bound: + # handle the case where the right bound is unspecified + stop = len(self) + + if start < 0 or stop < 0: + raise dns.exception.FormError + # If it's not an empty slice, access left and right bounds + # to make sure they're valid + if start != stop: + super(WireData, self).__getitem__(start) + super(WireData, self).__getitem__(stop - 1) + else: + for index in (start, stop): + if index is None: + continue + elif abs(index) > len(self): + raise dns.exception.FormError + + return WireData(super(WireData, self).__getitem__( + slice(start, stop))) return bytearray(self.unwrap())[key] except IndexError: raise dns.exception.FormError - def __getslice__(self, i, j): - try: - if j == _unspecified_bound: - # handle the case where the right bound is unspecified - j = len(self) - if i < 0 or j < 0: - raise dns.exception.FormError - # If it's not an empty slice, access left and right bounds - # to make sure they're valid - if i != j: - super(WireData, self).__getitem__(i) - super(WireData, self).__getitem__(j - 1) - return WireData(super(WireData, self).__getslice__(i, j)) - except IndexError: - raise dns.exception.FormError + if sys.version_info < (3,): + def __getslice__(self, i, j): # pylint: disable=getslice-method + return self.__getitem__(slice(i, j)) def __iter__(self): i = 0 diff --git a/eventlet/support/dns/zone.py b/eventlet/support/dns/zone.py index 4a73e1e..468618f 100644 --- a/eventlet/support/dns/zone.py +++ b/eventlet/support/dns/zone.py @@ -19,6 +19,7 @@ from __future__ import generators import sys import re +import os from io import BytesIO import dns.exception @@ -498,18 +499,27 @@ class Zone(object): @type nl: string or None """ - str_type = string_types + if isinstance(f, string_types): + f = open(f, 'wb') + want_close = True + else: + want_close = False + + # must be in this way, f.encoding may contain None, or even attribute + # may not be there + file_enc = getattr(f, 'encoding', None) + if file_enc is None: + file_enc = 'utf-8' if nl is None: - opts = 'wb' + nl_b = os.linesep.encode(file_enc) # binary mode, '\n' is not enough + nl = u'\n' + elif isinstance(nl, string_types): + nl_b = nl.encode(file_enc) else: - opts = 'wb' + nl_b = nl + nl = nl.decode() - if isinstance(f, str_type): - f = open(f, opts) - want_close = True - else: - want_close = False try: if sorted: names = list(self.keys()) @@ -520,11 +530,15 @@ class Zone(object): l = self[n].to_text(n, origin=self.origin, relativize=relativize) if isinstance(l, text_type): - l = l.encode() - if nl is None: - f.write(l) - f.write('\n') + l_b = l.encode(file_enc) else: + l_b = l + l = l.decode() + + try: + f.write(l_b) + f.write(nl_b) + except TypeError: # textual mode f.write(l) f.write(nl) finally: @@ -658,7 +672,7 @@ class _MasterReader(object): raise dns.exception.SyntaxError except dns.exception.SyntaxError: raise dns.exception.SyntaxError - except: + except Exception: rdclass = self.zone.rdclass if rdclass != self.zone.rdclass: raise dns.exception.SyntaxError("RR class is not zone's class") @@ -777,7 +791,7 @@ class _MasterReader(object): raise dns.exception.SyntaxError except dns.exception.SyntaxError: raise dns.exception.SyntaxError - except: + except Exception: rdclass = self.zone.rdclass if rdclass != self.zone.rdclass: raise dns.exception.SyntaxError("RR class is not zone's class") @@ -787,7 +801,7 @@ class _MasterReader(object): token = self.tok.get() if not token.is_identifier(): raise dns.exception.SyntaxError - except: + except Exception: raise dns.exception.SyntaxError("unknown rdatatype '%s'" % token.value) |