resolv 0.6.0 → 0.7.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
  SHA256:
3
- metadata.gz: 9229d4fa9f694c44c4442d65a94ee9cf0a0516cd642c34046ea1986eb3f14e47
4
- data.tar.gz: 8d04dbe4055ac5ab5da6a71fad40235914b7931c4ef5245599f3b1cc4075c19a
3
+ metadata.gz: 2a32f99ca7eadc476467c7da9dbc5cfeb8152761da79306c91b21182141cbd44
4
+ data.tar.gz: 2605e997fbe45d690ea5cdb82f7128a02fcb03d6b4150f2c6eea44747edb852a
5
5
  SHA512:
6
- metadata.gz: 946a361ded12633ea767ffeb339c28b93bbb29efaaab1c1d6a26b30d151dea6bb10a8246f6b9fa21233f6fb6e0437e4e6a1fbab662bfe74443d24a1b3bffa0ca
7
- data.tar.gz: 64da659522efac0f4cb19fa34c3824e86efa966c8424a90cba358b82a94738186ce51cc3c70d7d5d1a92e0212dc8b7eb6267df1603387457ab38355eec84ee8e
6
+ metadata.gz: 4529d93d71f7139c6eb0a29c7c3d69d0817ad092b9bbb8a6718b8588c0fc43aec45c84db4e3684fb7320548a238c5122198812474d0bac8292ca0891fa687c91
7
+ data.tar.gz: 9fcbff9a156782b6f5a8247262c237b3ba22c1843205a3ddc2d47b185e46fe959a2b62651b21c1573141748b35f8fe6063ab3c445f285d1990b35d1f129eaf44
data/.document ADDED
@@ -0,0 +1,4 @@
1
+ BSDL
2
+ COPYING
3
+ README.md
4
+ lib/
data/README.md CHANGED
@@ -14,15 +14,18 @@ gem 'resolv'
14
14
 
15
15
  And then execute:
16
16
 
17
- $ bundle install
17
+ ```bash
18
+ bundle install
19
+ ```
18
20
 
19
21
  Or install it yourself as:
20
22
 
21
- $ gem install resolv
23
+ ```bash
24
+ gem install resolv
25
+ ```
22
26
 
23
27
  ## Usage
24
28
 
25
-
26
29
  ```ruby
27
30
  p Resolv.getaddress "www.ruby-lang.org"
28
31
  p Resolv.getname "210.251.121.214"
@@ -44,4 +47,3 @@ To install this gem onto your local machine, run `bundle exec rake install`. To
44
47
  ## Contributing
45
48
 
46
49
  Bug reports and pull requests are welcome on GitHub at https://github.com/ruby/resolv.
47
-
@@ -1,5 +1,6 @@
1
1
  require 'mkmf'
2
- if RUBY_ENGINE == "ruby" and have_library('iphlpapi', 'GetNetworkParams')
2
+ if RUBY_ENGINE == "ruby" and have_library('iphlpapi', 'GetNetworkParams', ['windows.h', 'iphlpapi.h'])
3
+ have_library('advapi32', 'RegGetValueW', ['windows.h'])
3
4
  create_makefile('win32/resolv')
4
5
  else
5
6
  File.write('Makefile', "all clean install:\n\t@echo Done: $(@)\n")
@@ -4,12 +4,22 @@
4
4
 
5
5
  =end
6
6
 
7
- require 'win32/registry'
7
+ require 'win32/resolv.so'
8
8
 
9
9
  module Win32
10
10
  module Resolv
11
- API = Registry::API
12
- Error = Registry::Error
11
+ # Error at Win32 API
12
+ class Error < StandardError
13
+ # +code+ Win32 Error code
14
+ # +message+ Formatted message for +code+
15
+ def initialize(code, message)
16
+ super(message)
17
+ @code = code
18
+ end
19
+
20
+ # Win32 error code
21
+ attr_reader :code
22
+ end
13
23
 
14
24
  def self.get_hosts_path
15
25
  path = get_hosts_dir
@@ -34,98 +44,59 @@ module Win32
34
44
  end
35
45
  [ search, nameserver ]
36
46
  end
37
- end
38
- end
39
-
40
- begin
41
- require 'win32/resolv.so'
42
- rescue LoadError
43
- end
44
-
45
- module Win32
46
- #====================================================================
47
- # Windows NT
48
- #====================================================================
49
- module Resolv
50
- module SZ
51
- refine Registry do
52
- # ad hoc workaround for broken registry
53
- def read_s(key)
54
- type, str = read(key)
55
- unless type == Registry::REG_SZ
56
- warn "Broken registry, #{name}\\#{key} was #{Registry.type2name(type)}, ignored"
57
- return String.new
58
- end
59
- str
60
- end
61
- end
62
- end
63
- using SZ
64
-
65
- TCPIP_NT = 'SYSTEM\CurrentControlSet\Services\Tcpip\Parameters'
66
47
 
67
48
  class << self
68
49
  private
69
50
  def get_hosts_dir
70
- Registry::HKEY_LOCAL_MACHINE.open(TCPIP_NT) do |reg|
71
- reg.read_s_expand('DataBasePath')
51
+ tcpip_params do |params|
52
+ params.value('DataBasePath')
72
53
  end
73
54
  end
74
55
 
75
56
  def get_info
76
57
  search = nil
77
58
  nameserver = get_dns_server_list
78
- Registry::HKEY_LOCAL_MACHINE.open(TCPIP_NT) do |reg|
79
- begin
80
- slist = reg.read_s('SearchList')
81
- search = slist.split(/,\s*/) unless slist.empty?
82
- rescue Registry::Error
83
- end
59
+
60
+ tcpip_params do |params|
61
+ slist = params.value('SearchList')
62
+ search = slist.split(/,\s*/) if slist and !slist.empty?
84
63
 
85
64
  if add_search = search.nil?
86
65
  search = []
87
- begin
88
- nvdom = reg.read_s('NV Domain')
89
- unless nvdom.empty?
90
- @search = [ nvdom ]
91
- if reg.read_i('UseDomainNameDevolution') != 0
92
- if /^\w+\./ =~ nvdom
93
- devo = $'
94
- end
66
+ domain = params.value('Domain')
67
+
68
+ if domain and !domain.empty?
69
+ search = [ domain ]
70
+ udmnd = params.value('UseDomainNameDevolution')
71
+ if udmnd&.nonzero?
72
+ if /^\w+\./ =~ domain
73
+ devo = $'
95
74
  end
96
75
  end
97
- rescue Registry::Error
98
76
  end
99
77
  end
100
78
 
101
- reg.open('Interfaces') do |h|
102
- h.each_key do |iface, |
103
- h.open(iface) do |regif|
104
- next unless ns = %w[NameServer DhcpNameServer].find do |key|
105
- begin
106
- ns = regif.read_s(key)
107
- rescue Registry::Error
108
- else
109
- break ns.split(/[,\s]\s*/) unless ns.empty?
110
- end
111
- end
112
- next if (nameserver & ns).empty?
79
+ params.open('Interfaces') do |reg|
80
+ reg.each_key do |iface|
81
+ next unless ns = %w[NameServer DhcpNameServer].find do |key|
82
+ ns = iface.value(key)
83
+ break ns.split(/[,\s]\s*/) if ns and !ns.empty?
84
+ end
85
+
86
+ next if (nameserver & ns).empty?
113
87
 
114
- if add_search
115
- begin
116
- [ 'Domain', 'DhcpDomain' ].each do |key|
117
- dom = regif.read_s(key)
118
- unless dom.empty?
119
- search.concat(dom.split(/,\s*/))
120
- break
121
- end
122
- end
123
- rescue Registry::Error
88
+ if add_search
89
+ [ 'Domain', 'DhcpDomain' ].each do |key|
90
+ dom = iface.value(key)
91
+ if dom and !dom.empty?
92
+ search.concat(dom.split(/,\s*/))
93
+ break
124
94
  end
125
95
  end
126
96
  end
127
97
  end
128
98
  end
99
+
129
100
  search << devo if add_search and devo
130
101
  end
131
102
  [ search.uniq, nameserver.uniq ]
@@ -1,22 +1,56 @@
1
1
  #include <ruby.h>
2
2
  #include <ruby/encoding.h>
3
3
  #include <windows.h>
4
+ #include <windns.h>
4
5
  #ifndef NTDDI_VERSION
5
6
  #define NTDDI_VERSION 0x06000000
6
7
  #endif
7
8
  #include <iphlpapi.h>
8
9
 
10
+ #ifndef numberof
11
+ #define numberof(array) ((int)(sizeof(array) / sizeof((array)[0])))
12
+ #endif
13
+
9
14
  static VALUE
10
15
  w32error_make_error(DWORD e)
11
16
  {
12
- VALUE code = ULONG2NUM(e);
13
- return rb_class_new_instance(1, &code, rb_path2class("Win32::Resolv::Error"));
17
+ char buffer[512], *p;
18
+ DWORD source = 0;
19
+ VALUE args[2];
20
+ if (!FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM |
21
+ FORMAT_MESSAGE_IGNORE_INSERTS, &source, e,
22
+ MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US),
23
+ buffer, sizeof(buffer), NULL)) {
24
+ snprintf(buffer, sizeof(buffer), "Unknown Error %lu", (unsigned long)e);
25
+ }
26
+ p = buffer;
27
+ while ((p = strpbrk(p, "\r\n")) != NULL) {
28
+ memmove(p, p + 1, strlen(p));
29
+ if (!p[1]) {
30
+ p[0] = '\0';
31
+ break;
32
+ }
33
+ }
34
+ args[0] = ULONG2NUM(e);
35
+ args[1] = rb_str_new_cstr(buffer);
36
+ return rb_class_new_instance(2, args, rb_path2class("Win32::Resolv::Error"));
14
37
  }
15
38
 
16
39
  static void
17
- w32error_raise(DWORD e)
40
+ w32error_check(DWORD e)
41
+ {
42
+ if (e != NO_ERROR) {
43
+ rb_exc_raise(w32error_make_error(e));
44
+ }
45
+ }
46
+
47
+ static VALUE
48
+ wchar_to_utf8(const WCHAR *w, int n)
18
49
  {
19
- rb_exc_raise(w32error_make_error(e));
50
+ int clen = WideCharToMultiByte(CP_UTF8, 0, w, n, NULL, 0, NULL, NULL);
51
+ VALUE str = rb_enc_str_new(NULL, clen, rb_utf8_encoding());
52
+ WideCharToMultiByte(CP_UTF8, 0, w, n, RSTRING_PTR(str), clen, NULL, NULL);
53
+ return str;
20
54
  }
21
55
 
22
56
  static VALUE
@@ -28,9 +62,7 @@ get_dns_server_list(VALUE self)
28
62
  VALUE buf, nameservers = Qnil;
29
63
 
30
64
  ret = GetNetworkParams(NULL, &buflen);
31
- if (ret != NO_ERROR && ret != ERROR_BUFFER_OVERFLOW) {
32
- w32error_raise(ret);
33
- }
65
+ if (ret != ERROR_BUFFER_OVERFLOW) w32error_check(ret);
34
66
  fixedinfo = ALLOCV(buf, buflen);
35
67
  ret = GetNetworkParams(fixedinfo, &buflen);
36
68
  if (ret == NO_ERROR) {
@@ -44,18 +76,181 @@ get_dns_server_list(VALUE self)
44
76
  } while ((ipaddr = ipaddr->Next) != NULL);
45
77
  }
46
78
  ALLOCV_END(buf);
47
- if (ret != NO_ERROR) w32error_raise(ret);
79
+ w32error_check(ret);
48
80
 
49
81
  return nameservers;
50
82
  }
51
83
 
84
+
85
+ static const WCHAR TCPIP_Params[] = L"SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Parameters";
86
+
87
+ static void
88
+ hkey_finalize(void *p)
89
+ {
90
+ RegCloseKey((HKEY)p);
91
+ }
92
+
93
+ static const rb_data_type_t hkey_type = {
94
+ "RegKey",
95
+ {0, hkey_finalize},
96
+ 0, 0, RUBY_TYPED_FREE_IMMEDIATELY,
97
+ };
98
+
99
+ static VALUE
100
+ hkey_close(VALUE self)
101
+ {
102
+ RegCloseKey((HKEY)DATA_PTR(self));
103
+ DATA_PTR(self) = 0;
104
+ return self;
105
+ }
106
+
107
+ static VALUE reg_key_class;
108
+
109
+ static VALUE
110
+ reg_open_key(VALUE klass, HKEY hkey, const WCHAR *wname)
111
+ {
112
+ VALUE k = TypedData_Wrap_Struct(klass, &hkey_type, NULL);
113
+ DWORD e = RegOpenKeyExW(hkey, wname, 0, KEY_READ, (HKEY *)&DATA_PTR(k));
114
+ if (e == ERROR_FILE_NOT_FOUND) return Qnil;
115
+ w32error_check(e);
116
+ return rb_ensure(rb_yield, k, hkey_close, k);
117
+ }
118
+
119
+ static VALUE
120
+ tcpip_params_open(VALUE klass)
121
+ {
122
+ return reg_open_key(reg_key_class, HKEY_LOCAL_MACHINE, TCPIP_Params);
123
+ }
124
+
125
+ static int
126
+ to_wname(VALUE *name, WCHAR *wname, int wlen)
127
+ {
128
+ const char *n = StringValueCStr(*name);
129
+ int nlen = RSTRING_LEN(*name);
130
+ int len = MultiByteToWideChar(CP_UTF8, 0, n, nlen, wname, wlen - 1);
131
+ if (len == 0) w32error_check(GetLastError());
132
+ if (len >= wlen) rb_raise(rb_eArgError, "too long name");
133
+ wname[len] = L'\0';
134
+ return len;
135
+ }
136
+
137
+ static VALUE
138
+ reg_open(VALUE self, VALUE name)
139
+ {
140
+ HKEY hkey = DATA_PTR(self);
141
+ WCHAR wname[256];
142
+ to_wname(&name, wname, numberof(wname));
143
+ return reg_open_key(CLASS_OF(self), hkey, wname);
144
+ }
145
+
146
+
147
+ static VALUE
148
+ reg_each_key(VALUE self)
149
+ {
150
+ WCHAR wname[256];
151
+ HKEY hkey = DATA_PTR(self);
152
+ VALUE k = TypedData_Wrap_Struct(CLASS_OF(self), &hkey_type, NULL);
153
+ DWORD i, e, n;
154
+ for (i = 0; n = numberof(wname), (e = RegEnumKeyExW(hkey, i, wname, &n, NULL, NULL, NULL, NULL)) == ERROR_SUCCESS; i++) {
155
+ e = RegOpenKeyExW(hkey, wname, 0, KEY_READ, (HKEY *)&DATA_PTR(k));
156
+ w32error_check(e);
157
+ rb_ensure(rb_yield, k, hkey_close, k);
158
+ }
159
+ if (e != ERROR_NO_MORE_ITEMS) w32error_check(e);
160
+ return self;
161
+ }
162
+
163
+ static inline DWORD
164
+ swap_dw(DWORD x)
165
+ {
166
+ #if defined(_MSC_VER)
167
+ return _byteswap_ulong(x);
168
+ #else
169
+ return __builtin_bswap32(x);
170
+ #endif
171
+ }
172
+
173
+ static VALUE
174
+ reg_value(VALUE self, VALUE name)
175
+ {
176
+ HKEY hkey = DATA_PTR(self);
177
+ DWORD type = 0, size = 0, e;
178
+ VALUE result, value_buffer;
179
+ void *buffer;
180
+ WCHAR wname[256];
181
+ to_wname(&name, wname, numberof(wname));
182
+ e = RegGetValueW(hkey, NULL, wname, RRF_RT_ANY, &type, NULL, &size);
183
+ if (e == ERROR_FILE_NOT_FOUND) return Qnil;
184
+ w32error_check(e);
185
+ # define get_value_2nd(data, dsize) do { \
186
+ DWORD type2 = type; \
187
+ w32error_check(RegGetValueW(hkey, NULL, wname, RRF_RT_ANY, &type2, data, dsize)); \
188
+ if (type != type2) { \
189
+ rb_raise(rb_eRuntimeError, "registry value type changed %lu -> %lu", \
190
+ (unsigned long)type, (unsigned long)type2); \
191
+ } \
192
+ } while (0)
193
+
194
+ switch (type) {
195
+ case REG_DWORD: case REG_DWORD_BIG_ENDIAN:
196
+ {
197
+ DWORD d;
198
+ if (size != sizeof(d)) rb_raise(rb_eRuntimeError, "invalid size returned: %lu", (unsigned long)size);
199
+ w32error_check(RegGetValueW(hkey, NULL, wname, RRF_RT_REG_DWORD, &type, &d, &size));
200
+ if (type == REG_DWORD_BIG_ENDIAN) d = swap_dw(d);
201
+ return ULONG2NUM(d);
202
+ }
203
+ case REG_QWORD:
204
+ {
205
+ QWORD q;
206
+ if (size != sizeof(q)) rb_raise(rb_eRuntimeError, "invalid size returned: %lu", (unsigned long)size);
207
+ w32error_check(RegGetValueW(hkey, NULL, wname, RRF_RT_REG_QWORD, &type, &q, &size));
208
+ return ULL2NUM(q);
209
+ }
210
+ case REG_SZ: case REG_MULTI_SZ: case REG_EXPAND_SZ:
211
+ if (size % sizeof(WCHAR)) rb_raise(rb_eRuntimeError, "invalid size returned: %lu", (unsigned long)size);
212
+ buffer = ALLOCV_N(char, value_buffer, size);
213
+ get_value_2nd(buffer, &size);
214
+ if (type == REG_MULTI_SZ) {
215
+ const WCHAR *w = (WCHAR *)buffer;
216
+ result = rb_ary_new();
217
+ size /= sizeof(WCHAR);
218
+ size -= 1;
219
+ for (size_t i = 0; i < size; ++i) {
220
+ int n = lstrlenW(w+i);
221
+ rb_ary_push(result, wchar_to_utf8(w+i, n));
222
+ i += n;
223
+ }
224
+ }
225
+ else {
226
+ result = wchar_to_utf8((WCHAR *)buffer, lstrlenW((WCHAR *)buffer));
227
+ }
228
+ ALLOCV_END(value_buffer);
229
+ break;
230
+ default:
231
+ result = rb_str_new(0, size);
232
+ get_value_2nd(RSTRING_PTR(result), &size);
233
+ rb_str_set_len(result, size);
234
+ break;
235
+ }
236
+ return result;
237
+ }
238
+
52
239
  void
53
240
  InitVM_resolv(void)
54
241
  {
55
242
  VALUE mWin32 = rb_define_module("Win32");
56
243
  VALUE resolv = rb_define_module_under(mWin32, "Resolv");
57
244
  VALUE singl = rb_singleton_class(resolv);
245
+ VALUE regkey = rb_define_class_under(resolv, "registry key", rb_cObject);
246
+
247
+ reg_key_class = regkey;
248
+ rb_undef_alloc_func(regkey);
58
249
  rb_define_private_method(singl, "get_dns_server_list", get_dns_server_list, 0);
250
+ rb_define_private_method(singl, "tcpip_params", tcpip_params_open, 0);
251
+ rb_define_method(regkey, "open", reg_open, 1);
252
+ rb_define_method(regkey, "each_key", reg_each_key, 0);
253
+ rb_define_method(regkey, "value", reg_value, 1);
59
254
  }
60
255
 
61
256
  void
data/lib/resolv.rb CHANGED
@@ -4,6 +4,7 @@ require 'socket'
4
4
  require 'timeout'
5
5
  require 'io/wait'
6
6
  require 'securerandom'
7
+ require 'rbconfig'
7
8
 
8
9
  # Resolv is a thread-aware DNS resolver library written in Ruby. Resolv can
9
10
  # handle multiple DNS requests concurrently without blocking the entire Ruby
@@ -33,7 +34,8 @@ require 'securerandom'
33
34
 
34
35
  class Resolv
35
36
 
36
- VERSION = "0.6.0"
37
+ # The version string
38
+ VERSION = "0.7.0"
37
39
 
38
40
  ##
39
41
  # Looks up the first IP address for +name+.
@@ -177,14 +179,15 @@ class Resolv
177
179
  # Resolv::Hosts is a hostname resolver that uses the system hosts file.
178
180
 
179
181
  class Hosts
180
- if /mswin|mingw|cygwin/ =~ RUBY_PLATFORM and
182
+ if /mswin|cygwin|mingw|bccwin/ =~ RUBY_PLATFORM || ::RbConfig::CONFIG['host_os'] =~ /mswin/
181
183
  begin
182
- require 'win32/resolv'
183
- DefaultFileName = Win32::Resolv.get_hosts_path || IO::NULL
184
+ require 'win32/resolv' unless defined?(Win32::Resolv)
185
+ hosts = Win32::Resolv.get_hosts_path || IO::NULL
184
186
  rescue LoadError
185
187
  end
186
188
  end
187
- DefaultFileName ||= '/etc/hosts'
189
+ # The default file name for host names
190
+ DefaultFileName = hosts || '/etc/hosts'
188
191
 
189
192
  ##
190
193
  # Creates a new Resolv::Hosts, using +filename+ for its data source.
@@ -522,6 +525,8 @@ class Resolv
522
525
  }
523
526
  end
524
527
 
528
+ # :stopdoc:
529
+
525
530
  def fetch_resource(name, typeclass)
526
531
  lazy_initialize
527
532
  truncated = {}
@@ -659,8 +664,20 @@ class Resolv
659
664
  }
660
665
  end
661
666
 
662
- def self.bind_random_port(udpsock, bind_host="0.0.0.0") # :nodoc:
663
- begin
667
+ case RUBY_PLATFORM
668
+ when *[
669
+ # https://www.rfc-editor.org/rfc/rfc6056.txt
670
+ # Appendix A. Survey of the Algorithms in Use by Some Popular Implementations
671
+ /freebsd/, /linux/, /netbsd/, /openbsd/, /solaris/,
672
+ /darwin/, # the same as FreeBSD
673
+ ] then
674
+ def self.bind_random_port(udpsock, bind_host="0.0.0.0") # :nodoc:
675
+ udpsock.bind(bind_host, 0)
676
+ end
677
+ else
678
+ # Sequential port assignment
679
+ def self.bind_random_port(udpsock, bind_host="0.0.0.0") # :nodoc:
680
+ # Ephemeral port number range recommended by RFC 6056
664
681
  port = random(1024..65535)
665
682
  udpsock.bind(bind_host, port)
666
683
  rescue Errno::EADDRINUSE, # POSIX
@@ -983,13 +1000,13 @@ class Resolv
983
1000
  next unless keyword
984
1001
  case keyword
985
1002
  when 'nameserver'
986
- nameserver.concat(args)
1003
+ nameserver.concat(args.each(&:freeze))
987
1004
  when 'domain'
988
1005
  next if args.empty?
989
- search = [args[0]]
1006
+ search = [args[0].freeze]
990
1007
  when 'search'
991
1008
  next if args.empty?
992
- search = args
1009
+ search = args.each(&:freeze)
993
1010
  when 'options'
994
1011
  args.each {|arg|
995
1012
  case arg
@@ -1000,22 +1017,21 @@ class Resolv
1000
1017
  end
1001
1018
  }
1002
1019
  }
1003
- return { :nameserver => nameserver, :search => search, :ndots => ndots }
1020
+ return { :nameserver => nameserver.freeze, :search => search.freeze, :ndots => ndots.freeze }.freeze
1004
1021
  end
1005
1022
 
1006
1023
  def Config.default_config_hash(filename="/etc/resolv.conf")
1007
1024
  if File.exist? filename
1008
- config_hash = Config.parse_resolv_conf(filename)
1025
+ Config.parse_resolv_conf(filename)
1026
+ elsif defined?(Win32::Resolv)
1027
+ search, nameserver = Win32::Resolv.get_resolv_info
1028
+ config_hash = {}
1029
+ config_hash[:nameserver] = nameserver if nameserver
1030
+ config_hash[:search] = [search].flatten if search
1031
+ config_hash
1009
1032
  else
1010
- if /mswin|cygwin|mingw|bccwin/ =~ RUBY_PLATFORM
1011
- require 'win32/resolv'
1012
- search, nameserver = Win32::Resolv.get_resolv_info
1013
- config_hash = {}
1014
- config_hash[:nameserver] = nameserver if nameserver
1015
- config_hash[:search] = [search].flatten if search
1016
- end
1033
+ {}
1017
1034
  end
1018
- config_hash || {}
1019
1035
  end
1020
1036
 
1021
1037
  def lazy_initialize
@@ -1664,6 +1680,7 @@ class Resolv
1664
1680
  prev_index = @index
1665
1681
  save_index = nil
1666
1682
  d = []
1683
+ size = -1
1667
1684
  while true
1668
1685
  raise DecodeError.new("limit exceeded") if @limit <= @index
1669
1686
  case @data.getbyte(@index)
@@ -1684,7 +1701,10 @@ class Resolv
1684
1701
  end
1685
1702
  @index = idx
1686
1703
  else
1687
- d << self.get_label
1704
+ l = self.get_label
1705
+ d << l
1706
+ size += 1 + l.string.bytesize
1707
+ raise DecodeError.new("name label data exceed 255 octets") if size > 255
1688
1708
  end
1689
1709
  end
1690
1710
  end
@@ -2110,7 +2130,14 @@ class Resolv
2110
2130
 
2111
2131
  attr_reader :ttl
2112
2132
 
2113
- ClassHash = {} # :nodoc:
2133
+ ClassHash = Module.new do
2134
+ module_function
2135
+
2136
+ def []=(type_class_value, klass)
2137
+ type_value, class_value = type_class_value
2138
+ Resource.const_set(:"Type#{type_value}_Class#{class_value}", klass)
2139
+ end
2140
+ end
2114
2141
 
2115
2142
  def encode_rdata(msg) # :nodoc:
2116
2143
  raise NotImplementedError.new
@@ -2148,7 +2175,9 @@ class Resolv
2148
2175
  end
2149
2176
 
2150
2177
  def self.get_class(type_value, class_value) # :nodoc:
2151
- return ClassHash[[type_value, class_value]] ||
2178
+ cache = :"Type#{type_value}_Class#{class_value}"
2179
+
2180
+ return (const_defined?(cache) && const_get(cache)) ||
2152
2181
  Generic.create(type_value, class_value)
2153
2182
  end
2154
2183
 
@@ -2577,7 +2606,7 @@ class Resolv
2577
2606
  end
2578
2607
 
2579
2608
  ##
2580
- # Flags for this proprty:
2609
+ # Flags for this property:
2581
2610
  # - Bit 0 : 0 = not critical, 1 = critical
2582
2611
 
2583
2612
  attr_reader :flags
@@ -2898,15 +2927,21 @@ class Resolv
2898
2927
 
2899
2928
  class IPv4
2900
2929
 
2901
- ##
2902
- # Regular expression IPv4 addresses must match.
2903
-
2904
2930
  Regex256 = /0
2905
2931
  |1(?:[0-9][0-9]?)?
2906
2932
  |2(?:[0-4][0-9]?|5[0-5]?|[6-9])?
2907
- |[3-9][0-9]?/x
2933
+ |[3-9][0-9]?/x # :nodoc:
2934
+
2935
+ ##
2936
+ # Regular expression IPv4 addresses must match.
2908
2937
  Regex = /\A(#{Regex256})\.(#{Regex256})\.(#{Regex256})\.(#{Regex256})\z/
2909
2938
 
2939
+ ##
2940
+ # Creates a new IPv4 address from +arg+ which may be:
2941
+ #
2942
+ # IPv4:: returns +arg+.
2943
+ # String:: +arg+ must match the IPv4::Regex constant
2944
+
2910
2945
  def self.create(arg)
2911
2946
  case arg
2912
2947
  when IPv4
@@ -3215,13 +3250,15 @@ class Resolv
3215
3250
 
3216
3251
  end
3217
3252
 
3218
- module LOC
3253
+ module LOC # :nodoc:
3219
3254
 
3220
3255
  ##
3221
3256
  # A Resolv::LOC::Size
3222
3257
 
3223
3258
  class Size
3224
3259
 
3260
+ # Regular expression LOC size must match.
3261
+
3225
3262
  Regex = /^(\d+\.*\d*)[m]$/
3226
3263
 
3227
3264
  ##
@@ -3247,6 +3284,7 @@ class Resolv
3247
3284
  end
3248
3285
  end
3249
3286
 
3287
+ # Internal use; use self.create.
3250
3288
  def initialize(scalar)
3251
3289
  @scalar = scalar
3252
3290
  end
@@ -3284,6 +3322,8 @@ class Resolv
3284
3322
 
3285
3323
  class Coord
3286
3324
 
3325
+ # Regular expression LOC Coord must match.
3326
+
3287
3327
  Regex = /^(\d+)\s(\d+)\s(\d+\.\d+)\s([NESW])$/
3288
3328
 
3289
3329
  ##
@@ -3313,6 +3353,7 @@ class Resolv
3313
3353
  end
3314
3354
  end
3315
3355
 
3356
+ # Internal use; use self.create.
3316
3357
  def initialize(coordinates,orientation)
3317
3358
  unless coordinates.kind_of?(String)
3318
3359
  raise ArgumentError.new("Coord must be a 32bit unsigned integer in hex format: #{coordinates.inspect}")
@@ -3375,6 +3416,8 @@ class Resolv
3375
3416
 
3376
3417
  class Alt
3377
3418
 
3419
+ # Regular expression LOC Alt must match.
3420
+
3378
3421
  Regex = /^([+-]*\d+\.*\d*)[m]$/
3379
3422
 
3380
3423
  ##
@@ -3400,6 +3443,7 @@ class Resolv
3400
3443
  end
3401
3444
  end
3402
3445
 
3446
+ # Internal use; use self.create.
3403
3447
  def initialize(altitude)
3404
3448
  @altitude = altitude
3405
3449
  end
metadata CHANGED
@@ -1,14 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: resolv
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.6.0
4
+ version: 0.7.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Tanaka Akira
8
- autorequire:
9
8
  bindir: exe
10
9
  cert_chain: []
11
- date: 2024-12-13 00:00:00.000000000 Z
10
+ date: 1980-01-02 00:00:00.000000000 Z
12
11
  dependencies: []
13
12
  description: Thread-aware DNS resolver library in Ruby.
14
13
  email:
@@ -18,23 +17,14 @@ extensions:
18
17
  - ext/win32/resolv/extconf.rb
19
18
  extra_rdoc_files: []
20
19
  files:
21
- - ".git-blame-ignore-revs"
22
- - ".github/dependabot.yml"
23
- - ".github/workflows/push_gem.yml"
24
- - ".github/workflows/test.yml"
25
- - ".gitignore"
20
+ - ".document"
26
21
  - BSDL
27
22
  - COPYING
28
- - Gemfile
29
23
  - README.md
30
- - Rakefile
31
- - bin/console
32
- - bin/setup
33
24
  - ext/win32/resolv/extconf.rb
34
25
  - ext/win32/resolv/lib/resolv.rb
35
26
  - ext/win32/resolv/resolv.c
36
27
  - lib/resolv.rb
37
- - resolv.gemspec
38
28
  homepage: https://github.com/ruby/resolv
39
29
  licenses:
40
30
  - Ruby
@@ -42,7 +32,6 @@ licenses:
42
32
  metadata:
43
33
  homepage_uri: https://github.com/ruby/resolv
44
34
  source_code_uri: https://github.com/ruby/resolv
45
- post_install_message:
46
35
  rdoc_options: []
47
36
  require_paths:
48
37
  - lib
@@ -57,8 +46,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
57
46
  - !ruby/object:Gem::Version
58
47
  version: '0'
59
48
  requirements: []
60
- rubygems_version: 3.5.11
61
- signing_key:
49
+ rubygems_version: 3.6.9
62
50
  specification_version: 4
63
51
  summary: Thread-aware DNS resolver library in Ruby.
64
52
  test_files: []
@@ -1,7 +0,0 @@
1
- # This is a file used by GitHub to ignore the following commits on `git blame`.
2
- #
3
- # You can also do the same thing in your local repository with:
4
- # $ git config --local blame.ignoreRevsFile .git-blame-ignore-revs
5
-
6
- # Expand tabs
7
- 9ae210665a8524554e7c868d3ec67af54b0958bb
@@ -1,6 +0,0 @@
1
- version: 2
2
- updates:
3
- - package-ecosystem: 'github-actions'
4
- directory: '/'
5
- schedule:
6
- interval: 'weekly'
@@ -1,46 +0,0 @@
1
- name: Publish gem to rubygems.org
2
-
3
- on:
4
- push:
5
- tags:
6
- - 'v*'
7
-
8
- permissions:
9
- contents: read
10
-
11
- jobs:
12
- push:
13
- if: github.repository == 'ruby/resolv'
14
- runs-on: ubuntu-latest
15
-
16
- environment:
17
- name: rubygems.org
18
- url: https://rubygems.org/gems/resolv
19
-
20
- permissions:
21
- contents: write
22
- id-token: write
23
-
24
- steps:
25
- - name: Harden Runner
26
- uses: step-security/harden-runner@0080882f6c36860b6ba35c610c98ce87d4e2f26f # v2.10.2
27
- with:
28
- egress-policy: audit
29
-
30
- - uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4.1.4
31
-
32
- - name: Set up Ruby
33
- uses: ruby/setup-ruby@a6e6f86333f0a2523ece813039b8b4be04560854 # v1.190.0
34
- with:
35
- bundler-cache: true
36
- ruby-version: ruby
37
-
38
- - name: Publish to RubyGems
39
- uses: rubygems/release-gem@9e85cb11501bebc2ae661c1500176316d3987059 # v1.1.0
40
-
41
- - name: Create GitHub release
42
- run: |
43
- tag_name="$(git describe --tags --abbrev=0)"
44
- gh release create "${tag_name}" --verify-tag --generate-notes
45
- env:
46
- GITHUB_TOKEN: ${{ secrets.MATZBOT_GITHUB_WORKFLOW_TOKEN }}
@@ -1,52 +0,0 @@
1
- name: test
2
-
3
- on: [push, pull_request]
4
-
5
- jobs:
6
- ruby-versions:
7
- uses: ruby/actions/.github/workflows/ruby_versions.yml@master
8
- with:
9
- engine: cruby-jruby
10
- min_version: 2.5
11
-
12
- build:
13
- needs: ruby-versions
14
- name: build (${{ matrix.ruby }} / ${{ matrix.os }})
15
- strategy:
16
- matrix:
17
- ruby: ${{ fromJson(needs.ruby-versions.outputs.versions) }}
18
- os: [ ubuntu-latest, macos-latest, windows-latest ]
19
- include:
20
- - ruby: mswin
21
- os: windows-latest
22
- exclude:
23
- - ruby: 2.5
24
- os: macos-latest
25
- runs-on: ${{ matrix.os }}
26
- steps:
27
- - uses: actions/checkout@v4
28
- - name: Set up Ruby
29
- uses: ruby/setup-ruby@v1
30
- with:
31
- ruby-version: ${{ matrix.ruby }}
32
- bundler-cache: true
33
- - name: Run test
34
- run: bundle exec rake test
35
- timeout-minutes: 3
36
- continue-on-error: ${{ startsWith(matrix.ruby, 'jruby') }}
37
- - name: Build package
38
- id: build
39
- shell: bash
40
- run: |
41
- if ruby -e 'exit RUBY_VERSION>="3.0."'; then
42
- bundle exec rake build
43
- set pkg/*.gem
44
- echo pkg=$1 >> $GITHUB_OUTPUT
45
- fi
46
- - name: Install gem
47
- run: |
48
- gem install ${{ steps.build.outputs.pkg }}
49
- ruby -rresolv -e 'puts $LOADED_FEATURES.grep(/resolv/)'
50
- ruby -rresolv -e 'puts Resolv::VERSION'
51
- if: ${{ steps.build.outputs.pkg }}
52
- continue-on-error: ${{ startsWith(matrix.ruby, 'jruby') }}
data/.gitignore DELETED
@@ -1,10 +0,0 @@
1
- /.bundle/
2
- /.yardoc
3
- /_yardoc/
4
- /coverage/
5
- /doc/
6
- /pkg/
7
- /spec/reports/
8
- /tmp/
9
-
10
- Gemfile.lock
data/Gemfile DELETED
@@ -1,8 +0,0 @@
1
- source "https://rubygems.org"
2
-
3
- gemspec
4
-
5
- gem "rake"
6
- gem "test-unit"
7
- gem "test-unit-ruby-core"
8
- gem "ruby-core-tasks", github: "ruby/ruby-core-tasks"
data/Rakefile DELETED
@@ -1,18 +0,0 @@
1
- require "bundler/gem_tasks"
2
- require "rake/testtask"
3
-
4
- if RUBY_ENGINE == "ruby"
5
- require "ruby-core/extensiontask"
6
- helper = Bundler::GemHelper.instance
7
- extask = RubyCore::ExtensionTask.new(helper.gemspec)
8
- task :test => :compile
9
- end
10
-
11
- Rake::TestTask.new(:test) do |t|
12
- t.libs.unshift(*extask.libs) if extask
13
- t.libs << "test/lib"
14
- t.ruby_opts << "-rhelper"
15
- t.test_files = FileList["test/**/test_*.rb"]
16
- end
17
-
18
- task :default => :test
data/bin/console DELETED
@@ -1,14 +0,0 @@
1
- #!/usr/bin/env ruby
2
-
3
- require "bundler/setup"
4
- require "resolv"
5
-
6
- # You can add fixtures and/or initialization code here to make experimenting
7
- # with your gem easier. You can also use a different console, if you like.
8
-
9
- # (If you use this, don't forget to add pry to your Gemfile!)
10
- # require "pry"
11
- # Pry.start
12
-
13
- require "irb"
14
- IRB.start(__FILE__)
data/bin/setup DELETED
@@ -1,8 +0,0 @@
1
- #!/usr/bin/env bash
2
- set -euo pipefail
3
- IFS=$'\n\t'
4
- set -vx
5
-
6
- bundle install
7
-
8
- # Do any other automated setup that you need to do here
data/resolv.gemspec DELETED
@@ -1,30 +0,0 @@
1
- name = File.basename(__FILE__, ".gemspec")
2
- version = ["lib", Array.new(name.count("-")+1).join("/")].find do |dir|
3
- break File.foreach(File.join(__dir__, dir, "#{name.tr('-', '/')}.rb")) do |line|
4
- /^\s*VERSION\s*=\s*"(.*)"/ =~ line and break $1
5
- end rescue nil
6
- end
7
-
8
- Gem::Specification.new do |spec|
9
- spec.name = name
10
- spec.version = version
11
- spec.authors = ["Tanaka Akira"]
12
- spec.email = ["akr@fsij.org"]
13
-
14
- spec.summary = %q{Thread-aware DNS resolver library in Ruby.}
15
- spec.description = %q{Thread-aware DNS resolver library in Ruby.}
16
- spec.homepage = "https://github.com/ruby/resolv"
17
- spec.required_ruby_version = Gem::Requirement.new(">= 2.3.0")
18
- spec.licenses = ["Ruby", "BSD-2-Clause"]
19
- spec.extensions << "ext/win32/resolv/extconf.rb"
20
-
21
- spec.metadata["homepage_uri"] = spec.homepage
22
- spec.metadata["source_code_uri"] = spec.homepage
23
-
24
- spec.files = Dir.chdir(File.expand_path('..', __FILE__)) do
25
- `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
26
- end
27
- spec.bindir = "exe"
28
- spec.executables = []
29
- spec.require_paths = ["lib"]
30
- end