Package dns :: Package rdtypes :: Package ANY :: Module LOC
[hide private]
[frames] | no frames]

Source Code for Module dns.rdtypes.ANY.LOC

  1  # Copyright (C) 2003-2007, 2009 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 cStringIO 
 17  import struct 
 18   
 19  import dns.exception 
 20  import dns.rdata 
 21   
 22  _pows = (1L, 10L, 100L, 1000L, 10000L, 100000L, 1000000L, 10000000L, 
 23           100000000L, 1000000000L, 10000000000L) 
 24   
25 -def _exponent_of(what, desc):
26 exp = None 27 for i in xrange(len(_pows)): 28 if what // _pows[i] == 0L: 29 exp = i - 1 30 break 31 if exp is None or exp < 0: 32 raise dns.exception.SyntaxError, "%s value out of bounds" % desc 33 return exp
34
35 -def _float_to_tuple(what):
36 if what < 0: 37 sign = -1 38 what *= -1 39 else: 40 sign = 1 41 what = long(round(what * 3600000)) 42 degrees = int(what // 3600000) 43 what -= degrees * 3600000 44 minutes = int(what // 60000) 45 what -= minutes * 60000 46 seconds = int(what // 1000) 47 what -= int(seconds * 1000) 48 what = int(what) 49 return (degrees * sign, minutes, seconds, what)
50
51 -def _tuple_to_float(what):
52 if what[0] < 0: 53 sign = -1 54 value = float(what[0]) * -1 55 else: 56 sign = 1 57 value = float(what[0]) 58 value += float(what[1]) / 60.0 59 value += float(what[2]) / 3600.0 60 value += float(what[3]) / 3600000.0 61 return sign * value
62
63 -def _encode_size(what, desc):
64 what = long(what); 65 exponent = _exponent_of(what, desc) & 0xF 66 base = what // pow(10, exponent) & 0xF 67 return base * 16 + exponent
68
69 -def _decode_size(what, desc):
70 exponent = what & 0x0F 71 if exponent > 9: 72 raise dns.exception.SyntaxError, "bad %s exponent" % desc 73 base = (what & 0xF0) >> 4 74 if base > 9: 75 raise dns.exception.SyntaxError, "bad %s base" % desc 76 return long(base) * pow(10, exponent)
77
78 -class LOC(dns.rdata.Rdata):
79 """LOC record 80 81 @ivar latitude: latitude 82 @type latitude: (int, int, int, int) tuple specifying the degrees, minutes, 83 seconds, and milliseconds of the coordinate. 84 @ivar longitude: longitude 85 @type longitude: (int, int, int, int) tuple specifying the degrees, 86 minutes, seconds, and milliseconds of the coordinate. 87 @ivar altitude: altitude 88 @type altitude: float 89 @ivar size: size of the sphere 90 @type size: float 91 @ivar horizontal_precision: horizontal precision 92 @type horizontal_precision: float 93 @ivar vertical_precision: vertical precision 94 @type vertical_precision: float 95 @see: RFC 1876""" 96 97 __slots__ = ['latitude', 'longitude', 'altitude', 'size', 98 'horizontal_precision', 'vertical_precision'] 99
100 - def __init__(self, rdclass, rdtype, latitude, longitude, altitude, 101 size=1.0, hprec=10000.0, vprec=10.0):
102 """Initialize a LOC record instance. 103 104 The parameters I{latitude} and I{longitude} may be either a 4-tuple 105 of integers specifying (degrees, minutes, seconds, milliseconds), 106 or they may be floating point values specifying the number of 107 degrees. The other parameters are floats.""" 108 109 super(LOC, self).__init__(rdclass, rdtype) 110 if isinstance(latitude, int) or isinstance(latitude, long): 111 latitude = float(latitude) 112 if isinstance(latitude, float): 113 latitude = _float_to_tuple(latitude) 114 self.latitude = latitude 115 if isinstance(longitude, int) or isinstance(longitude, long): 116 longitude = float(longitude) 117 if isinstance(longitude, float): 118 longitude = _float_to_tuple(longitude) 119 self.longitude = longitude 120 self.altitude = float(altitude) 121 self.size = float(size) 122 self.horizontal_precision = float(hprec) 123 self.vertical_precision = float(vprec)
124
125 - def to_text(self, origin=None, relativize=True, **kw):
126 if self.latitude[0] > 0: 127 lat_hemisphere = 'N' 128 lat_degrees = self.latitude[0] 129 else: 130 lat_hemisphere = 'S' 131 lat_degrees = -1 * self.latitude[0] 132 if self.longitude[0] > 0: 133 long_hemisphere = 'E' 134 long_degrees = self.longitude[0] 135 else: 136 long_hemisphere = 'W' 137 long_degrees = -1 * self.longitude[0] 138 text = "%d %d %d.%03d %s %d %d %d.%03d %s %0.2fm" % ( 139 lat_degrees, self.latitude[1], self.latitude[2], self.latitude[3], 140 lat_hemisphere, long_degrees, self.longitude[1], self.longitude[2], 141 self.longitude[3], long_hemisphere, self.altitude / 100.0 142 ) 143 144 if self.size != 1.0 or self.horizontal_precision != 10000.0 or \ 145 self.vertical_precision != 10.0: 146 text += " %0.2fm %0.2fm %0.2fm" % ( 147 self.size / 100.0, self.horizontal_precision / 100.0, 148 self.vertical_precision / 100.0 149 ) 150 return text
151
152 - def from_text(cls, rdclass, rdtype, tok, origin = None, relativize = True):
153 latitude = [0, 0, 0, 0] 154 longitude = [0, 0, 0, 0] 155 size = 1.0 156 hprec = 10000.0 157 vprec = 10.0 158 159 latitude[0] = tok.get_int() 160 t = tok.get_string() 161 if t.isdigit(): 162 latitude[1] = int(t) 163 t = tok.get_string() 164 if '.' in t: 165 (seconds, milliseconds) = t.split('.') 166 if not seconds.isdigit(): 167 raise dns.exception.SyntaxError, \ 168 'bad latitude seconds value' 169 latitude[2] = int(seconds) 170 if latitude[2] >= 60: 171 raise dns.exception.SyntaxError, \ 172 'latitude seconds >= 60' 173 l = len(milliseconds) 174 if l == 0 or l > 3 or not milliseconds.isdigit(): 175 raise dns.exception.SyntaxError, \ 176 'bad latitude milliseconds value' 177 if l == 1: 178 m = 100 179 elif l == 2: 180 m = 10 181 else: 182 m = 1 183 latitude[3] = m * int(milliseconds) 184 t = tok.get_string() 185 elif t.isdigit(): 186 latitude[2] = int(t) 187 t = tok.get_string() 188 if t == 'S': 189 latitude[0] *= -1 190 elif t != 'N': 191 raise dns.exception.SyntaxError, 'bad latitude hemisphere value' 192 193 longitude[0] = tok.get_int() 194 t = tok.get_string() 195 if t.isdigit(): 196 longitude[1] = int(t) 197 t = tok.get_string() 198 if '.' in t: 199 (seconds, milliseconds) = t.split('.') 200 if not seconds.isdigit(): 201 raise dns.exception.SyntaxError, \ 202 'bad longitude seconds value' 203 longitude[2] = int(seconds) 204 if longitude[2] >= 60: 205 raise dns.exception.SyntaxError, \ 206 'longitude seconds >= 60' 207 l = len(milliseconds) 208 if l == 0 or l > 3 or not milliseconds.isdigit(): 209 raise dns.exception.SyntaxError, \ 210 'bad longitude milliseconds value' 211 if l == 1: 212 m = 100 213 elif l == 2: 214 m = 10 215 else: 216 m = 1 217 longitude[3] = m * int(milliseconds) 218 t = tok.get_string() 219 elif t.isdigit(): 220 longitude[2] = int(t) 221 t = tok.get_string() 222 if t == 'W': 223 longitude[0] *= -1 224 elif t != 'E': 225 raise dns.exception.SyntaxError, 'bad longitude hemisphere value' 226 227 t = tok.get_string() 228 if t[-1] == 'm': 229 t = t[0 : -1] 230 altitude = float(t) * 100.0 # m -> cm 231 232 (ttype, value) = tok.get() 233 if ttype != dns.tokenizer.EOL and ttype != dns.tokenizer.EOF: 234 if value[-1] == 'm': 235 value = value[0 : -1] 236 size = float(value) * 100.0 # m -> cm 237 (ttype, value) = tok.get() 238 if ttype != dns.tokenizer.EOL and ttype != dns.tokenizer.EOF: 239 if value[-1] == 'm': 240 value = value[0 : -1] 241 hprec = float(value) * 100.0 # m -> cm 242 (ttype, value) = tok.get() 243 if ttype != dns.tokenizer.EOL and ttype != dns.tokenizer.EOF: 244 if value[-1] == 'm': 245 value = value[0 : -1] 246 vprec = float(value) * 100.0 # m -> cm 247 (ttype, value) = tok.get() 248 if ttype != dns.tokenizer.EOL and \ 249 ttype != dns.tokenizer.EOF: 250 raise dns.exception.SyntaxError, \ 251 "expected EOL or EOF" 252 253 return cls(rdclass, rdtype, latitude, longitude, altitude, 254 size, hprec, vprec)
255 256 from_text = classmethod(from_text) 257
258 - def to_wire(self, file, compress = None, origin = None):
259 if self.latitude[0] < 0: 260 sign = -1 261 degrees = long(-1 * self.latitude[0]) 262 else: 263 sign = 1 264 degrees = long(self.latitude[0]) 265 milliseconds = (degrees * 3600000 + 266 self.latitude[1] * 60000 + 267 self.latitude[2] * 1000 + 268 self.latitude[3]) * sign 269 latitude = 0x80000000L + milliseconds 270 if self.longitude[0] < 0: 271 sign = -1 272 degrees = long(-1 * self.longitude[0]) 273 else: 274 sign = 1 275 degrees = long(self.longitude[0]) 276 milliseconds = (degrees * 3600000 + 277 self.longitude[1] * 60000 + 278 self.longitude[2] * 1000 + 279 self.longitude[3]) * sign 280 longitude = 0x80000000L + milliseconds 281 altitude = long(self.altitude) + 10000000L 282 size = _encode_size(self.size, "size") 283 hprec = _encode_size(self.horizontal_precision, "horizontal precision") 284 vprec = _encode_size(self.vertical_precision, "vertical precision") 285 wire = struct.pack("!BBBBIII", 0, size, hprec, vprec, latitude, 286 longitude, altitude) 287 file.write(wire)
288
289 - def from_wire(cls, rdclass, rdtype, wire, current, rdlen, origin = None):
290 (version, size, hprec, vprec, latitude, longitude, altitude) = \ 291 struct.unpack("!BBBBIII", wire[current : current + rdlen]) 292 if latitude > 0x80000000L: 293 latitude = float(latitude - 0x80000000L) / 3600000 294 else: 295 latitude = -1 * float(0x80000000L - latitude) / 3600000 296 if latitude < -90.0 or latitude > 90.0: 297 raise dns.exception.FormError, "bad latitude" 298 if longitude > 0x80000000L: 299 longitude = float(longitude - 0x80000000L) / 3600000 300 else: 301 longitude = -1 * float(0x80000000L - longitude) / 3600000 302 if longitude < -180.0 or longitude > 180.0: 303 raise dns.exception.FormError, "bad longitude" 304 altitude = float(altitude) - 10000000.0 305 size = _decode_size(size, "size") 306 hprec = _decode_size(hprec, "horizontal precision") 307 vprec = _decode_size(vprec, "vertical precision") 308 return cls(rdclass, rdtype, latitude, longitude, altitude, 309 size, hprec, vprec)
310 311 from_wire = classmethod(from_wire) 312
313 - def _cmp(self, other):
314 f = cStringIO.StringIO() 315 self.to_wire(f) 316 wire1 = f.getvalue() 317 f.seek(0) 318 f.truncate() 319 other.to_wire(f) 320 wire2 = f.getvalue() 321 f.close() 322 323 return cmp(wire1, wire2)
324
325 - def _get_float_latitude(self):
326 return _tuple_to_float(self.latitude)
327
328 - def _set_float_latitude(self, value):
329 self.latitude = _float_to_tuple(value)
330 331 float_latitude = property(_get_float_latitude, _set_float_latitude, 332 doc="latitude as a floating point value") 333
334 - def _get_float_longitude(self):
335 return _tuple_to_float(self.longitude)
336
337 - def _set_float_longitude(self, value):
338 self.longitude = _float_to_tuple(value)
339 340 float_longitude = property(_get_float_longitude, _set_float_longitude, 341 doc="longitude as a floating point value")
342