Project

General

Profile

Feature #1436

Updated by nobu (Nobuyoshi Nakada) 14 days ago

=begin 
  Please consider this diff which would add support to resolv.rb to permit parsing of LOC resources. 
  I would welcome any criticism or guidance that would make this more suitable for inclusion. 
  Regards, 
 
  JB Smith 
 
 
 
 
  ```diff 
  Index: lib/resolv.rb 
  =================================================================== 
  --- lib/resolv.rb 	 (revision 23349) 
  +++ lib/resolv.rb 	 (working copy) 
  @@ -1835,6 +1835,97 @@ 
         end 
  
         ## 
  +        # Location resource 
  +       
  +        class LOC < Resource 
  +       
  +          TypeValue = 29 # :nodoc: 
  +         
  +          def initialize(version, ssize, hprecision, vprecision, latitude, longitude, altitude) 
  +            @version      = version 
  +            @ssize        = Resolv::LOC::Size.create(ssize) 
  +            @hprecision = Resolv::LOC::Size.create(hprecision) 
  +            @vprecision = Resolv::LOC::Size.create(vprecision) 
  +            @latitude     = Resolv::LOC::Coord.create(latitude) 
  +            @longitude    = Resolv::LOC::Coord.create(longitude) 
  +            @altitude     = Resolv::LOC::Alt.create(altitude) 
  +          end 
  +         
  +          ## 
  +          # Returns the version value for this LOC record which should always be 00 
  +         
  +          attr_reader :version 
  +         
  +          ## 
  +          # The spherical size of this LOC 
  +          # in meters using scientific notation as 2 integers of XeY 
  +         
  +          attr_reader :ssize 
  +         
  +          ## 
  +          # The horizontal precision using ssize type values 
  +          # in meters using scientific notation as 2 integers of XeY 
  +          # for precision use value/2 e.g. 2m = +/-1m 
  +         
  +          attr_reader :hprecision 
  +         
  +          ## 
  +          # The vertical precision using ssize type values 
  +          # in meters using scientific notation as 2 integers of XeY 
  +          # for precision use value/2 e.g. 2m = +/-1m 
  +         
  +          attr_reader :vprecision 
  +         
  +          ## 
  +          # The latitude for this LOC where 2**31 is the equator 
  +          # in thousandths of an arc second as an unsigned 32bit integer 
  +         
  +          attr_reader :latitude 
  +         
  +          ## 
  +          # The longitude for this LOC where 2**31 is the prime meridian 
  +          # in thousandths of an arc second as an unsigned 32bit integer 
  +         
  +          attr_reader :longitude 
  +         
  +          ## 
  +          # The altitude of the LOC above a reference sphere whose surface sits 100km below the WGS84 spheroid 
  +          # in centimeters as an unsigned 32bit integer 
  +         
  +          attr_reader :altitude 
  +         
  +         
  +          def encode_rdata(msg) # :nodoc: 
  +            msg.put_bytes(@version) 
  +            msg.put_bytes(@ssize.scalar) 
  +            msg.put_bytes(@hprecision.scalar) 
  +            msg.put_bytes(@vprecision.scalar) 
  +            msg.put_bytes(@latitude.coordinates) 
  +            msg.put_bytes(@longitude.coordinates) 
  +            msg.put_bytes(@altitude.altitude) 
  +          end 
  +         
  +          def self.decode_rdata(msg) # :nodoc: 
  +            version      = msg.get_bytes(1) 
  +            ssize        = msg.get_bytes(1) 
  +            hprecision = msg.get_bytes(1) 
  +            vprecision = msg.get_bytes(1) 
  +            latitude     = msg.get_bytes(4) 
  +            longitude    = msg.get_bytes(4) 
  +            altitude     = msg.get_bytes(4) 
  +            return self.new( 
  +              version,  
  +              Resolv::LOC::Size.new(ssize),  
  +              Resolv::LOC::Size.new(hprecision),  
  +              Resolv::LOC::Size.new(vprecision),  
  +              Resolv::LOC::Coord.new(latitude,"lat"),  
  +              Resolv::LOC::Coord.new(longitude,"lon"),  
  +              Resolv::LOC::Alt.new(altitude) 
  +            ) 
  +          end 
  +        end 
  + 
  +        ## 
         # A Query type requesting any RR. 
  
         class ANY < Query 
  @@ -1842,7 +1933,7 @@ 
         end 
  
         ClassInsensitiveTypes = [ # :nodoc: 
  -          NS, CNAME, SOA, PTR, HINFO, MINFO, MX, TXT, ANY 
  +          NS, CNAME, SOA, PTR, HINFO, MINFO, MX, TXT, LOC, ANY 
         ] 
  
         ## 
  @@ -2260,6 +2351,223 @@ 
       end 
     end 
  
  +    module LOC 
  +   
  +      ## 
  +      # A Resolv::LOC::Size 
  +     
  +      class Size 
  +     
  +        Regex = /^(\d+\.*\d*)[m]$/ 
  +       
  +        ## 
  +        # Creates a new LOC::Size from +arg+ which may be: 
  +        # 
  +        # LOC::Size:: returns +arg+. 
  +        # String:: +arg+ must match the LOC::Size::Regex constant 
  +       
  +        def self.create(arg) 
  +          case arg 
  +          when Size 
  +            return arg 
  +          when String 
  +            scalar = '' 
  +            if Regex =~ arg 
  +              scalar = [(($1.to_f*(1e2)).to_i.to_s[0].to_i*(2**4)+(($1.to_f*(1e2)).to_i.to_s.length-1))].pack("C") 
  +            else 
  +              raise ArgumentError.new("not a properly formed Size string: " + arg) 
  +            end 
  +            return Size.new(scalar)  
  +          else 
  +            raise ArgumentError.new("cannot interpret as Size: #{arg.inspect}") 
  +          end 
  +        end 
  +       
  +        def initialize(scalar) 
  +          @scalar = scalar 
  +        end 
  +       
  +        ## 
  +        # The raw size 
  +       
  +        attr_reader :scalar 
  +       
  +        def to_s # :nodoc: 
  +          s = @scalar.unpack("H2").join.to_s 
  +          return ((s[0].to_i)*(10**(s[1].to_i-2))).to_s << "m" 
  +        end 
  +       
  +        def inspect # :nodoc: 
  +          return "#<#{self.class} #{self.to_s}>" 
  +        end 
  +       
  +        def ==(other) # :nodoc: 
  +          return @scalar == other.scalar 
  +        end 
  +   
  +        def eql?(other) # :nodoc: 
  +          return self == other 
  +        end 
  +   
  +        def hash # :nodoc: 
  +          return @scalar.hash 
  +        end 
  +       
  +      end 
  +     
  +      ## 
  +      # A Resolv::LOC::Coord 
  +     
  +      class Coord 
  +     
  +        Regex = /^(\d+)\s(\d+)\s(\d+\.\d+)\s([NESW])$/ 
  +       
  +        ## 
  +        # Creates a new LOC::Coord from +arg+ which may be: 
  +        # 
  +        # LOC::Coord:: returns +arg+. 
  +        # String:: +arg+ must match the LOC::Coord::Regex constant 
  +       
  +        def self.create(arg) 
  +          case arg 
  +          when Coord 
  +            return arg 
  +          when String 
  +            coordinates = '' 
  +            if Regex =~ arg &&    $1<180 
  +              hemi = ($4[/([NE])/,1]) || ($4[/([SW])/,1]) ? 1 : -1 
  +              coordinates = [(($1.to_i*(36e5))+($2.to_i*(6e4))+($3.to_f*(1e3)))*hemi+(2**31)].pack("N") 
  +              (orientation ||= '') << $4[[/NS/],1] ? 'lat' : 'lon' 
  +            else 
  +              raise ArgumentError.new("not a properly formed Coord string: " + arg) 
  +            end 
  +            return Coord.new(coordinates,orientation)  
  +          else 
  +            raise ArgumentError.new("cannot interpret as Coord: #{arg.inspect}") 
  +          end 
  +        end 
  +           
  +        def initialize(coordinates,orientation) 
  +          unless coordinates.kind_of?(String) 
  +            raise ArgumentError.new("Coord must be a 32bit unsigned integer in hex format: #{coordinates.inspect}") 
  +          end 
  +          unless orientation.kind_of?(String) && orientation[/^lon$|^lat$/]  
  +            raise ArgumentError.new('Coord expects orientation to be a String argument of "lat" or "lon"') 
  +          end   
  +          @coordinates = coordinates 
  +          @orientation = orientation 
  +        end 
  +   
  +        ## 
  +        # The raw coordinates 
  +   
  +        attr_reader :coordinates 
  +       
  +        ## The orientation of the hemisphere as 'lat' or 'lon' 
  +       
  +        attr_reader :orientation 
  +       
  +        def to_s # :nodoc: 
  +            c = @coordinates.unpack("N").join.to_i 
  +            val        = (c - (2**31)).abs 
  +            fracsecs = (val % 1e3).to_i.to_s  
  +            val        = val / 1e3 
  +            secs       = (val % 60).to_i.to_s  
  +            val        = val / 60 
  +            mins       = (val % 60).to_i.to_s  
  +            degs       = (val / 60).to_i.to_s 
  +            posi = (c >= 2**31) 
  +            case posi 
  +            when true 
  +              hemi = @orientation[/^lat$/] ? "N" : "E" 
  +            else 
  +              hemi = @orientation[/^lon$/] ? "W" : "S" 
  +            end 
  +            return degs << " " << mins << " " << secs << "." << fracsecs << " " << hemi 
  +        end 
  +       
  +        def inspect # :nodoc: 
  +          return "#<#{self.class} #{self.to_s}>" 
  +        end 
  +       
  +        def ==(other) # :nodoc: 
  +          return @coordinates == other.coordinates 
  +        end 
  +   
  +        def eql?(other) # :nodoc: 
  +          return self == other 
  +        end 
  +   
  +        def hash # :nodoc: 
  +          return @coordinates.hash 
  +        end 
  +       
  +      end 
  +     
  +      ## 
  +      # A Resolv::LOC::Alt 
  +     
  +      class Alt 
  +       
  +        Regex = /^([+-]*\d+\.*\d*)[m]$/ 
  +       
  +        ## 
  +        # Creates a new LOC::Alt from +arg+ which may be: 
  +        # 
  +        # LOC::Alt:: returns +arg+. 
  +        # String:: +arg+ must match the LOC::Alt::Regex constant 
  +       
  +        def self.create(arg) 
  +          case arg 
  +          when Alt 
  +            return arg 
  +          when String 
  +            altitude = '' 
  +            if Regex =~ arg 
  +              altitude = [($1.to_f*(1e2))+(1e7)].pack("N") 
  +            else 
  +              raise ArgumentError.new("not a properly formed Alt string: " + arg) 
  +            end 
  +            return Alt.new(altitude)  
  +          else 
  +            raise ArgumentError.new("cannot interpret as Alt: #{arg.inspect}") 
  +          end 
  +        end 
  +       
  +        def initialize(altitude) 
  +          @altitude = altitude 
  +        end 
  +       
  +        ## 
  +        # The raw altitude 
  +       
  +        attr_reader :altitude 
  +       
  +        def to_s # :nodoc: 
  +          a = @altitude.unpack("N").join.to_i 
  +          return ((a.to_f/1e2)-1e5).to_s + "m" 
  +        end 
  +       
  +        def inspect # :nodoc: 
  +          return "#<#{self.class} #{self.to_s}>" 
  +        end 
  +       
  +        def ==(other) # :nodoc: 
  +          return @altitude == other.altitude 
  +        end 
  +   
  +        def eql?(other) # :nodoc: 
  +          return self == other 
  +        end 
  +   
  +        def hash # :nodoc: 
  +          return @altitude.hash 
  +        end 
  +       
  +      end 
  +   
  +    end 
  + 
     ## 
     # Default resolver to use for Resolv class methods. 
 =end 

Back