--- dns.py	2006-11-26 17:39:59.000000000 +0100
+++ dns.py	2006-11-27 08:33:50.000000000 +0100
@@ -69,6 +69,7 @@
  RP, AFSDB) = range(1, 19)
 AAAA = 28
 SRV = 33
+NAPTR = 35
 A6 = 38
 DNAME = 39
 
@@ -96,7 +97,7 @@
 
     AAAA: 'AAAA',
     SRV: 'SRV',
-
+	NAPTR: 'NAPTR',
     A6: 'A6',
     DNAME: 'DNAME'
 }
@@ -212,6 +213,63 @@
         encoded in the data is it necessary.
         """
 
+class Charstr:
+    implements(IEncodable)
+
+    def __init__(self, string=''):
+        assert isinstance(string, types.StringTypes), "%r is not a string" % (name,)
+        self.string = string
+
+    def encode(self, strio, compDict=None):
+        """
+        Encode this Character string into the appropriate byte format.
+
+        @type strio: file
+        @param strio: The byte representation of this Charstr will be written to
+        this file.
+
+        @type compDict: dict
+        @param compDict: dictionary of Charstrs that have already been encoded
+        and whose addresses may be backreferenced by this Charstr (for the purpose
+        of reducing the message size).
+        """
+        string = self.string
+        if compDict is not None:
+            if compDict.has_key(string):
+                strio.write(
+                    struct.pack("!H", 0xc000 | compDict[string]))
+                return
+            else:
+                compDict[string] = strio.tell() + Message.headerSize
+
+        ind = len(string)
+        strio.write(chr(ind))
+        strio.write(string)
+
+    def decode(self, strio, length = None):
+        """
+        Decode a byte string into this Name.
+
+        @type strio: file
+        @param strio: Bytes will be read from this file until the full Name
+        is decoded.
+
+        @raise EOFError: Raised when there are not enough bytes available
+        from C{strio}.
+        """
+        self.string = ''
+        off = 0
+        l = ord(readPrecisely(strio, 1))
+        if l != 0:
+            self.string = readPrecisely(strio, l)
+
+    def __eq__(self, other):
+        if isinstance(other, Charstr):
+            return self.string == other.string
+        return 0
+
+    def __str__(self):
+        return self.string
 
 class Name:
     implements(IEncodable)
@@ -738,9 +796,50 @@
         self.target.decode(strio)
 
 
-    def __hash__(self):
-        return hash((self.priority, self.weight, self.port, self.target))
+def __hash__(self):
+    return hash((self.priority, self.weight, self.port, self.target))
+
 
+    class Record_NAPTR(tputil.FancyEqMixin, tputil.FancyStrMixin):                # EXPERIMENTAL
+        implements(IEncodable, IRecord)
+        TYPE = NAPTR
+
+        compareAttributes = ('order', 'preference', 'flags', 'service', 'regexp', "replacement")
+        showAttributes = ('order', 'preference', ('flags', 'flags', '%s'),('service', 'service', '%s'),('regexp', 'regexp', '%s'),('replacement', 'replacement', '%s'),'ttl')
+
+        def __init__(self, order=0, preference=0, flags='', service='', regexp='', replacement='', ttl=None):
+            self.order = int(order)
+            self.preference = int(preference)
+            self.flags = Charstr(flags)
+            self.service = Charstr(service)
+            self.regexp = Charstr(regexp)
+            self.replacement = Name(replacement)
+            self.ttl = str2time(ttl)
+
+        def encode(self, strio, compDict = None):
+            strio.write(struct.pack('!HH', self.order, self.preference))
+            # This can't be compressed
+            self.flags.encode(strio, None)
+            self.service.encode(strio, None)
+            self.regexp.encode(strio, None)
+            self.replacement.encode(strio, None)
+
+        def decode(self, strio, length = None):
+            r = struct.unpack('!HH', readPrecisely(strio, struct.calcsize('!HH')))
+            self.order, self.preference = r
+            self.flags = Charstr()
+            self.service = Charstr()
+            self.regexp = Charstr()
+            self.replacement = Name()
+            self.flags.decode(strio)
+            self.service.decode(strio)
+            self.regexp.decode(strio)
+            self.replacement.decode(strio)
+
+        def __hash__(self):
+            return hash((
+                self.order, self.preference, self.flags, 
+                self.service, self.regexp, self.replacement))
 
 
 class Record_AFSDB(tputil.FancyStrMixin, tputil.FancyEqMixin):
