net-dns 0.8.0 → 0.20.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.
Files changed (56) hide show
  1. checksums.yaml +6 -14
  2. data/.rspec +1 -0
  3. data/.travis.yml +9 -16
  4. data/CHANGELOG.md +37 -13
  5. data/LICENSE.txt +56 -0
  6. data/README.md +94 -77
  7. data/demo/check_soa.rb +27 -38
  8. data/demo/threads.rb +3 -7
  9. data/lib/net/dns/header.rb +86 -110
  10. data/lib/net/dns/names.rb +31 -31
  11. data/lib/net/dns/packet.rb +148 -158
  12. data/lib/net/dns/question.rb +41 -42
  13. data/lib/net/dns/resolver/socks.rb +47 -55
  14. data/lib/net/dns/resolver/timeouts.rb +19 -30
  15. data/lib/net/dns/resolver.rb +151 -176
  16. data/lib/net/dns/rr/a.rb +45 -55
  17. data/lib/net/dns/rr/aaaa.rb +39 -50
  18. data/lib/net/dns/rr/classes.rb +32 -37
  19. data/lib/net/dns/rr/cname.rb +31 -41
  20. data/lib/net/dns/rr/hinfo.rb +40 -56
  21. data/lib/net/dns/rr/mr.rb +31 -42
  22. data/lib/net/dns/rr/mx.rb +35 -47
  23. data/lib/net/dns/rr/ns.rb +31 -41
  24. data/lib/net/dns/rr/null.rb +10 -15
  25. data/lib/net/dns/rr/ptr.rb +16 -24
  26. data/lib/net/dns/rr/soa.rb +36 -35
  27. data/lib/net/dns/rr/srv.rb +18 -19
  28. data/lib/net/dns/rr/txt.rb +11 -16
  29. data/lib/net/dns/rr/types.rb +118 -109
  30. data/lib/net/dns/rr.rb +107 -117
  31. data/lib/net/dns/version.rb +5 -13
  32. data/lib/net/dns.rb +6 -11
  33. metadata +18 -83
  34. data/.gitignore +0 -8
  35. data/Gemfile +0 -4
  36. data/Rakefile +0 -71
  37. data/fixtures/resolv.conf +0 -4
  38. data/lib/net/dns/core_ext.rb +0 -52
  39. data/net-dns.gemspec +0 -35
  40. data/test/header_test.rb +0 -167
  41. data/test/names_test.rb +0 -21
  42. data/test/packet_test.rb +0 -49
  43. data/test/question_test.rb +0 -83
  44. data/test/resolver/timeouts_test.rb +0 -109
  45. data/test/resolver_test.rb +0 -117
  46. data/test/rr/a_test.rb +0 -113
  47. data/test/rr/aaaa_test.rb +0 -109
  48. data/test/rr/classes_test.rb +0 -85
  49. data/test/rr/cname_test.rb +0 -97
  50. data/test/rr/hinfo_test.rb +0 -117
  51. data/test/rr/mr_test.rb +0 -105
  52. data/test/rr/mx_test.rb +0 -112
  53. data/test/rr/ns_test.rb +0 -86
  54. data/test/rr/types_test.rb +0 -69
  55. data/test/rr_test.rb +0 -131
  56. data/test/test_helper.rb +0 -4
@@ -1,6 +1,5 @@
1
1
  module Net
2
2
  module DNS
3
-
4
3
  # DNS packet header class
5
4
  #
6
5
  # The Net::DNS::Header class represents the header portion of a
@@ -37,7 +36,6 @@ module Net
37
36
  # more or less the same.
38
37
  #
39
38
  class Header
40
-
41
39
  # A wrong +count+ parameter has been passed.
42
40
  class WrongCountError < ArgumentError
43
41
  end
@@ -54,7 +52,6 @@ module Net
54
52
  class Error < StandardError
55
53
  end
56
54
 
57
-
58
55
  # DNS Header RCode handling class
59
56
  #
60
57
  # It should be used internally by Net::DNS::Header class. However, it's still
@@ -103,7 +100,6 @@ module Net
103
100
  # More RCodes has to come for TSIGs and other operations.
104
101
  #
105
102
  class RCode
106
-
107
103
  # Constant for +rcode+ Response Code No Error
108
104
  NOERROR = 0
109
105
  # Constant for +rcode+ Response Code Format Error
@@ -117,33 +113,31 @@ module Net
117
113
  # Constant for +rcode+ Response Code Refused Error
118
114
  REFUSED = 5
119
115
 
120
-
121
-
122
116
  RCodeType = %w[NoError FormErr ServFail NXDomain NotImp
123
- Refused YXDomain YXRRSet NXRRSet NotAuth NotZone]
117
+ Refused YXDomain YXRRSet NXRRSet NotAuth NotZone].freeze
124
118
 
125
119
  RCodeErrorString = ["No errors",
126
- "The name server was unable to interpret the query",
127
- "The name server was unable to process this query due to problem with the name server",
128
- "Domain name referenced in the query does not exists",
129
- "The name server does not support the requested kind of query",
130
- "The name server refuses to perform the specified operation for policy reasons",
131
- "",
132
- "",
133
- "",
134
- "",
135
- ""]
136
-
137
- attr_reader :code, :type, :explanation
120
+ "The name server was unable to interpret the query",
121
+ "The name server was unable to process this query due to problem with the name server",
122
+ "Domain name referenced in the query does not exists",
123
+ "The name server does not support the requested kind of query",
124
+ "The name server refuses to perform the specified operation for policy reasons",
125
+ "",
126
+ "",
127
+ "",
128
+ "",
129
+ "",].freeze
130
+
131
+ attr_reader :code
132
+ attr_reader :type
133
+ attr_reader :explanation
138
134
 
139
135
  def initialize(code)
140
- if (0..10).include? code
141
- @code = code
142
- @type = RCodeType[code]
143
- @explanation = RCodeErrorString[code]
144
- else
145
- raise ArgumentError, "RCode `#{code}' out of range"
146
- end
136
+ raise ArgumentError, "RCode `#{code}' out of range" unless (0..10).cover? code
137
+
138
+ @code = code
139
+ @type = RCodeType[code]
140
+ @explanation = RCodeErrorString[code]
147
141
  end
148
142
 
149
143
  def to_s
@@ -151,7 +145,6 @@ module Net
151
145
  end
152
146
  end
153
147
 
154
-
155
148
  # Constant for +opCode+ query
156
149
  QUERY = 0
157
150
  # Constant for +opCode+ iquery
@@ -159,7 +152,7 @@ module Net
159
152
  # Constant for +opCode+ status
160
153
  STATUS = 2
161
154
  # Array with given strings
162
- OPARR = %w[QUERY IQUERY STATUS]
155
+ OPARR = %w[QUERY IQUERY STATUS].freeze
163
156
 
164
157
  # Reader for +id+ attribute
165
158
  attr_reader :id
@@ -212,11 +205,9 @@ module Net
212
205
  # See also each option for a detailed explanation of usage.
213
206
  #
214
207
  def initialize(arg = {})
215
- if arg.kind_of? Hash
216
- new_from_hash(arg)
217
- else
218
- raise ArgumentError, "Wrong argument class `#{arg.class}'"
219
- end
208
+ raise ArgumentError, "Wrong argument class `#{arg.class}'" unless arg.is_a? Hash
209
+
210
+ new_from_hash(arg)
220
211
  end
221
212
 
222
213
  # Creates a new Net::DNS::Header object from binary data, which is
@@ -232,13 +223,11 @@ module Net
232
223
  # #=> "true" if it comes from authoritative name server
233
224
  #
234
225
  def self.parse(arg)
235
- if arg.kind_of? String
236
- o = allocate
237
- o.send(:new_from_binary, arg)
238
- o
239
- else
240
- raise ArgumentError, "Wrong argument class `#{arg.class}'"
241
- end
226
+ raise ArgumentError, "Wrong argument class `#{arg.class}'" unless arg.is_a? String
227
+
228
+ o = allocate
229
+ o.send(:new_from_binary, arg)
230
+ o
242
231
  end
243
232
 
244
233
  # Inspect method, prints out all the options and relative values.
@@ -253,24 +242,24 @@ module Net
253
242
  # way of display output.
254
243
  #
255
244
  def inspect
256
- ";; id = #@id\n" +
257
- if false # @opCode == "UPDATE"
258
- #do stuff
259
- else
260
- ";; qr = #@qr\t" +
261
- "opCode: #{opCode_str}\t" +
262
- "aa = #@aa\t" +
263
- "tc = #@tc\t" +
264
- "rd = #@rd\n" +
265
- ";; ra = #@ra\t" +
266
- "ad = #@ad\t" +
267
- "cd = #@cd\t" +
268
- "rcode = #{@rCode.type}\n" +
269
- ";; qdCount = #@qdCount\t"+
270
- "anCount = #@anCount\t"+
271
- "nsCount = #@nsCount\t"+
272
- "arCount = #@arCount\n"
273
- end
245
+ ";; id = #{@id}\n" +
246
+ if false # @opCode == "UPDATE"
247
+ # do stuff
248
+ else
249
+ ";; qr = #{@qr}\t" \
250
+ "opCode: #{opCode_str}\t" \
251
+ "aa = #{@aa}\t" \
252
+ "tc = #{@tc}\t" \
253
+ "rd = #{@rd}\n" \
254
+ ";; ra = #{@ra}\t" \
255
+ "ad = #{@ad}\t" \
256
+ "cd = #{@cd}\t" \
257
+ "rcode = #{@rCode.type}\n" \
258
+ ";; qdCount = #{@qdCount}\t" \
259
+ "anCount = #{@anCount}\t" \
260
+ "nsCount = #{@nsCount}\t" \
261
+ "arCount = #{@arCount}\n"
262
+ end
274
263
  end
275
264
 
276
265
  # The Net::DNS::Header#format method prints out the header
@@ -297,7 +286,7 @@ module Net
297
286
  def format
298
287
  del = ("+-" * 16) + "+\n"
299
288
  len = del.length
300
- str = del + "|" + @id.to_s.center(len-3) + "|\n"
289
+ str = del + "|" + @id.to_s.center(len - 3) + "|\n"
301
290
  str += del + "|" + @qr.to_s
302
291
  str += "|" + @opCode.to_s.center(7)
303
292
  str += "|" + @aa.to_s
@@ -307,10 +296,10 @@ module Net
307
296
  str += "|" + @ad.to_s
308
297
  str += "|" + @cd.to_s.center(3)
309
298
  str += "|" + @rCode.to_s.center(7) + "|\n"
310
- str += del + "|" + @qdCount.to_s.center(len-3) + "|\n"
311
- str += del + "|" + @anCount.to_s.center(len-3) + "|\n"
312
- str += del + "|" + @nsCount.to_s.center(len-3) + "|\n"
313
- str += del + "|" + @arCount.to_s.center(len-3) + "|\n" + del
299
+ str += del + "|" + @qdCount.to_s.center(len - 3) + "|\n"
300
+ str += del + "|" + @anCount.to_s.center(len - 3) + "|\n"
301
+ str += del + "|" + @nsCount.to_s.center(len - 3) + "|\n"
302
+ str += del + "|" + @arCount.to_s.center(len - 3) + "|\n" + del
314
303
  str
315
304
  end
316
305
 
@@ -323,8 +312,8 @@ module Net
323
312
  def data
324
313
  arr = []
325
314
  arr.push(@id)
326
- arr.push((@qr<<7)|(@opCode<<3)|(@aa<<2)|(@tc<<1)|@rd)
327
- arr.push((@ra<<7)|(@ad<<5)|(@cd<<4)|@rCode.code)
315
+ arr.push((@qr << 7) | (@opCode << 3) | (@aa << 2) | (@tc << 1) | @rd)
316
+ arr.push((@ra << 7) | (@ad << 5) | (@cd << 4) | @rCode.code)
328
317
  arr.push(@qdCount)
329
318
  arr.push(@anCount)
330
319
  arr.push(@nsCount)
@@ -336,11 +325,9 @@ module Net
336
325
  # performing security tests.
337
326
  #
338
327
  def id=(val)
339
- if (0..65535).include? val
340
- @id = val
341
- else
342
- raise ArgumentError, "ID `#{val}' out of range"
343
- end
328
+ raise ArgumentError, "ID `#{val}' out of range" unless (0..65_535).cover? val
329
+
330
+ @id = val
344
331
  end
345
332
 
346
333
  # Checks whether the header is a query (+qr+ bit set to 0)
@@ -361,7 +348,7 @@ module Net
361
348
  @qr = 1
362
349
  when false
363
350
  @qr = 0
364
- when 0,1
351
+ when 0, 1
365
352
  @qr = val
366
353
  else
367
354
  raise ArgumentError, ":qr must be true(or 1) or false(or 0)"
@@ -399,11 +386,9 @@ module Net
399
386
  # header.opCode = Header::STATUS
400
387
  #
401
388
  def opCode=(val)
402
- if (0..2).include? val
403
- @opCode = val
404
- else
405
- raise WrongOpcodeError, "Wrong opCode value (#{val}), must be QUERY, IQUERY or STATUS"
406
- end
389
+ raise WrongOpcodeError, "Wrong opCode value (#{val}), must be QUERY, IQUERY or STATUS" unless (0..2).cover? val
390
+
391
+ @opCode = val
407
392
  end
408
393
 
409
394
  # Checks whether the response is authoritative
@@ -433,7 +418,7 @@ module Net
433
418
  @aa = 1
434
419
  when false
435
420
  @aa = 0
436
- when 0,1
421
+ when 0, 1
437
422
  @aa = val
438
423
  else
439
424
  raise ArgumentError, ":aa must be true(or 1) or false(or 0)"
@@ -471,7 +456,7 @@ module Net
471
456
  @tc = 1
472
457
  when false
473
458
  @tc = 0
474
- when 0,1
459
+ when 0, 1
475
460
  @tc = val
476
461
  else
477
462
  raise ArgumentError, ":tc must be true(or 1) or false(or 0)"
@@ -536,7 +521,7 @@ module Net
536
521
  @ra = 1
537
522
  when false
538
523
  @ra = 0
539
- when 0,1
524
+ when 0, 1
540
525
  @ra = val
541
526
  else
542
527
  raise ArgumentError, ":ra must be true(or 1) or false(or 0)"
@@ -560,7 +545,7 @@ module Net
560
545
  @cd = 1
561
546
  when false
562
547
  @cd = 0
563
- when 0,1
548
+ when 0, 1
564
549
  @cd = val
565
550
  else
566
551
  raise ArgumentError, ":cd must be true(or 1) or false(or 0)"
@@ -588,7 +573,7 @@ module Net
588
573
  @ad = 1
589
574
  when false
590
575
  @ad = 0
591
- when 0,1
576
+ when 0, 1
592
577
  @ad = val
593
578
  else
594
579
  raise ArgumentError, ":ad must be true(or 1) or false(or 0)"
@@ -604,7 +589,7 @@ module Net
604
589
  # #=> was unable to interpret the query
605
590
  #
606
591
  def rCode_str
607
- return rCode.type, rCode.explanation
592
+ [rCode.type, rCode.explanation]
608
593
  end
609
594
 
610
595
  # Checks for errors in the DNS packet
@@ -627,44 +612,36 @@ module Net
627
612
  # Sets the number of entries in a question section
628
613
  #
629
614
  def qdCount=(val)
630
- if (0..65535).include? val
631
- @qdCount = val
632
- else
633
- raise WrongCountError, "Wrong number of count (#{val}), must be 0-65535"
634
- end
615
+ raise WrongCountError, "Wrong number of count (#{val}), must be 0-65535" unless (0..65_535).cover? val
616
+
617
+ @qdCount = val
635
618
  end
636
619
 
637
620
  # Sets the number of RRs in an answer section
638
621
  #
639
622
  def anCount=(val)
640
- if (0..65535).include? val
641
- @anCount = val
642
- else
643
- raise WrongCountError, "Wrong number of count (#{val}), must be 0-65535"
644
- end
623
+ raise WrongCountError, "Wrong number of count (#{val}), must be 0-65535" unless (0..65_535).cover? val
624
+
625
+ @anCount = val
645
626
  end
646
627
 
647
628
  # Sets the number of RRs in an authority section
648
629
  #
649
630
  def nsCount=(val)
650
- if (0..65535).include? val
651
- @nsCount = val
652
- else
653
- raise WrongCountError, "Wrong number of count (#{val}), must be 0-65535"
654
- end
631
+ raise WrongCountError, "Wrong number of count (#{val}), must be 0-65535" unless (0..65_535).cover? val
632
+
633
+ @nsCount = val
655
634
  end
656
635
 
657
636
  # Sets the number of RRs in an addictional section
658
637
  #
659
638
  def arCount=(val)
660
- if (0..65535).include? val
661
- @arCount = val
662
- else
663
- raise WrongCountError, "Wrong number of count: `#{val}' must be 0-65535"
664
- end
639
+ raise WrongCountError, "Wrong number of count: `#{val}' must be 0-65535" unless (0..65_535).cover? val
640
+
641
+ @arCount = val
665
642
  end
666
643
 
667
- private
644
+ private
668
645
 
669
646
  def new_from_scratch
670
647
  @id = genID # generate ad unique id
@@ -679,13 +656,14 @@ module Net
679
656
  unless str.size == Net::DNS::HFIXEDSZ
680
657
  raise ArgumentError, "Header binary data has wrong size: `#{str.size}' bytes"
681
658
  end
659
+
682
660
  arr = str.unpack("n C2 n4")
683
- @id = arr[0]
661
+ @id = arr[0]
684
662
  @qr = (arr[1] >> 7) & 0x01
685
663
  @opCode = (arr[1] >> 3) & 0x0F
686
664
  @aa = (arr[1] >> 2) & 0x01
687
665
  @tc = (arr[1] >> 1) & 0x01
688
- @rd = arr[1] & 0x1
666
+ @rd = arr[1] & 0x1
689
667
  @ra = (arr[2] >> 7) & 0x01
690
668
  @ad = (arr[2] >> 5) & 0x01
691
669
  @cd = (arr[2] >> 4) & 0x01
@@ -698,16 +676,14 @@ module Net
698
676
 
699
677
  def new_from_hash(hash)
700
678
  new_from_scratch
701
- hash.each do |key,val|
702
- eval "self.#{key.to_s} = val"
679
+ hash.each do |key, val|
680
+ eval "self.#{key} = val"
703
681
  end
704
682
  end
705
683
 
706
684
  def genID
707
- rand(65535)
685
+ rand(65_535)
708
686
  end
709
-
710
687
  end
711
-
712
688
  end
713
689
  end
data/lib/net/dns/names.rb CHANGED
@@ -1,8 +1,6 @@
1
1
  module Net # :nodoc:
2
2
  module DNS
3
-
4
3
  module Names
5
-
6
4
  # Base error class.
7
5
  class Error < StandardError
8
6
  end
@@ -11,11 +9,10 @@ module Net # :nodoc:
11
9
  class ExpandError < Error
12
10
  end
13
11
 
14
-
15
12
  INT16SZ = 2
16
13
 
17
14
  # Expand a compressed name in a DNS Packet object. Please
18
- # see RFC1025 for an explanation of how the compression
15
+ # see RFC1035 for an explanation of how the compression
19
16
  # in DNS packets works, how may it be useful and how should
20
17
  # be handled.
21
18
  #
@@ -23,29 +20,33 @@ module Net # :nodoc:
23
20
  # offset, which indicates the point in the packet in which the
24
21
  # parsing has arrived.
25
22
  #
26
- def dn_expand(packet,offset)
23
+ def dn_expand(packet, offset)
27
24
  name = ""
28
25
  packetlen = packet.size
29
- while true
30
- raise ExpandError, "Offset is greater than packet lenght!" if packetlen < (offset+1)
31
- len = packet.unpack("@#{offset} C")[0]
26
+ loop do
27
+ raise ExpandError, "Offset is greater than packet length!" if packetlen < (offset + 1)
28
+
29
+ len = packet.unpack1("@#{offset} C")
32
30
 
33
31
  if len == 0
34
32
  offset += 1
35
33
  break
36
34
  elsif (len & 0xC0) == 0xC0
37
- raise ExpandError, "Packet ended before offset expand" if packetlen < (offset+INT16SZ)
38
- ptr = packet.unpack("@#{offset} n")[0]
35
+ raise ExpandError, "Packet ended before offset expand" if packetlen < (offset + INT16SZ)
36
+
37
+ ptr = packet.unpack1("@#{offset} n")
39
38
  ptr &= 0x3FFF
40
- name2 = dn_expand(packet,ptr)[0]
41
- raise ExpandError, "Packet is malformed!" if name2 == nil
39
+ name2 = dn_expand(packet, ptr)[0]
40
+ raise ExpandError, "Packet is malformed!" if name2.nil?
41
+
42
42
  name += name2
43
43
  offset += INT16SZ
44
44
  break
45
45
  else
46
46
  offset += 1
47
- raise ExpandError, "No expansion found" if packetlen < (offset+len)
48
- elem = packet[offset..offset+len-1]
47
+ raise ExpandError, "No expansion found" if packetlen < (offset + len)
48
+
49
+ elem = packet[offset..offset + len - 1]
49
50
  name += "#{elem}."
50
51
  offset += len
51
52
  end
@@ -54,16 +55,18 @@ module Net # :nodoc:
54
55
  end
55
56
 
56
57
  def pack_name(name)
57
- if name.size > 255
58
+ if name.size > 255
58
59
  raise ArgumentError, "Name may not exceed 255 chars"
59
60
  end
61
+
60
62
  arr = name.split(".")
61
63
  str = ""
62
64
  arr.each do |elem|
63
65
  if elem.size > 63
64
66
  raise ArgumentError, "Label may not exceed 63 chars"
65
67
  end
66
- str += [elem.size,elem].pack("Ca*")
68
+
69
+ str += [elem.size, elem].pack("Ca*")
67
70
  end
68
71
  str += [0].pack("C")
69
72
  str
@@ -74,45 +77,42 @@ module Net # :nodoc:
74
77
  ar = []
75
78
  string = ""
76
79
  arr.size.times do |i|
77
- x = i+1
80
+ x = i + 1
78
81
  elem = arr[-x]
79
82
  len = elem.size
80
- string = ((string.reverse)+([len,elem].pack("Ca*")).reverse).reverse
83
+ string = (string.reverse + [len, elem].pack("Ca*").reverse).reverse
81
84
  ar.unshift(string)
82
85
  end
83
- return ar
86
+ ar
84
87
  end
85
88
 
86
- def dn_comp(name,offset,compnames)
89
+ def dn_comp(name, offset, compnames)
87
90
  names = {}
88
91
  ptr = 0
89
92
  str = ""
90
93
  arr = names_array(name)
91
94
  arr.each do |entry|
92
- if compnames.has_key?(entry)
95
+ if compnames.key?(entry)
93
96
  ptr = 0xC000 | compnames[entry]
94
97
  str += [ptr].pack("n")
95
98
  offset += INT16SZ
96
99
  break
97
100
  else
98
- len = entry.unpack("C")[0]
101
+ len = entry.unpack1("C")
99
102
  elem = entry[1..len]
100
- str += [len,elem].pack("Ca*")
101
- names.update({"#{entry}" => offset})
103
+ str += [len, elem].pack("Ca*")
104
+ names.update(entry.to_s => offset)
102
105
  offset += len
103
106
  end
104
107
  end
105
- return str,offset,names
108
+ [str, offset, names]
106
109
  end
107
110
 
108
111
  def valid?(name)
109
- if name =~ /^([a-z0-9]([-a-z0-9]*[a-z0-9])?\.)+((a[cdefgilmnoqrstuwxz]|aero|arpa)|(b[abdefghijmnorstvwyz]|biz)|(c[acdfghiklmnorsuvxyz]|cat|com|coop)|d[ejkmoz]|(e[ceghrstu]|edu)|f[ijkmor]|(g[abdefghilmnpqrstuwy]|gov)|h[kmnrtu]|(i[delmnoqrst]|info|int)|(j[emop]|jobs)|k[eghimnprwyz]|l[abcikrstuvy]|(m[acdghklmnopqrstuvwxyz]|mil|mobi|museum)|(n[acefgilopruz]|name|net)|(om|org)|(p[aefghklmnrstwy]|pro)|qa|r[eouw]|s[abcdeghijklmnortvyz]|(t[cdfghjklmnoprtvwz]|travel)|u[agkmsyz]|v[aceginu]|w[fs]|y[etu]|z[amw])$/i
110
- return name
111
- else
112
- raise ArgumentError, "Invalid FQDN: #{name}"
113
- end
114
- end
112
+ raise ArgumentError, "Invalid FQDN: #{name}" unless name =~ /^([a-z0-9]([-a-z0-9]*[a-z0-9])?\.)+((a[cdefgilmnoqrstuwxz]|aero|arpa)|(b[abdefghijmnorstvwyz]|biz)|(c[acdfghiklmnorsuvxyz]|cat|com|coop)|d[ejkmoz]|(e[ceghrstu]|edu)|f[ijkmor]|(g[abdefghilmnpqrstuwy]|gov)|h[kmnrtu]|(i[delmnoqrst]|info|int)|(j[emop]|jobs)|k[eghimnprwyz]|l[abcikrstuvy]|(m[acdghklmnopqrstuvwxyz]|mil|mobi|museum)|(n[acefgilopruz]|name|net)|(om|org)|(p[aefghklmnrstwy]|pro)|qa|r[eouw]|s[abcdeghijklmnortvyz]|(t[cdfghjklmnoprtvwz]|travel)|u[agkmsyz]|v[aceginu]|w[fs]|y[etu]|z[amw])$/i
115
113
 
114
+ name
115
+ end
116
116
  end
117
117
  end
118
118
  end