rubysl-resolv 2.0.0 → 2.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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.