rubysl-resolv 2.0.0 → 2.1.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 1f910ca03a2f2e7fc5ba345a15f7e35786dd07b5
4
- data.tar.gz: 95ab27ed98857c6cc1055b92a6c47d008a9d3ec0
3
+ metadata.gz: 70fb96e5c839213a9643ffac29c5be3498aee4fa
4
+ data.tar.gz: 6ecacc7fa6ebf9243c40c33b3e233905a711a366
5
5
  SHA512:
6
- metadata.gz: 8be3e9e9377c375c5bd7a88f3d6c48a7536af1fe6133e939b738f946af57525b6f70fc48993a015c1a5db04e440890bfbe78ce5dc22c9061c058b628ae18a24a
7
- data.tar.gz: ec78bb44fc70c12de9caee8c9cfa7c9d8542f83b7eda0e43f7bd9dfa86ac38adafd6a7fba69c281993ce82673669534827584f3df96d0763ba28b69678ab387b
6
+ metadata.gz: 9fcdec1fd50945fd720068ec027c820ba6644623c0bb94bc9917fd39fd0507fd81256c549ba77918cc40d45a540b1766d80b4fbb0eed54089e68b77f689a4406
7
+ data.tar.gz: 9fff4616e686c1c6905b46b3c7d5ef4b5233c410b2b0a41cfc2408b0e997d37e7a24b4f23403b27c51c1df50b714e4e87c6fdaf1d77a239d52f168b5614d6a31
data/.travis.yml CHANGED
@@ -1,7 +1,14 @@
1
1
  language: ruby
2
2
  env:
3
3
  - RUBYLIB=lib
4
- script: bundle exec mspec
4
+ - RUBYLIB=
5
+ script: mspec spec
5
6
  rvm:
6
- - 1.9.3
7
- - rbx-nightly-19mode
7
+ - 2.1.0
8
+ - rbx-2
9
+ matrix:
10
+ exclude:
11
+ - rvm: 2.1.0
12
+ env: RUBYLIB=lib
13
+ - rvm: rbx-2
14
+ env: RUBYLIB=
@@ -9,7 +9,7 @@ rescue LoadError
9
9
  end
10
10
 
11
11
  # Resolv is a thread-aware DNS resolver library written in Ruby. Resolv can
12
- # handle multiple DNS requests concurrently without blocking the entire ruby
12
+ # handle multiple DNS requests concurrently without blocking the entire Ruby
13
13
  # interpreter.
14
14
  #
15
15
  # See also resolv-replace.rb to replace the libc resolver with Resolv.
@@ -165,10 +165,11 @@ class Resolv
165
165
  # Resolv::Hosts is a hostname resolver that uses the system hosts file.
166
166
 
167
167
  class Hosts
168
- if /mswin|mingw|bccwin/ =~ RUBY_PLATFORM
168
+ begin
169
+ raise LoadError unless /mswin|mingw|cygwin/ =~ RUBY_PLATFORM
169
170
  require 'win32/resolv'
170
171
  DefaultFileName = Win32::Resolv.get_hosts_path
171
- else
172
+ rescue LoadError
172
173
  DefaultFileName = '/etc/hosts'
173
174
  end
174
175
 
@@ -186,7 +187,7 @@ class Resolv
186
187
  unless @initialized
187
188
  @name2addr = {}
188
189
  @addr2name = {}
189
- open(@filename) {|f|
190
+ open(@filename, 'rb') {|f|
190
191
  f.each {|line|
191
192
  line.sub!(/#.*/, '')
192
193
  addr, hostname, *aliases = line.split(/\s+/)
@@ -506,6 +507,12 @@ class Resolv
506
507
  # #getresource for argument details.
507
508
 
508
509
  def each_resource(name, typeclass, &proc)
510
+ fetch_resource(name, typeclass) {|reply, reply_name|
511
+ extract_resources(reply, reply_name, typeclass, &proc)
512
+ }
513
+ end
514
+
515
+ def fetch_resource(name, typeclass)
509
516
  lazy_initialize
510
517
  requester = make_udp_requester
511
518
  senders = {}
@@ -515,8 +522,9 @@ class Resolv
515
522
  msg.rd = 1
516
523
  msg.add_question(candidate, typeclass)
517
524
  unless sender = senders[[candidate, nameserver, port]]
518
- sender = senders[[candidate, nameserver, port]] =
519
- requester.sender(msg, candidate, nameserver, port)
525
+ sender = requester.sender(msg, candidate, nameserver, port)
526
+ next if !sender
527
+ senders[[candidate, nameserver, port]] = sender
520
528
  end
521
529
  reply, reply_name = requester.request(sender, tout)
522
530
  case reply.rcode
@@ -532,7 +540,7 @@ class Resolv
532
540
  # response will not fit in an untruncated UDP packet.
533
541
  redo
534
542
  else
535
- extract_resources(reply, reply_name, typeclass, &proc)
543
+ yield(reply, reply_name)
536
544
  end
537
545
  return
538
546
  when RCode::NXDomain
@@ -645,7 +653,9 @@ class Resolv
645
653
  begin
646
654
  port = rangerand(1024..65535)
647
655
  udpsock.bind(bind_host, port)
648
- rescue Errno::EADDRINUSE
656
+ rescue Errno::EADDRINUSE, # POSIX
657
+ Errno::EACCES, # SunOS: See PRIV_SYS_NFS in privileges(5)
658
+ Errno::EPERM # FreeBSD: security.mac.portacl.port_high is configurable. See mac_portacl(4).
649
659
  retry
650
660
  end
651
661
  end
@@ -659,7 +669,12 @@ class Resolv
659
669
  def request(sender, tout)
660
670
  start = Time.now
661
671
  timelimit = start + tout
662
- sender.send
672
+ begin
673
+ sender.send
674
+ rescue Errno::EHOSTUNREACH
675
+ # multi-homed IPv6 may generate this
676
+ raise ResolvTimeout
677
+ end
663
678
  while true
664
679
  before_select = Time.now
665
680
  timeout = timelimit - before_select
@@ -685,7 +700,7 @@ class Resolv
685
700
  rescue DecodeError
686
701
  next # broken DNS message ignored
687
702
  end
688
- if s = @senders[[from,msg.id]]
703
+ if s = sender_for(from, msg)
689
704
  break
690
705
  else
691
706
  # unexpected DNS message ignored
@@ -694,6 +709,10 @@ class Resolv
694
709
  return msg, s.data
695
710
  end
696
711
 
712
+ def sender_for(addr, msg)
713
+ @senders[[addr,msg.id]]
714
+ end
715
+
697
716
  def close
698
717
  socks = @socks
699
718
  @socks = nil
@@ -725,9 +744,12 @@ class Resolv
725
744
  af = Socket::AF_INET
726
745
  end
727
746
  next if @socks_hash[bind_host]
728
- sock = UDPSocket.new(af)
747
+ begin
748
+ sock = UDPSocket.new(af)
749
+ rescue Errno::EAFNOSUPPORT
750
+ next # The kernel doesn't support the address family.
751
+ end
729
752
  sock.do_not_reverse_lookup = true
730
- sock.fcntl(Fcntl::F_SETFD, Fcntl::FD_CLOEXEC) if defined? Fcntl::F_SETFD
731
753
  DNS.bind_random_port(sock, bind_host)
732
754
  @socks << sock
733
755
  @socks_hash[bind_host] = sock
@@ -740,11 +762,12 @@ class Resolv
740
762
  end
741
763
 
742
764
  def sender(msg, data, host, port=Port)
765
+ sock = @socks_hash[host.index(':') ? "::" : "0.0.0.0"]
766
+ return nil if !sock
743
767
  service = [host, port]
744
768
  id = DNS.allocate_request_id(host, port)
745
769
  request = msg.encode
746
770
  request[0,2] = [id].pack('n')
747
- sock = @socks_hash[host.index(':') ? "::" : "0.0.0.0"]
748
771
  return @senders[[service, id]] =
749
772
  Sender.new(request, data, sock, host, port)
750
773
  end
@@ -765,6 +788,7 @@ class Resolv
765
788
  attr_reader :data
766
789
 
767
790
  def send
791
+ raise "@sock is nil." if @sock.nil?
768
792
  @sock.send(@msg, 0, @host, @port)
769
793
  end
770
794
  end
@@ -779,7 +803,6 @@ class Resolv
779
803
  sock = UDPSocket.new(is_ipv6 ? Socket::AF_INET6 : Socket::AF_INET)
780
804
  @socks = [sock]
781
805
  sock.do_not_reverse_lookup = true
782
- sock.fcntl(Fcntl::F_SETFD, Fcntl::FD_CLOEXEC) if defined? Fcntl::F_SETFD
783
806
  DNS.bind_random_port(sock, is_ipv6 ? "::" : "0.0.0.0")
784
807
  sock.connect(host, port)
785
808
  end
@@ -808,12 +831,28 @@ class Resolv
808
831
 
809
832
  class Sender < Requester::Sender # :nodoc:
810
833
  def send
834
+ raise "@sock is nil." if @sock.nil?
811
835
  @sock.send(@msg, 0)
812
836
  end
813
837
  attr_reader :data
814
838
  end
815
839
  end
816
840
 
841
+ class MDNSOneShot < UnconnectedUDP # :nodoc:
842
+ def sender(msg, data, host, port=Port)
843
+ id = DNS.allocate_request_id(host, port)
844
+ request = msg.encode
845
+ request[0,2] = [id].pack('n')
846
+ sock = @socks_hash[host.index(':') ? "::" : "0.0.0.0"]
847
+ return @senders[id] =
848
+ UnconnectedUDP::Sender.new(request, data, sock, host, port)
849
+ end
850
+
851
+ def sender_for(addr, msg)
852
+ @senders[msg.id]
853
+ end
854
+ end
855
+
817
856
  class TCP < Requester # :nodoc:
818
857
  def initialize(host, port=Port)
819
858
  super()
@@ -821,7 +860,6 @@ class Resolv
821
860
  @port = port
822
861
  sock = TCPSocket.new(@host, @port)
823
862
  @socks = [sock]
824
- sock.fcntl(Fcntl::F_SETFD, Fcntl::FD_CLOEXEC) if defined? Fcntl::F_SETFD
825
863
  @senders = {}
826
864
  end
827
865
 
@@ -877,7 +915,7 @@ class Resolv
877
915
  values = Array(values)
878
916
  values.each do |t|
879
917
  Numeric === t or raise ArgumentError, "#{t.inspect} is not numeric"
880
- t > 0.0 or raise ArgumentError, "timeout=#{t} must be postive"
918
+ t > 0.0 or raise ArgumentError, "timeout=#{t} must be positive"
881
919
  end
882
920
  @timeouts = values
883
921
  else
@@ -889,7 +927,7 @@ class Resolv
889
927
  nameserver = []
890
928
  search = nil
891
929
  ndots = 1
892
- open(filename) {|f|
930
+ open(filename, 'rb') {|f|
893
931
  f.each {|line|
894
932
  line.sub!(/[#;].*/, '')
895
933
  keyword, *args = line.split(/\s+/)
@@ -1489,6 +1527,7 @@ class Resolv
1489
1527
  end
1490
1528
 
1491
1529
  def get_bytes(len = @limit - @index)
1530
+ raise DecodeError.new("limit exceeded") if @limit < @index + len
1492
1531
  d = @data[@index, len]
1493
1532
  @index += len
1494
1533
  return d
@@ -1516,6 +1555,7 @@ class Resolv
1516
1555
  end
1517
1556
 
1518
1557
  def get_string
1558
+ raise DecodeError.new("limit exceeded") if @limit <= @index
1519
1559
  len = @data[@index].ord
1520
1560
  raise DecodeError.new("limit exceeded") if @limit < @index + 1 + len
1521
1561
  d = @data[@index + 1, len]
@@ -1535,29 +1575,33 @@ class Resolv
1535
1575
  return Name.new(self.get_labels)
1536
1576
  end
1537
1577
 
1538
- def get_labels(limit=nil)
1539
- limit = @index if !limit || @index < limit
1578
+ def get_labels
1579
+ prev_index = @index
1580
+ save_index = nil
1540
1581
  d = []
1541
1582
  while true
1583
+ raise DecodeError.new("limit exceeded") if @limit <= @index
1542
1584
  case @data[@index].ord
1543
1585
  when 0
1544
1586
  @index += 1
1587
+ if save_index
1588
+ @index = save_index
1589
+ end
1545
1590
  return d
1546
1591
  when 192..255
1547
1592
  idx = self.get_unpack('n')[0] & 0x3fff
1548
- if limit <= idx
1593
+ if prev_index <= idx
1549
1594
  raise DecodeError.new("non-backward name pointer")
1550
1595
  end
1551
- save_index = @index
1596
+ prev_index = idx
1597
+ if !save_index
1598
+ save_index = @index
1599
+ end
1552
1600
  @index = idx
1553
- d += self.get_labels(limit)
1554
- @index = save_index
1555
- return d
1556
1601
  else
1557
1602
  d << self.get_label
1558
1603
  end
1559
1604
  end
1560
- return d
1561
1605
  end
1562
1606
 
1563
1607
  def get_label
@@ -1932,10 +1976,10 @@ class Resolv
1932
1976
  attr_reader :strings
1933
1977
 
1934
1978
  ##
1935
- # Returns the first string from +strings+.
1979
+ # Returns the concatenated string from +strings+.
1936
1980
 
1937
1981
  def data
1938
- @strings[0]
1982
+ @strings.join("")
1939
1983
  end
1940
1984
 
1941
1985
  def encode_rdata(msg) # :nodoc:
@@ -1948,6 +1992,97 @@ class Resolv
1948
1992
  end
1949
1993
  end
1950
1994
 
1995
+ ##
1996
+ # Location resource
1997
+
1998
+ class LOC < Resource
1999
+
2000
+ TypeValue = 29 # :nodoc:
2001
+
2002
+ def initialize(version, ssize, hprecision, vprecision, latitude, longitude, altitude)
2003
+ @version = version
2004
+ @ssize = Resolv::LOC::Size.create(ssize)
2005
+ @hprecision = Resolv::LOC::Size.create(hprecision)
2006
+ @vprecision = Resolv::LOC::Size.create(vprecision)
2007
+ @latitude = Resolv::LOC::Coord.create(latitude)
2008
+ @longitude = Resolv::LOC::Coord.create(longitude)
2009
+ @altitude = Resolv::LOC::Alt.create(altitude)
2010
+ end
2011
+
2012
+ ##
2013
+ # Returns the version value for this LOC record which should always be 00
2014
+
2015
+ attr_reader :version
2016
+
2017
+ ##
2018
+ # The spherical size of this LOC
2019
+ # in meters using scientific notation as 2 integers of XeY
2020
+
2021
+ attr_reader :ssize
2022
+
2023
+ ##
2024
+ # The horizontal precision using ssize type values
2025
+ # in meters using scientific notation as 2 integers of XeY
2026
+ # for precision use value/2 e.g. 2m = +/-1m
2027
+
2028
+ attr_reader :hprecision
2029
+
2030
+ ##
2031
+ # The vertical precision using ssize type values
2032
+ # in meters using scientific notation as 2 integers of XeY
2033
+ # for precision use value/2 e.g. 2m = +/-1m
2034
+
2035
+ attr_reader :vprecision
2036
+
2037
+ ##
2038
+ # The latitude for this LOC where 2**31 is the equator
2039
+ # in thousandths of an arc second as an unsigned 32bit integer
2040
+
2041
+ attr_reader :latitude
2042
+
2043
+ ##
2044
+ # The longitude for this LOC where 2**31 is the prime meridian
2045
+ # in thousandths of an arc second as an unsigned 32bit integer
2046
+
2047
+ attr_reader :longitude
2048
+
2049
+ ##
2050
+ # The altitude of the LOC above a reference sphere whose surface sits 100km below the WGS84 spheroid
2051
+ # in centimeters as an unsigned 32bit integer
2052
+
2053
+ attr_reader :altitude
2054
+
2055
+
2056
+ def encode_rdata(msg) # :nodoc:
2057
+ msg.put_bytes(@version)
2058
+ msg.put_bytes(@ssize.scalar)
2059
+ msg.put_bytes(@hprecision.scalar)
2060
+ msg.put_bytes(@vprecision.scalar)
2061
+ msg.put_bytes(@latitude.coordinates)
2062
+ msg.put_bytes(@longitude.coordinates)
2063
+ msg.put_bytes(@altitude.altitude)
2064
+ end
2065
+
2066
+ def self.decode_rdata(msg) # :nodoc:
2067
+ version = msg.get_bytes(1)
2068
+ ssize = msg.get_bytes(1)
2069
+ hprecision = msg.get_bytes(1)
2070
+ vprecision = msg.get_bytes(1)
2071
+ latitude = msg.get_bytes(4)
2072
+ longitude = msg.get_bytes(4)
2073
+ altitude = msg.get_bytes(4)
2074
+ return self.new(
2075
+ version,
2076
+ Resolv::LOC::Size.new(ssize),
2077
+ Resolv::LOC::Size.new(hprecision),
2078
+ Resolv::LOC::Size.new(vprecision),
2079
+ Resolv::LOC::Coord.new(latitude,"lat"),
2080
+ Resolv::LOC::Coord.new(longitude,"lon"),
2081
+ Resolv::LOC::Alt.new(altitude)
2082
+ )
2083
+ end
2084
+ end
2085
+
1951
2086
  ##
1952
2087
  # A Query type requesting any RR.
1953
2088
 
@@ -1956,7 +2091,7 @@ class Resolv
1956
2091
  end
1957
2092
 
1958
2093
  ClassInsensitiveTypes = [ # :nodoc:
1959
- NS, CNAME, SOA, PTR, HINFO, MINFO, MX, TXT, ANY
2094
+ NS, CNAME, SOA, PTR, HINFO, MINFO, MX, TXT, LOC, ANY
1960
2095
  ]
1961
2096
 
1962
2097
  ##
@@ -2381,15 +2516,316 @@ class Resolv
2381
2516
  end
2382
2517
  end
2383
2518
 
2519
+ ##
2520
+ # Resolv::MDNS is a one-shot Multicast DNS (mDNS) resolver. It blindly
2521
+ # makes queries to the mDNS addresses without understanding anything about
2522
+ # multicast ports.
2523
+ #
2524
+ # Information taken form the following places:
2525
+ #
2526
+ # * RFC 6762
2527
+
2528
+ class MDNS < DNS
2529
+
2530
+ ##
2531
+ # Default mDNS Port
2532
+
2533
+ Port = 5353
2534
+
2535
+ ##
2536
+ # Default IPv4 mDNS address
2537
+
2538
+ AddressV4 = '224.0.0.251'
2539
+
2540
+ ##
2541
+ # Default IPv6 mDNS address
2542
+
2543
+ AddressV6 = 'ff02::fb'
2544
+
2545
+ ##
2546
+ # Default mDNS addresses
2547
+
2548
+ Addresses = [
2549
+ [AddressV4, Port],
2550
+ [AddressV6, Port],
2551
+ ]
2552
+
2553
+ ##
2554
+ # Creates a new one-shot Multicast DNS (mDNS) resolver.
2555
+ #
2556
+ # +config_info+ can be:
2557
+ #
2558
+ # nil::
2559
+ # Uses the default mDNS addresses
2560
+ #
2561
+ # Hash::
2562
+ # Must contain :nameserver or :nameserver_port like
2563
+ # Resolv::DNS#initialize.
2564
+
2565
+ def initialize(config_info=nil)
2566
+ if config_info then
2567
+ super({ nameserver_port: Addresses }.merge(config_info))
2568
+ else
2569
+ super(nameserver_port: Addresses)
2570
+ end
2571
+ end
2572
+
2573
+ ##
2574
+ # Iterates over all IP addresses for +name+ retrieved from the mDNS
2575
+ # resolver, provided name ends with "local". If the name does not end in
2576
+ # "local" no records will be returned.
2577
+ #
2578
+ # +name+ can be a Resolv::DNS::Name or a String. Retrieved addresses will
2579
+ # be a Resolv::IPv4 or Resolv::IPv6
2580
+
2581
+ def each_address(name)
2582
+ name = Resolv::DNS::Name.create(name)
2583
+
2584
+ return unless name.to_a.last == 'local'
2585
+
2586
+ super(name)
2587
+ end
2588
+
2589
+ def make_udp_requester # :nodoc:
2590
+ nameserver_port = @config.nameserver_port
2591
+ Requester::MDNSOneShot.new(*nameserver_port)
2592
+ end
2593
+
2594
+ end
2595
+
2596
+ module LOC
2597
+
2598
+ ##
2599
+ # A Resolv::LOC::Size
2600
+
2601
+ class Size
2602
+
2603
+ Regex = /^(\d+\.*\d*)[m]$/
2604
+
2605
+ ##
2606
+ # Creates a new LOC::Size from +arg+ which may be:
2607
+ #
2608
+ # LOC::Size:: returns +arg+.
2609
+ # String:: +arg+ must match the LOC::Size::Regex constant
2610
+
2611
+ def self.create(arg)
2612
+ case arg
2613
+ when Size
2614
+ return arg
2615
+ when String
2616
+ scalar = ''
2617
+ if Regex =~ arg
2618
+ 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")
2619
+ else
2620
+ raise ArgumentError.new("not a properly formed Size string: " + arg)
2621
+ end
2622
+ return Size.new(scalar)
2623
+ else
2624
+ raise ArgumentError.new("cannot interpret as Size: #{arg.inspect}")
2625
+ end
2626
+ end
2627
+
2628
+ def initialize(scalar)
2629
+ @scalar = scalar
2630
+ end
2631
+
2632
+ ##
2633
+ # The raw size
2634
+
2635
+ attr_reader :scalar
2636
+
2637
+ def to_s # :nodoc:
2638
+ s = @scalar.unpack("H2").join.to_s
2639
+ return ((s[0].to_i)*(10**(s[1].to_i-2))).to_s << "m"
2640
+ end
2641
+
2642
+ def inspect # :nodoc:
2643
+ return "#<#{self.class} #{self.to_s}>"
2644
+ end
2645
+
2646
+ def ==(other) # :nodoc:
2647
+ return @scalar == other.scalar
2648
+ end
2649
+
2650
+ def eql?(other) # :nodoc:
2651
+ return self == other
2652
+ end
2653
+
2654
+ def hash # :nodoc:
2655
+ return @scalar.hash
2656
+ end
2657
+
2658
+ end
2659
+
2660
+ ##
2661
+ # A Resolv::LOC::Coord
2662
+
2663
+ class Coord
2664
+
2665
+ Regex = /^(\d+)\s(\d+)\s(\d+\.\d+)\s([NESW])$/
2666
+
2667
+ ##
2668
+ # Creates a new LOC::Coord from +arg+ which may be:
2669
+ #
2670
+ # LOC::Coord:: returns +arg+.
2671
+ # String:: +arg+ must match the LOC::Coord::Regex constant
2672
+
2673
+ def self.create(arg)
2674
+ case arg
2675
+ when Coord
2676
+ return arg
2677
+ when String
2678
+ coordinates = ''
2679
+ if Regex =~ arg && $1<180
2680
+ hemi = ($4[/([NE])/,1]) || ($4[/([SW])/,1]) ? 1 : -1
2681
+ coordinates = [(($1.to_i*(36e5))+($2.to_i*(6e4))+($3.to_f*(1e3)))*hemi+(2**31)].pack("N")
2682
+ (orientation ||= '') << $4[[/NS/],1] ? 'lat' : 'lon'
2683
+ else
2684
+ raise ArgumentError.new("not a properly formed Coord string: " + arg)
2685
+ end
2686
+ return Coord.new(coordinates,orientation)
2687
+ else
2688
+ raise ArgumentError.new("cannot interpret as Coord: #{arg.inspect}")
2689
+ end
2690
+ end
2691
+
2692
+ def initialize(coordinates,orientation)
2693
+ unless coordinates.kind_of?(String)
2694
+ raise ArgumentError.new("Coord must be a 32bit unsigned integer in hex format: #{coordinates.inspect}")
2695
+ end
2696
+ unless orientation.kind_of?(String) && orientation[/^lon$|^lat$/]
2697
+ raise ArgumentError.new('Coord expects orientation to be a String argument of "lat" or "lon"')
2698
+ end
2699
+ @coordinates = coordinates
2700
+ @orientation = orientation
2701
+ end
2702
+
2703
+ ##
2704
+ # The raw coordinates
2705
+
2706
+ attr_reader :coordinates
2707
+
2708
+ ## The orientation of the hemisphere as 'lat' or 'lon'
2709
+
2710
+ attr_reader :orientation
2711
+
2712
+ def to_s # :nodoc:
2713
+ c = @coordinates.unpack("N").join.to_i
2714
+ val = (c - (2**31)).abs
2715
+ fracsecs = (val % 1e3).to_i.to_s
2716
+ val = val / 1e3
2717
+ secs = (val % 60).to_i.to_s
2718
+ val = val / 60
2719
+ mins = (val % 60).to_i.to_s
2720
+ degs = (val / 60).to_i.to_s
2721
+ posi = (c >= 2**31)
2722
+ case posi
2723
+ when true
2724
+ hemi = @orientation[/^lat$/] ? "N" : "E"
2725
+ else
2726
+ hemi = @orientation[/^lon$/] ? "W" : "S"
2727
+ end
2728
+ return degs << " " << mins << " " << secs << "." << fracsecs << " " << hemi
2729
+ end
2730
+
2731
+ def inspect # :nodoc:
2732
+ return "#<#{self.class} #{self.to_s}>"
2733
+ end
2734
+
2735
+ def ==(other) # :nodoc:
2736
+ return @coordinates == other.coordinates
2737
+ end
2738
+
2739
+ def eql?(other) # :nodoc:
2740
+ return self == other
2741
+ end
2742
+
2743
+ def hash # :nodoc:
2744
+ return @coordinates.hash
2745
+ end
2746
+
2747
+ end
2748
+
2749
+ ##
2750
+ # A Resolv::LOC::Alt
2751
+
2752
+ class Alt
2753
+
2754
+ Regex = /^([+-]*\d+\.*\d*)[m]$/
2755
+
2756
+ ##
2757
+ # Creates a new LOC::Alt from +arg+ which may be:
2758
+ #
2759
+ # LOC::Alt:: returns +arg+.
2760
+ # String:: +arg+ must match the LOC::Alt::Regex constant
2761
+
2762
+ def self.create(arg)
2763
+ case arg
2764
+ when Alt
2765
+ return arg
2766
+ when String
2767
+ altitude = ''
2768
+ if Regex =~ arg
2769
+ altitude = [($1.to_f*(1e2))+(1e7)].pack("N")
2770
+ else
2771
+ raise ArgumentError.new("not a properly formed Alt string: " + arg)
2772
+ end
2773
+ return Alt.new(altitude)
2774
+ else
2775
+ raise ArgumentError.new("cannot interpret as Alt: #{arg.inspect}")
2776
+ end
2777
+ end
2778
+
2779
+ def initialize(altitude)
2780
+ @altitude = altitude
2781
+ end
2782
+
2783
+ ##
2784
+ # The raw altitude
2785
+
2786
+ attr_reader :altitude
2787
+
2788
+ def to_s # :nodoc:
2789
+ a = @altitude.unpack("N").join.to_i
2790
+ return ((a.to_f/1e2)-1e5).to_s + "m"
2791
+ end
2792
+
2793
+ def inspect # :nodoc:
2794
+ return "#<#{self.class} #{self.to_s}>"
2795
+ end
2796
+
2797
+ def ==(other) # :nodoc:
2798
+ return @altitude == other.altitude
2799
+ end
2800
+
2801
+ def eql?(other) # :nodoc:
2802
+ return self == other
2803
+ end
2804
+
2805
+ def hash # :nodoc:
2806
+ return @altitude.hash
2807
+ end
2808
+
2809
+ end
2810
+
2811
+ end
2812
+
2384
2813
  ##
2385
2814
  # Default resolver to use for Resolv class methods.
2386
2815
 
2387
2816
  DefaultResolver = self.new
2388
2817
 
2818
+ ##
2819
+ # Replaces the resolvers in the default resolver with +new_resolvers+. This
2820
+ # allows resolvers to be changed for resolv-replace.
2821
+
2822
+ def DefaultResolver.replace_resolvers new_resolvers
2823
+ @resolvers = new_resolvers
2824
+ end
2825
+
2389
2826
  ##
2390
2827
  # Address Regexp to use for matching IP addresses.
2391
2828
 
2392
2829
  AddressRegex = /(?:#{IPv4::Regex})|(?:#{IPv6::Regex})/
2393
2830
 
2394
2831
  end
2395
-
@@ -1,5 +1,5 @@
1
1
  module RubySL
2
2
  module Resolv
3
- VERSION = "2.0.0"
3
+ VERSION = "2.1.0"
4
4
  end
5
5
  end
@@ -21,4 +21,5 @@ Gem::Specification.new do |spec|
21
21
  spec.add_development_dependency "bundler", "~> 1.3"
22
22
  spec.add_development_dependency "rake", "~> 10.0"
23
23
  spec.add_development_dependency "mspec", "~> 1.5"
24
+ spec.add_development_dependency "rubysl-prettyprint", "~> 2.0"
24
25
  end
metadata CHANGED
@@ -1,57 +1,71 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rubysl-resolv
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.0.0
4
+ version: 2.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Brian Shirai
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2013-08-17 00:00:00.000000000 Z
11
+ date: 2014-02-24 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
15
15
  requirement: !ruby/object:Gem::Requirement
16
16
  requirements:
17
- - - ~>
17
+ - - "~>"
18
18
  - !ruby/object:Gem::Version
19
19
  version: '1.3'
20
20
  type: :development
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
- - - ~>
24
+ - - "~>"
25
25
  - !ruby/object:Gem::Version
26
26
  version: '1.3'
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: rake
29
29
  requirement: !ruby/object:Gem::Requirement
30
30
  requirements:
31
- - - ~>
31
+ - - "~>"
32
32
  - !ruby/object:Gem::Version
33
33
  version: '10.0'
34
34
  type: :development
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
- - - ~>
38
+ - - "~>"
39
39
  - !ruby/object:Gem::Version
40
40
  version: '10.0'
41
41
  - !ruby/object:Gem::Dependency
42
42
  name: mspec
43
43
  requirement: !ruby/object:Gem::Requirement
44
44
  requirements:
45
- - - ~>
45
+ - - "~>"
46
46
  - !ruby/object:Gem::Version
47
47
  version: '1.5'
48
48
  type: :development
49
49
  prerelease: false
50
50
  version_requirements: !ruby/object:Gem::Requirement
51
51
  requirements:
52
- - - ~>
52
+ - - "~>"
53
53
  - !ruby/object:Gem::Version
54
54
  version: '1.5'
55
+ - !ruby/object:Gem::Dependency
56
+ name: rubysl-prettyprint
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: '2.0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: '2.0'
55
69
  description: Ruby standard library resolv.
56
70
  email:
57
71
  - brixen@gmail.com
@@ -59,8 +73,8 @@ executables: []
59
73
  extensions: []
60
74
  extra_rdoc_files: []
61
75
  files:
62
- - .gitignore
63
- - .travis.yml
76
+ - ".gitignore"
77
+ - ".travis.yml"
64
78
  - Gemfile
65
79
  - LICENSE
66
80
  - README.md
@@ -84,17 +98,17 @@ require_paths:
84
98
  - lib
85
99
  required_ruby_version: !ruby/object:Gem::Requirement
86
100
  requirements:
87
- - - ~>
101
+ - - "~>"
88
102
  - !ruby/object:Gem::Version
89
103
  version: '2.0'
90
104
  required_rubygems_version: !ruby/object:Gem::Requirement
91
105
  requirements:
92
- - - '>='
106
+ - - ">="
93
107
  - !ruby/object:Gem::Version
94
108
  version: '0'
95
109
  requirements: []
96
110
  rubyforge_project:
97
- rubygems_version: 2.0.7
111
+ rubygems_version: 2.2.1
98
112
  signing_key:
99
113
  specification_version: 4
100
114
  summary: Ruby standard library resolv.