133259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck# Copyright (C) 2001-2007, 2009, 2010 Nominum, Inc. 233259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck# 333259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck# Permission to use, copy, modify, and distribute this software and its 433259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck# documentation for any purpose with or without fee is hereby granted, 533259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck# provided that the above copyright notice and this permission notice 633259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck# appear in all copies. 733259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck# 833259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck# THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES 933259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 1033259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR 1133259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 1233259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 1333259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT 1433259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 1533259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck 1633259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck"""DNS Names. 1733259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck 1833259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck@var root: The DNS root name. 1933259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck@type root: dns.name.Name object 2033259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck@var empty: The empty DNS name. 2133259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck@type empty: dns.name.Name object 2233259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck""" 2333259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck 2433259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reckimport cStringIO 2533259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reckimport struct 2633259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reckimport sys 2733259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck 2833259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reckif sys.hexversion >= 0x02030000: 2933259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck import encodings.idna 3033259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck 3133259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reckimport dns.exception 3233259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck 3333259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John ReckNAMERELN_NONE = 0 3433259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John ReckNAMERELN_SUPERDOMAIN = 1 3533259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John ReckNAMERELN_SUBDOMAIN = 2 3633259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John ReckNAMERELN_EQUAL = 3 3733259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John ReckNAMERELN_COMMONANCESTOR = 4 3833259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck 3933259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reckclass EmptyLabel(dns.exception.SyntaxError): 4033259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck """Raised if a label is empty.""" 4133259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck pass 4233259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck 4333259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reckclass BadEscape(dns.exception.SyntaxError): 4433259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck """Raised if an escaped code in a text format name is invalid.""" 4533259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck pass 4633259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck 4733259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reckclass BadPointer(dns.exception.FormError): 4833259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck """Raised if a compression pointer points forward instead of backward.""" 4933259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck pass 5033259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck 5133259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reckclass BadLabelType(dns.exception.FormError): 5233259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck """Raised if the label type of a wire format name is unknown.""" 5333259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck pass 5433259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck 5533259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reckclass NeedAbsoluteNameOrOrigin(dns.exception.DNSException): 5633259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck """Raised if an attempt is made to convert a non-absolute name to 5733259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck wire when there is also a non-absolute (or missing) origin.""" 5833259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck pass 5933259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck 6033259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reckclass NameTooLong(dns.exception.FormError): 6133259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck """Raised if a name is > 255 octets long.""" 6233259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck pass 6333259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck 6433259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reckclass LabelTooLong(dns.exception.SyntaxError): 6533259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck """Raised if a label is > 63 octets long.""" 6633259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck pass 6733259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck 6833259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reckclass AbsoluteConcatenation(dns.exception.DNSException): 6933259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck """Raised if an attempt is made to append anything other than the 7033259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck empty name to an absolute name.""" 7133259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck pass 7233259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck 7333259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reckclass NoParent(dns.exception.DNSException): 7433259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck """Raised if an attempt is made to get the parent of the root name 7533259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck or the empty name.""" 7633259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck pass 7733259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck 7833259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck_escaped = { 7933259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck '"' : True, 8033259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck '(' : True, 8133259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck ')' : True, 8233259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck '.' : True, 8333259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck ';' : True, 8433259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck '\\' : True, 8533259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck '@' : True, 8633259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck '$' : True 8733259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck } 8833259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck 8933259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reckdef _escapify(label): 9033259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck """Escape the characters in label which need it. 9133259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck @returns: the escaped string 9233259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck @rtype: string""" 9333259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck text = '' 9433259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck for c in label: 9533259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck if c in _escaped: 9633259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck text += '\\' + c 9733259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck elif ord(c) > 0x20 and ord(c) < 0x7F: 9833259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck text += c 9933259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck else: 10033259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck text += '\\%03d' % ord(c) 10133259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck return text 10233259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck 10333259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reckdef _validate_labels(labels): 10433259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck """Check for empty labels in the middle of a label sequence, 10533259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck labels that are too long, and for too many labels. 10633259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck @raises NameTooLong: the name as a whole is too long 10733259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck @raises LabelTooLong: an individual label is too long 10833259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck @raises EmptyLabel: a label is empty (i.e. the root label) and appears 10933259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck in a position other than the end of the label sequence""" 11033259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck 11133259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck l = len(labels) 11233259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck total = 0 11333259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck i = -1 11433259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck j = 0 11533259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck for label in labels: 11633259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck ll = len(label) 11733259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck total += ll + 1 11833259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck if ll > 63: 11933259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck raise LabelTooLong 12033259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck if i < 0 and label == '': 12133259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck i = j 12233259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck j += 1 12333259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck if total > 255: 12433259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck raise NameTooLong 12533259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck if i >= 0 and i != l - 1: 12633259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck raise EmptyLabel 12733259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck 12833259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reckclass Name(object): 12933259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck """A DNS name. 13033259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck 13133259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck The dns.name.Name class represents a DNS name as a tuple of labels. 13233259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck Instances of the class are immutable. 13333259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck 13433259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck @ivar labels: The tuple of labels in the name. Each label is a string of 13533259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck up to 63 octets.""" 13633259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck 13733259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck __slots__ = ['labels'] 13833259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck 13933259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck def __init__(self, labels): 14033259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck """Initialize a domain name from a list of labels. 14133259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck @param labels: the labels 14233259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck @type labels: any iterable whose values are strings 14333259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck """ 14433259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck 14533259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck super(Name, self).__setattr__('labels', tuple(labels)) 14633259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck _validate_labels(self.labels) 14733259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck 14833259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck def __setattr__(self, name, value): 14933259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck raise TypeError("object doesn't support attribute assignment") 15033259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck 15133259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck def is_absolute(self): 15233259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck """Is the most significant label of this name the root label? 15333259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck @rtype: bool 15433259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck """ 15533259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck 15633259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck return len(self.labels) > 0 and self.labels[-1] == '' 15733259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck 15833259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck def is_wild(self): 15933259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck """Is this name wild? (I.e. Is the least significant label '*'?) 16033259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck @rtype: bool 16133259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck """ 16233259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck 16333259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck return len(self.labels) > 0 and self.labels[0] == '*' 16433259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck 16533259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck def __hash__(self): 16633259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck """Return a case-insensitive hash of the name. 16733259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck @rtype: int 16833259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck """ 16933259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck 17033259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck h = 0L 17133259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck for label in self.labels: 17233259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck for c in label: 17333259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck h += ( h << 3 ) + ord(c.lower()) 17433259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck return int(h % sys.maxint) 17533259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck 17633259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck def fullcompare(self, other): 17733259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck """Compare two names, returning a 3-tuple (relation, order, nlabels). 17833259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck 17933259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck I{relation} describes the relation ship between the names, 18033259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck and is one of: dns.name.NAMERELN_NONE, 18133259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck dns.name.NAMERELN_SUPERDOMAIN, dns.name.NAMERELN_SUBDOMAIN, 18233259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck dns.name.NAMERELN_EQUAL, or dns.name.NAMERELN_COMMONANCESTOR 18333259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck 18433259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck I{order} is < 0 if self < other, > 0 if self > other, and == 18533259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck 0 if self == other. A relative name is always less than an 18633259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck absolute name. If both names have the same relativity, then 18733259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck the DNSSEC order relation is used to order them. 18833259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck 18933259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck I{nlabels} is the number of significant labels that the two names 19033259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck have in common. 19133259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck """ 19233259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck 19333259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck sabs = self.is_absolute() 19433259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck oabs = other.is_absolute() 19533259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck if sabs != oabs: 19633259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck if sabs: 19733259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck return (NAMERELN_NONE, 1, 0) 19833259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck else: 19933259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck return (NAMERELN_NONE, -1, 0) 20033259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck l1 = len(self.labels) 20133259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck l2 = len(other.labels) 20233259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck ldiff = l1 - l2 20333259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck if ldiff < 0: 20433259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck l = l1 20533259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck else: 20633259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck l = l2 20733259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck 20833259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck order = 0 20933259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck nlabels = 0 21033259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck namereln = NAMERELN_NONE 21133259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck while l > 0: 21233259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck l -= 1 21333259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck l1 -= 1 21433259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck l2 -= 1 21533259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck label1 = self.labels[l1].lower() 21633259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck label2 = other.labels[l2].lower() 21733259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck if label1 < label2: 21833259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck order = -1 21933259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck if nlabels > 0: 22033259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck namereln = NAMERELN_COMMONANCESTOR 22133259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck return (namereln, order, nlabels) 22233259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck elif label1 > label2: 22333259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck order = 1 22433259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck if nlabels > 0: 22533259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck namereln = NAMERELN_COMMONANCESTOR 22633259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck return (namereln, order, nlabels) 22733259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck nlabels += 1 22833259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck order = ldiff 22933259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck if ldiff < 0: 23033259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck namereln = NAMERELN_SUPERDOMAIN 23133259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck elif ldiff > 0: 23233259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck namereln = NAMERELN_SUBDOMAIN 23333259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck else: 23433259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck namereln = NAMERELN_EQUAL 23533259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck return (namereln, order, nlabels) 23633259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck 23733259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck def is_subdomain(self, other): 23833259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck """Is self a subdomain of other? 23933259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck 24033259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck The notion of subdomain includes equality. 24133259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck @rtype: bool 24233259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck """ 24333259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck 24433259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck (nr, o, nl) = self.fullcompare(other) 24533259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck if nr == NAMERELN_SUBDOMAIN or nr == NAMERELN_EQUAL: 24633259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck return True 24733259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck return False 24833259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck 24933259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck def is_superdomain(self, other): 25033259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck """Is self a superdomain of other? 25133259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck 25233259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck The notion of subdomain includes equality. 25333259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck @rtype: bool 25433259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck """ 25533259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck 25633259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck (nr, o, nl) = self.fullcompare(other) 25733259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck if nr == NAMERELN_SUPERDOMAIN or nr == NAMERELN_EQUAL: 25833259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck return True 25933259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck return False 26033259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck 26133259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck def canonicalize(self): 26233259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck """Return a name which is equal to the current name, but is in 26333259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck DNSSEC canonical form. 26433259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck @rtype: dns.name.Name object 26533259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck """ 26633259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck 26733259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck return Name([x.lower() for x in self.labels]) 26833259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck 26933259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck def __eq__(self, other): 27033259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck if isinstance(other, Name): 27133259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck return self.fullcompare(other)[1] == 0 27233259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck else: 27333259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck return False 27433259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck 27533259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck def __ne__(self, other): 27633259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck if isinstance(other, Name): 27733259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck return self.fullcompare(other)[1] != 0 27833259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck else: 27933259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck return True 28033259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck 28133259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck def __lt__(self, other): 28233259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck if isinstance(other, Name): 28333259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck return self.fullcompare(other)[1] < 0 28433259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck else: 28533259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck return NotImplemented 28633259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck 28733259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck def __le__(self, other): 28833259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck if isinstance(other, Name): 28933259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck return self.fullcompare(other)[1] <= 0 29033259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck else: 29133259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck return NotImplemented 29233259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck 29333259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck def __ge__(self, other): 29433259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck if isinstance(other, Name): 29533259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck return self.fullcompare(other)[1] >= 0 29633259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck else: 29733259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck return NotImplemented 29833259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck 29933259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck def __gt__(self, other): 30033259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck if isinstance(other, Name): 30133259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck return self.fullcompare(other)[1] > 0 30233259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck else: 30333259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck return NotImplemented 30433259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck 30533259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck def __repr__(self): 30633259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck return '<DNS name ' + self.__str__() + '>' 30733259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck 30833259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck def __str__(self): 30933259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck return self.to_text(False) 31033259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck 31133259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck def to_text(self, omit_final_dot = False): 31233259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck """Convert name to text format. 31333259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck @param omit_final_dot: If True, don't emit the final dot (denoting the 31433259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck root label) for absolute names. The default is False. 31533259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck @rtype: string 31633259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck """ 31733259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck 31833259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck if len(self.labels) == 0: 31933259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck return '@' 32033259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck if len(self.labels) == 1 and self.labels[0] == '': 32133259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck return '.' 32233259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck if omit_final_dot and self.is_absolute(): 32333259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck l = self.labels[:-1] 32433259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck else: 32533259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck l = self.labels 32633259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck s = '.'.join(map(_escapify, l)) 32733259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck return s 32833259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck 32933259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck def to_unicode(self, omit_final_dot = False): 33033259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck """Convert name to Unicode text format. 33133259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck 33233259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck IDN ACE lables are converted to Unicode. 33333259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck 33433259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck @param omit_final_dot: If True, don't emit the final dot (denoting the 33533259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck root label) for absolute names. The default is False. 33633259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck @rtype: string 33733259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck """ 33833259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck 33933259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck if len(self.labels) == 0: 34033259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck return u'@' 34133259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck if len(self.labels) == 1 and self.labels[0] == '': 34233259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck return u'.' 34333259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck if omit_final_dot and self.is_absolute(): 34433259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck l = self.labels[:-1] 34533259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck else: 34633259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck l = self.labels 34733259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck s = u'.'.join([encodings.idna.ToUnicode(_escapify(x)) for x in l]) 34833259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck return s 34933259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck 35033259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck def to_digestable(self, origin=None): 35133259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck """Convert name to a format suitable for digesting in hashes. 35233259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck 35333259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck The name is canonicalized and converted to uncompressed wire format. 35433259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck 35533259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck @param origin: If the name is relative and origin is not None, then 35633259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck origin will be appended to it. 35733259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck @type origin: dns.name.Name object 35833259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck @raises NeedAbsoluteNameOrOrigin: All names in wire format are 35933259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck absolute. If self is a relative name, then an origin must be supplied; 36033259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck if it is missing, then this exception is raised 36133259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck @rtype: string 36233259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck """ 36333259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck 36433259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck if not self.is_absolute(): 36533259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck if origin is None or not origin.is_absolute(): 36633259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck raise NeedAbsoluteNameOrOrigin 36733259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck labels = list(self.labels) 36833259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck labels.extend(list(origin.labels)) 36933259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck else: 37033259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck labels = self.labels 37133259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck dlabels = ["%s%s" % (chr(len(x)), x.lower()) for x in labels] 37233259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck return ''.join(dlabels) 37333259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck 37433259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck def to_wire(self, file = None, compress = None, origin = None): 37533259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck """Convert name to wire format, possibly compressing it. 37633259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck 37733259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck @param file: the file where the name is emitted (typically 37833259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck a cStringIO file). If None, a string containing the wire name 37933259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck will be returned. 38033259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck @type file: file or None 38133259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck @param compress: The compression table. If None (the default) names 38233259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck will not be compressed. 38333259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck @type compress: dict 38433259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck @param origin: If the name is relative and origin is not None, then 38533259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck origin will be appended to it. 38633259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck @type origin: dns.name.Name object 38733259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck @raises NeedAbsoluteNameOrOrigin: All names in wire format are 38833259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck absolute. If self is a relative name, then an origin must be supplied; 38933259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck if it is missing, then this exception is raised 39033259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck """ 39133259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck 39233259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck if file is None: 39333259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck file = cStringIO.StringIO() 39433259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck want_return = True 39533259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck else: 39633259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck want_return = False 39733259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck 39833259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck if not self.is_absolute(): 39933259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck if origin is None or not origin.is_absolute(): 40033259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck raise NeedAbsoluteNameOrOrigin 40133259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck labels = list(self.labels) 40233259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck labels.extend(list(origin.labels)) 40333259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck else: 40433259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck labels = self.labels 40533259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck i = 0 40633259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck for label in labels: 40733259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck n = Name(labels[i:]) 40833259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck i += 1 40933259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck if not compress is None: 41033259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck pos = compress.get(n) 41133259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck else: 41233259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck pos = None 41333259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck if not pos is None: 41433259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck value = 0xc000 + pos 41533259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck s = struct.pack('!H', value) 41633259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck file.write(s) 41733259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck break 41833259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck else: 41933259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck if not compress is None and len(n) > 1: 42033259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck pos = file.tell() 42133259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck if pos < 0xc000: 42233259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck compress[n] = pos 42333259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck l = len(label) 42433259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck file.write(chr(l)) 42533259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck if l > 0: 42633259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck file.write(label) 42733259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck if want_return: 42833259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck return file.getvalue() 42933259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck 43033259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck def __len__(self): 43133259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck """The length of the name (in labels). 43233259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck @rtype: int 43333259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck """ 43433259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck 43533259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck return len(self.labels) 43633259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck 43733259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck def __getitem__(self, index): 43833259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck return self.labels[index] 43933259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck 44033259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck def __getslice__(self, start, stop): 44133259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck return self.labels[start:stop] 44233259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck 44333259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck def __add__(self, other): 44433259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck return self.concatenate(other) 44533259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck 44633259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck def __sub__(self, other): 44733259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck return self.relativize(other) 44833259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck 44933259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck def split(self, depth): 45033259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck """Split a name into a prefix and suffix at depth. 45133259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck 45233259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck @param depth: the number of labels in the suffix 45333259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck @type depth: int 45433259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck @raises ValueError: the depth was not >= 0 and <= the length of the 45533259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck name. 45633259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck @returns: the tuple (prefix, suffix) 45733259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck @rtype: tuple 45833259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck """ 45933259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck 46033259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck l = len(self.labels) 46133259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck if depth == 0: 46233259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck return (self, dns.name.empty) 46333259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck elif depth == l: 46433259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck return (dns.name.empty, self) 46533259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck elif depth < 0 or depth > l: 46633259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck raise ValueError('depth must be >= 0 and <= the length of the name') 46733259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck return (Name(self[: -depth]), Name(self[-depth :])) 46833259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck 46933259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck def concatenate(self, other): 47033259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck """Return a new name which is the concatenation of self and other. 47133259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck @rtype: dns.name.Name object 47233259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck @raises AbsoluteConcatenation: self is absolute and other is 47333259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck not the empty name 47433259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck """ 47533259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck 47633259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck if self.is_absolute() and len(other) > 0: 47733259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck raise AbsoluteConcatenation 47833259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck labels = list(self.labels) 47933259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck labels.extend(list(other.labels)) 48033259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck return Name(labels) 48133259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck 48233259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck def relativize(self, origin): 48333259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck """If self is a subdomain of origin, return a new name which is self 48433259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck relative to origin. Otherwise return self. 48533259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck @rtype: dns.name.Name object 48633259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck """ 48733259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck 48833259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck if not origin is None and self.is_subdomain(origin): 48933259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck return Name(self[: -len(origin)]) 49033259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck else: 49133259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck return self 49233259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck 49333259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck def derelativize(self, origin): 49433259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck """If self is a relative name, return a new name which is the 49533259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck concatenation of self and origin. Otherwise return self. 49633259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck @rtype: dns.name.Name object 49733259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck """ 49833259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck 49933259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck if not self.is_absolute(): 50033259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck return self.concatenate(origin) 50133259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck else: 50233259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck return self 50333259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck 50433259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck def choose_relativity(self, origin=None, relativize=True): 50533259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck """Return a name with the relativity desired by the caller. If 50633259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck origin is None, then self is returned. Otherwise, if 50733259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck relativize is true the name is relativized, and if relativize is 50833259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck false the name is derelativized. 50933259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck @rtype: dns.name.Name object 51033259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck """ 51133259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck 51233259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck if origin: 51333259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck if relativize: 51433259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck return self.relativize(origin) 51533259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck else: 51633259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck return self.derelativize(origin) 51733259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck else: 51833259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck return self 51933259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck 52033259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck def parent(self): 52133259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck """Return the parent of the name. 52233259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck @rtype: dns.name.Name object 52333259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck @raises NoParent: the name is either the root name or the empty name, 52433259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck and thus has no parent. 52533259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck """ 52633259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck if self == root or self == empty: 52733259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck raise NoParent 52833259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck return Name(self.labels[1:]) 52933259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck 53033259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reckroot = Name(['']) 53133259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reckempty = Name([]) 53233259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck 53333259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reckdef from_unicode(text, origin = root): 53433259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck """Convert unicode text into a Name object. 53533259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck 53633259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck Lables are encoded in IDN ACE form. 53733259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck 53833259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck @rtype: dns.name.Name object 53933259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck """ 54033259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck 54133259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck if not isinstance(text, unicode): 54233259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck raise ValueError("input to from_unicode() must be a unicode string") 54333259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck if not (origin is None or isinstance(origin, Name)): 54433259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck raise ValueError("origin must be a Name or None") 54533259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck labels = [] 54633259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck label = u'' 54733259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck escaping = False 54833259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck edigits = 0 54933259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck total = 0 55033259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck if text == u'@': 55133259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck text = u'' 55233259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck if text: 55333259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck if text == u'.': 55433259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck return Name(['']) # no Unicode "u" on this constant! 55533259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck for c in text: 55633259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck if escaping: 55733259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck if edigits == 0: 55833259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck if c.isdigit(): 55933259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck total = int(c) 56033259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck edigits += 1 56133259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck else: 56233259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck label += c 56333259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck escaping = False 56433259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck else: 56533259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck if not c.isdigit(): 56633259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck raise BadEscape 56733259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck total *= 10 56833259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck total += int(c) 56933259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck edigits += 1 57033259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck if edigits == 3: 57133259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck escaping = False 57233259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck label += chr(total) 57333259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck elif c == u'.' or c == u'\u3002' or \ 57433259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck c == u'\uff0e' or c == u'\uff61': 57533259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck if len(label) == 0: 57633259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck raise EmptyLabel 57733259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck labels.append(encodings.idna.ToASCII(label)) 57833259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck label = u'' 57933259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck elif c == u'\\': 58033259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck escaping = True 58133259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck edigits = 0 58233259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck total = 0 58333259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck else: 58433259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck label += c 58533259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck if escaping: 58633259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck raise BadEscape 58733259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck if len(label) > 0: 58833259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck labels.append(encodings.idna.ToASCII(label)) 58933259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck else: 59033259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck labels.append('') 59133259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck if (len(labels) == 0 or labels[-1] != '') and not origin is None: 59233259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck labels.extend(list(origin.labels)) 59333259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck return Name(labels) 59433259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck 59533259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reckdef from_text(text, origin = root): 59633259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck """Convert text into a Name object. 59733259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck @rtype: dns.name.Name object 59833259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck """ 59933259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck 60033259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck if not isinstance(text, str): 60133259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck if isinstance(text, unicode) and sys.hexversion >= 0x02030000: 60233259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck return from_unicode(text, origin) 60333259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck else: 60433259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck raise ValueError("input to from_text() must be a string") 60533259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck if not (origin is None or isinstance(origin, Name)): 60633259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck raise ValueError("origin must be a Name or None") 60733259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck labels = [] 60833259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck label = '' 60933259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck escaping = False 61033259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck edigits = 0 61133259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck total = 0 61233259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck if text == '@': 61333259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck text = '' 61433259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck if text: 61533259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck if text == '.': 61633259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck return Name(['']) 61733259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck for c in text: 61833259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck if escaping: 61933259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck if edigits == 0: 62033259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck if c.isdigit(): 62133259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck total = int(c) 62233259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck edigits += 1 62333259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck else: 62433259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck label += c 62533259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck escaping = False 62633259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck else: 62733259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck if not c.isdigit(): 62833259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck raise BadEscape 62933259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck total *= 10 63033259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck total += int(c) 63133259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck edigits += 1 63233259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck if edigits == 3: 63333259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck escaping = False 63433259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck label += chr(total) 63533259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck elif c == '.': 63633259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck if len(label) == 0: 63733259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck raise EmptyLabel 63833259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck labels.append(label) 63933259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck label = '' 64033259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck elif c == '\\': 64133259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck escaping = True 64233259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck edigits = 0 64333259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck total = 0 64433259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck else: 64533259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck label += c 64633259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck if escaping: 64733259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck raise BadEscape 64833259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck if len(label) > 0: 64933259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck labels.append(label) 65033259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck else: 65133259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck labels.append('') 65233259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck if (len(labels) == 0 or labels[-1] != '') and not origin is None: 65333259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck labels.extend(list(origin.labels)) 65433259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck return Name(labels) 65533259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck 65633259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reckdef from_wire(message, current): 65733259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck """Convert possibly compressed wire format into a Name. 65833259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck @param message: the entire DNS message 65933259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck @type message: string 66033259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck @param current: the offset of the beginning of the name from the start 66133259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck of the message 66233259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck @type current: int 66333259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck @raises dns.name.BadPointer: a compression pointer did not point backwards 66433259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck in the message 66533259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck @raises dns.name.BadLabelType: an invalid label type was encountered. 66633259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck @returns: a tuple consisting of the name that was read and the number 66733259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck of bytes of the wire format message which were consumed reading it 66833259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck @rtype: (dns.name.Name object, int) tuple 66933259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck """ 67033259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck 67133259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck if not isinstance(message, str): 67233259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck raise ValueError("input to from_wire() must be a byte string") 67333259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck labels = [] 67433259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck biggest_pointer = current 67533259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck hops = 0 67633259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck count = ord(message[current]) 67733259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck current += 1 67833259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck cused = 1 67933259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck while count != 0: 68033259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck if count < 64: 68133259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck labels.append(message[current : current + count]) 68233259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck current += count 68333259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck if hops == 0: 68433259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck cused += count 68533259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck elif count >= 192: 68633259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck current = (count & 0x3f) * 256 + ord(message[current]) 68733259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck if hops == 0: 68833259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck cused += 1 68933259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck if current >= biggest_pointer: 69033259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck raise BadPointer 69133259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck biggest_pointer = current 69233259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck hops += 1 69333259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck else: 69433259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck raise BadLabelType 69533259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck count = ord(message[current]) 69633259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck current += 1 69733259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck if hops == 0: 69833259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck cused += 1 69933259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck labels.append('') 70033259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck return (Name(labels), cused) 701