7fe043082b397c948b308e37bdd0f63d554238a4
[bbaumbach/samba-autobuild/.git] / lib / dnspython / dns / rdtypes / IN / NAPTR.py
1 # Copyright (C) 2003-2007, 2009-2011 Nominum, Inc.
2 #
3 # Permission to use, copy, modify, and distribute this software and its
4 # documentation for any purpose with or without fee is hereby granted,
5 # provided that the above copyright notice and this permission notice
6 # appear in all copies.
7 #
8 # THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES
9 # WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10 # MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR
11 # ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12 # WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13 # ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
14 # OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15
16 import struct
17
18 import dns.exception
19 import dns.name
20 import dns.rdata
21
22 def _write_string(file, s):
23     l = len(s)
24     assert l < 256
25     byte = chr(l)
26     file.write(byte)
27     file.write(s)
28
29 class NAPTR(dns.rdata.Rdata):
30     """NAPTR record
31
32     @ivar order: order
33     @type order: int
34     @ivar preference: preference
35     @type preference: int
36     @ivar flags: flags
37     @type flags: string
38     @ivar service: service
39     @type service: string
40     @ivar regexp: regular expression
41     @type regexp: string
42     @ivar replacement: replacement name
43     @type replacement: dns.name.Name object
44     @see: RFC 3403"""
45
46     __slots__ = ['order', 'preference', 'flags', 'service', 'regexp',
47                  'replacement']
48
49     def __init__(self, rdclass, rdtype, order, preference, flags, service,
50                  regexp, replacement):
51         super(NAPTR, self).__init__(rdclass, rdtype)
52         self.order = order
53         self.preference = preference
54         self.flags = flags
55         self.service = service
56         self.regexp = regexp
57         self.replacement = replacement
58
59     def to_text(self, origin=None, relativize=True, **kw):
60         replacement = self.replacement.choose_relativity(origin, relativize)
61         return '%d %d "%s" "%s" "%s" %s' % \
62                (self.order, self.preference,
63                 dns.rdata._escapify(self.flags),
64                 dns.rdata._escapify(self.service),
65                 dns.rdata._escapify(self.regexp),
66                 self.replacement)
67
68     def from_text(cls, rdclass, rdtype, tok, origin = None, relativize = True):
69         order = tok.get_uint16()
70         preference = tok.get_uint16()
71         flags = tok.get_string()
72         service = tok.get_string()
73         regexp = tok.get_string()
74         replacement = tok.get_name()
75         replacement = replacement.choose_relativity(origin, relativize)
76         tok.get_eol()
77         return cls(rdclass, rdtype, order, preference, flags, service,
78                    regexp, replacement)
79
80     from_text = classmethod(from_text)
81
82     def to_wire(self, file, compress = None, origin = None):
83         two_ints = struct.pack("!HH", self.order, self.preference)
84         file.write(two_ints)
85         _write_string(file, self.flags)
86         _write_string(file, self.service)
87         _write_string(file, self.regexp)
88         self.replacement.to_wire(file, compress, origin)
89
90     def from_wire(cls, rdclass, rdtype, wire, current, rdlen, origin = None):
91         (order, preference) = struct.unpack('!HH', wire[current : current + 4])
92         current += 4
93         rdlen -= 4
94         strings = []
95         for i in xrange(3):
96             l = ord(wire[current])
97             current += 1
98             rdlen -= 1
99             if l > rdlen or rdlen < 0:
100                 raise dns.exception.FormError
101             s = wire[current : current + l].unwrap()
102             current += l
103             rdlen -= l
104             strings.append(s)
105         (replacement, cused) = dns.name.from_wire(wire[: current + rdlen],
106                                                   current)
107         if cused != rdlen:
108             raise dns.exception.FormError
109         if not origin is None:
110             replacement = replacement.relativize(origin)
111         return cls(rdclass, rdtype, order, preference, strings[0], strings[1],
112                    strings[2], replacement)
113
114     from_wire = classmethod(from_wire)
115
116     def choose_relativity(self, origin = None, relativize = True):
117         self.replacement = self.replacement.choose_relativity(origin,
118                                                               relativize)
119
120     def _cmp(self, other):
121         sp = struct.pack("!HH", self.order, self.preference)
122         op = struct.pack("!HH", other.order, other.preference)
123         v = cmp(sp, op)
124         if v == 0:
125             v = cmp(self.flags, other.flags)
126             if v == 0:
127                 v = cmp(self.service, other.service)
128                 if v == 0:
129                     v = cmp(self.regexp, other.regexp)
130                     if v == 0:
131                         v = cmp(self.replacement, other.replacement)
132         return v