ronin-support 1.0.1 → 1.0.3

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 (48) hide show
  1. checksums.yaml +4 -4
  2. data/ChangeLog.md +38 -0
  3. data/README.md +0 -1
  4. data/lib/ronin/support/archive/core_ext/file.rb +43 -0
  5. data/lib/ronin/support/archive/core_ext.rb +1 -1
  6. data/lib/ronin/support/binary/array.rb +1 -1
  7. data/lib/ronin/support/binary/buffer.rb +3 -3
  8. data/lib/ronin/support/binary/core_ext.rb +2 -0
  9. data/lib/ronin/support/binary/cstring.rb +43 -0
  10. data/lib/ronin/support/binary/ctypes/array_type.rb +1 -1
  11. data/lib/ronin/support/binary/ctypes/os/bsd.rb +1 -1
  12. data/lib/ronin/support/binary/ctypes/unbounded_array_type.rb +1 -1
  13. data/lib/ronin/support/binary/packet.rb +77 -0
  14. data/lib/ronin/support/binary/stack.rb +3 -3
  15. data/lib/ronin/support/binary/template.rb +1 -5
  16. data/lib/ronin/support/binary.rb +1 -0
  17. data/lib/ronin/support/cli/io_shell.rb +2 -0
  18. data/lib/ronin/support/compression/core_ext/file.rb +16 -0
  19. data/lib/ronin/support/core_ext/kernel.rb +0 -4
  20. data/lib/ronin/support/crypto/cert.rb +17 -9
  21. data/lib/ronin/support/crypto/core_ext/file.rb +32 -0
  22. data/lib/ronin/support/crypto/core_ext/string.rb +34 -2
  23. data/lib/ronin/support/encoding/base16.rb +1 -1
  24. data/lib/ronin/support/encoding/base32.rb +1 -1
  25. data/lib/ronin/support/encoding/c/core_ext/string.rb +1 -1
  26. data/lib/ronin/support/encoding/c.rb +2 -2
  27. data/lib/ronin/support/encoding/core_ext/string.rb +2 -2
  28. data/lib/ronin/support/encoding/hex/core_ext/string.rb +1 -1
  29. data/lib/ronin/support/encoding/hex.rb +2 -2
  30. data/lib/ronin/support/encoding/js.rb +1 -1
  31. data/lib/ronin/support/encoding/powershell.rb +1 -1
  32. data/lib/ronin/support/encoding/quoted_printable.rb +3 -1
  33. data/lib/ronin/support/encoding/ruby.rb +1 -1
  34. data/lib/ronin/support/encoding/uuencoding.rb +3 -1
  35. data/lib/ronin/support/encoding/xml.rb +1 -1
  36. data/lib/ronin/support/network/dns/mixin.rb +2 -10
  37. data/lib/ronin/support/network/http/core_ext/uri/http.rb +8 -0
  38. data/lib/ronin/support/network/ip.rb +45 -14
  39. data/lib/ronin/support/network/ip_range.rb +4 -4
  40. data/lib/ronin/support/network/ssl/mixin.rb +2 -0
  41. data/lib/ronin/support/path.rb +1 -1
  42. data/lib/ronin/support/text/homoglyph/core_ext/string.rb +33 -0
  43. data/lib/ronin/support/text/patterns/network.rb +20 -20
  44. data/lib/ronin/support/text/random/mixin.rb +17 -17
  45. data/lib/ronin/support/text/random.rb +23 -23
  46. data/lib/ronin/support/text/typo/core_ext/string.rb +24 -0
  47. data/lib/ronin/support/version.rb +1 -1
  48. metadata +2 -2
@@ -54,10 +54,10 @@ class String
54
54
 
55
55
  #
56
56
  # @return [String]
57
- # The SHA2 checksum of the String.
57
+ # The SHA256 checksum of the String.
58
58
  #
59
59
  # @example
60
- # "hello".sha2
60
+ # "hello".sha256
61
61
  # # => "2cf24dba5fb0a30e26e83b2ac5b9e29e1b161e5c1fa7425e73043362938b9824"
62
62
  #
63
63
  # @api public
@@ -152,6 +152,10 @@ class String
152
152
  # @return [String]
153
153
  # The encrypted String.
154
154
  #
155
+ # @example
156
+ # "top secret".encrypt('aes-256-cbc', password: 's3cr3t')
157
+ # # => "\xF0[\x17\xDA\xA2\x82\x93\xF4\xB6s\xB5\xD8\x1F\xF2\xC6\\"
158
+ #
155
159
  # @see http://rubydoc.info/stdlib/openssl/OpenSSL/Cipher
156
160
  #
157
161
  # @since 0.6.0
@@ -191,6 +195,10 @@ class String
191
195
  # @return [String]
192
196
  # The decrypted String.
193
197
  #
198
+ # @example
199
+ # "\xF0[\x17\xDA\xA2\x82\x93\xF4\xB6s\xB5\xD8\x1F\xF2\xC6\\".decrypt('aes-256-cbc', password: 's3cr3t')
200
+ # # => "top secret"
201
+ #
194
202
  # @see http://rubydoc.info/stdlib/openssl/OpenSSL/Cipher
195
203
  #
196
204
  # @since 0.6.0
@@ -236,6 +244,10 @@ class String
236
244
  # @raise [ArgumentError]
237
245
  # Either the the `key:` or `password:` keyword argument must be given.
238
246
  #
247
+ # @example
248
+ # "top secret".aes_encrypt(key_size: 256, password: 's3cr3t')
249
+ # # => "\xF0[\x17\xDA\xA2\x82\x93\xF4\xB6s\xB5\xD8\x1F\xF2\xC6\\"
250
+ #
239
251
  # @since 1.0.0
240
252
  #
241
253
  def aes_encrypt(**kwargs)
@@ -275,6 +287,10 @@ class String
275
287
  # @raise [ArgumentError]
276
288
  # Either the the `key:` or `password:` keyword argument must be given.
277
289
  #
290
+ # @example
291
+ # "\xF0[\x17\xDA\xA2\x82\x93\xF4\xB6s\xB5\xD8\x1F\xF2\xC6\\".aes_decrypt(key_size: 256, password: 's3cr3t')
292
+ # # => "top secret"
293
+ #
278
294
  # @since 1.0.0
279
295
  #
280
296
  def aes_decrypt(**kwargs)
@@ -311,6 +327,10 @@ class String
311
327
  # @raise [ArgumentError]
312
328
  # Either the the `key:` or `password:` keyword argument must be given.
313
329
  #
330
+ # @example
331
+ # "top secret".aes128_encrypt(password: 's3cr3t')
332
+ # # => "\x88\xA53\xE9|\xE2\x8E\xA0\xABv\xCF\x94\x17\xBB*\xC5"
333
+ #
314
334
  # @since 1.0.0
315
335
  #
316
336
  def aes128_encrypt(**kwargs)
@@ -347,6 +367,10 @@ class String
347
367
  # @raise [ArgumentError]
348
368
  # Either the the `key:` or `password:` keyword argument must be given.
349
369
  #
370
+ # @example
371
+ # "\x88\xA53\xE9|\xE2\x8E\xA0\xABv\xCF\x94\x17\xBB*\xC5".aes128_decrypt(password: 's3cr3t')
372
+ # # => "top secret"
373
+ #
350
374
  # @since 1.0.0
351
375
  #
352
376
  def aes128_decrypt(**kwargs)
@@ -383,6 +407,10 @@ class String
383
407
  # @raise [ArgumentError]
384
408
  # Either the the `key:` or `password:` keyword argument must be given.
385
409
  #
410
+ # @example
411
+ # "top secret".aes256_encrypt(password: 's3cr3t')
412
+ # # => "\xF0[\x17\xDA\xA2\x82\x93\xF4\xB6s\xB5\xD8\x1F\xF2\xC6\\"
413
+ #
386
414
  # @since 1.0.0
387
415
  #
388
416
  def aes256_encrypt(**kwargs)
@@ -419,6 +447,10 @@ class String
419
447
  # @raise [ArgumentError]
420
448
  # Either the the `key:` or `password:` keyword argument must be given.
421
449
  #
450
+ # @example
451
+ # "\xF0[\x17\xDA\xA2\x82\x93\xF4\xB6s\xB5\xD8\x1F\xF2\xC6\\".aes256_decrypt(password: 's3cr3t')
452
+ # # => "top secret"
453
+ #
422
454
  # @since 1.0.0
423
455
  #
424
456
  def aes256_decrypt(**kwargs)
@@ -71,7 +71,7 @@ module Ronin
71
71
  # # => "hello"
72
72
  #
73
73
  def self.decode(data)
74
- decoded = String.new
74
+ decoded = String.new(encoding: Encoding::ASCII_8BIT)
75
75
 
76
76
  data.scan(/../).each do |hex_char|
77
77
  decoded << hex_char.to_i(16).chr
@@ -63,7 +63,7 @@ module Ronin
63
63
  # The Base32 decoded String.
64
64
  #
65
65
  def self.decode(data)
66
- decoded = String.new
66
+ decoded = String.new(encoding: Encoding::UTF_8)
67
67
 
68
68
  each_chunk(data,8) do |chunk|
69
69
  chunk.decode(decoded)
@@ -47,7 +47,7 @@ class String
47
47
  # The unescaped C String.
48
48
  #
49
49
  # @example
50
- # "\x68\x65\x6c\x6c\x6f\x20\x77\x6f\x72\x6c\x64".c_unescape
50
+ # "\\x68\\x65\\x6c\\x6c\\x6f\\x20\\x77\\x6f\\x72\\x6c\\x64".c_unescape
51
51
  # # => "hello world"
52
52
  #
53
53
  # @see Ronin::Support::Encoding::C.unescape
@@ -213,11 +213,11 @@ module Ronin
213
213
  # The unescaped C String.
214
214
  #
215
215
  # @example
216
- # Encoding::C.unescape("\x68\x65\x6c\x6c\x6f\x20\x77\x6f\x72\x6c\x64")
216
+ # Encoding::C.unescape("\\x68\\x65\\x6c\\x6c\\x6f\\x20\\x77\\x6f\\x72\\x6c\\x64")
217
217
  # # => "hello world"
218
218
  #
219
219
  def self.unescape(data)
220
- unescaped = String.new
220
+ unescaped = String.new(encoding: Encoding::UTF_8)
221
221
  scanner = StringScanner.new(data)
222
222
 
223
223
  until scanner.eos?
@@ -48,7 +48,7 @@ class String
48
48
  def encode_bytes(include: nil, exclude: nil)
49
49
  included = (Chars::CharSet.new(*include) if include)
50
50
  excluded = (Chars::CharSet.new(*exclude) if exclude)
51
- formatted = String.new
51
+ formatted = String.new(encoding: ::Encoding::UTF_8)
52
52
 
53
53
  each_byte do |b|
54
54
  formatted << if (included.nil? || included.include_byte?(b)) &&
@@ -90,7 +90,7 @@ class String
90
90
  def encode_chars(include: nil, exclude: nil)
91
91
  included = (Chars::CharSet.new(*include) if include)
92
92
  excluded = (Chars::CharSet.new(*exclude) if exclude)
93
- formatted = String.new
93
+ formatted = String.new(encoding: ::Encoding::UTF_8)
94
94
 
95
95
  each_char do |c|
96
96
  formatted << if (included.nil? || included.include_char?(c)) &&
@@ -79,7 +79,7 @@ class String
79
79
  # The hex unescaped version of the String.
80
80
  #
81
81
  # @example
82
- # "hello\\nworld".hex_escape
82
+ # "hello\\nworld".hex_unescape
83
83
  # # => "hello\nworld"
84
84
  #
85
85
  # @see Ronin::Support::Encoding::Hex.unescape
@@ -188,11 +188,11 @@ module Ronin
188
188
  # the same String if it is not quoted.
189
189
  #
190
190
  # @example
191
- # Encoding::Hex.unescape("\"hello\\nworld\"")
191
+ # Encoding::Hex.unescape("hello\\nworld")
192
192
  # # => "hello\nworld"
193
193
  #
194
194
  def self.unescape(data)
195
- buffer = String.new
195
+ buffer = String.new(encoding: Encoding::UTF_8)
196
196
  scanner = StringScanner.new(data)
197
197
 
198
198
  until scanner.eos?
@@ -182,7 +182,7 @@ module Ronin
182
182
  # # => "hello world"
183
183
  #
184
184
  def self.unescape(data)
185
- unescaped = String.new
185
+ unescaped = String.new(encoding: Encoding::UTF_8)
186
186
 
187
187
  data.scan(/[\\%]u[0-9a-fA-F]{1,4}|[\\%][0-9a-fA-F]{1,2}|\\[btnfr\'\"\\]|./) do |c|
188
188
  unescaped << BACKSLASHED_CHARS.fetch(c) do
@@ -191,7 +191,7 @@ module Ronin
191
191
  # # => "hello\nworld"
192
192
  #
193
193
  def self.unescape(data)
194
- unescaped = String.new
194
+ unescaped = String.new(encoding: Encoding::UTF_8)
195
195
  scanner = StringScanner.new(data)
196
196
 
197
197
  until scanner.eos?
@@ -22,7 +22,9 @@ module Ronin
22
22
  module Support
23
23
  class Encoding < ::Encoding
24
24
  #
25
- # Contains methods for encoding/decoding Quoted Printable data.
25
+ # Contains methods for encoding/decoding [Quoted Printable] data.
26
+ #
27
+ # [Quoted-Printable]: https://en.wikipedia.org/wiki/Quoted-printable
26
28
  #
27
29
  # ## Core-Ext Methods
28
30
  #
@@ -174,7 +174,7 @@ module Ronin
174
174
  # # => "hello"
175
175
  #
176
176
  def self.unescape(data)
177
- unescaped = String.new
177
+ unescaped = String.new(encoding: Encoding::UTF_8)
178
178
  scanner = StringScanner.new(data)
179
179
 
180
180
  until scanner.eos?
@@ -20,7 +20,9 @@ module Ronin
20
20
  module Support
21
21
  class Encoding < ::Encoding
22
22
  #
23
- # Contains methods for encoding/decoding UUEncoded data.
23
+ # Contains methods for encoding/decoding [UUEncoded][uuencoding] data.
24
+ #
25
+ # [uuencoding]: https://en.wikipedia.org/wiki/Uuencoding
24
26
  #
25
27
  # ## Core-Ext Methods
26
28
  #
@@ -312,7 +312,7 @@ module Ronin
312
312
  # @see http://rubydoc.info/stdlib/cgi/CGI.unescapeHash
313
313
  #
314
314
  def self.unescape(data)
315
- unescaped = String.new
315
+ unescaped = String.new(encoding: Encoding::UTF_8)
316
316
  scanner = StringScanner.new(data)
317
317
 
318
318
  until scanner.eos?
@@ -25,6 +25,8 @@ module Ronin
25
25
  #
26
26
  # Provides helper methods for performing DNS queries.
27
27
  #
28
+ # @api public
29
+ #
28
30
  module Mixin
29
31
  #
30
32
  # Sets the DNS nameservers to query.
@@ -79,8 +81,6 @@ module Ronin
79
81
  # @return [Resolv, Resolv::DNS]
80
82
  # The DNS Resolver.
81
83
  #
82
- # @api public
83
- #
84
84
  def dns_resolver(nameservers: nil, nameserver: nil)
85
85
  if nameserver
86
86
  Network::DNS.resolver(nameserver: nameserver)
@@ -111,8 +111,6 @@ module Ronin
111
111
  # @return [String, nil]
112
112
  # The address of the hostname.
113
113
  #
114
- # @api public
115
- #
116
114
  def dns_get_address(host,**kwargs)
117
115
  dns_resolver(**kwargs).get_address(host.to_s)
118
116
  end
@@ -137,8 +135,6 @@ module Ronin
137
135
  # @return [Array<String>]
138
136
  # The addresses of the hostname.
139
137
  #
140
- # @api public
141
- #
142
138
  def dns_get_addresses(host,**kwargs)
143
139
  dns_resolver(**kwargs).get_addresses(host.to_s)
144
140
  end
@@ -161,8 +157,6 @@ module Ronin
161
157
  # @return [String, nil]
162
158
  # The hostname of the address.
163
159
  #
164
- # @api public
165
- #
166
160
  def dns_get_name(ip,**kwargs)
167
161
  dns_resolver(**kwargs).get_name(ip.to_s)
168
162
  end
@@ -187,8 +181,6 @@ module Ronin
187
181
  # @return [Array<String>]
188
182
  # The hostnames of the address.
189
183
  #
190
- # @api public
191
- #
192
184
  def dns_get_names(ip,**kwargs)
193
185
  dns_resolver(**kwargs).get_names(ip.to_s)
194
186
  end
@@ -33,6 +33,10 @@ module URI
33
33
  # @return [Integer]
34
34
  # The HTTP Response Status.
35
35
  #
36
+ # @example
37
+ # URI('http://github.com/').status
38
+ # # => 301
39
+ #
36
40
  # @see Ronin::Support::Network::HTTP.response_status
37
41
  #
38
42
  # @since 0.3.0
@@ -53,6 +57,10 @@ module URI
53
57
  #
54
58
  # @see Ronin::Support::Network::HTTP.ok?
55
59
  #
60
+ # @example
61
+ # URI('https://example.com/').ok?
62
+ # # => true
63
+ #
56
64
  # @since 0.3.0
57
65
  #
58
66
  def ok?(**kwargs)
@@ -66,11 +66,6 @@ module Ronin
66
66
  #
67
67
  class IP < IPAddr
68
68
 
69
- # The address of the IP.
70
- #
71
- # @return [String]
72
- attr_reader :address
73
-
74
69
  #
75
70
  # Initializes the IP address.
76
71
  #
@@ -92,9 +87,15 @@ module Ronin
92
87
  # the IP address.
93
88
  #
94
89
  def initialize(address,family=Socket::AF_UNSPEC)
95
- # XXX: remove the %iface suffix for ruby < 3.1.0
96
- if address.kind_of?(String) && address =~ /%.+$/
97
- address = address.sub(/%.+$/,'')
90
+ case address
91
+ when String
92
+ # XXX: remove the %iface suffix for ruby < 3.1.0
93
+ if address =~ /%.+$/
94
+ address = address.sub(/%.+$/,'')
95
+ end
96
+
97
+ # pre-cache the given IP address String
98
+ @address = address
98
99
  end
99
100
 
100
101
  begin
@@ -102,13 +103,33 @@ module Ronin
102
103
  rescue IPAddr::InvalidAddressError
103
104
  raise(InvalidIP,"invalid IP address: #{address.inspect}")
104
105
  end
106
+ end
105
107
 
106
- @address = case address
107
- when String then address.to_s
108
- else to_s
109
- end
108
+ protected
109
+
110
+ #
111
+ # Sets the IP address using the numeric IP address value.
112
+ #
113
+ # @param [Integer] addr
114
+ # The new numeric IP address value.
115
+ #
116
+ # @param [Integer] family
117
+ # Optional IP address family.
118
+ #
119
+ # @return [self]
120
+ #
121
+ # @api private
122
+ #
123
+ def set(addr,*family)
124
+ super(addr,*family)
125
+
126
+ # unset the cached IP address since the numeric address has changed
127
+ @address = nil
128
+ return self
110
129
  end
111
130
 
131
+ public
132
+
112
133
  # The URI for https://ipinfo.io/ip
113
134
  IPINFO_URI = URI::HTTPS.build(host: 'ipinfo.io', path: '/ip')
114
135
 
@@ -286,6 +307,16 @@ module Ronin
286
307
  ipv4? && (@addr & 0xff) == 0x00
287
308
  end
288
309
 
310
+ #
311
+ # The IP address.
312
+ #
313
+ # @return [String]
314
+ # The String version of the IP address.
315
+ #
316
+ def address
317
+ @address ||= to_s
318
+ end
319
+
289
320
  #
290
321
  # The Autonomous System Number (ASN) information for the IP address.
291
322
  #
@@ -519,8 +550,8 @@ module Ronin
519
550
  end
520
551
 
521
552
  alias canonical to_string
522
- alias to_uint to_i
523
553
  alias to_str to_s
554
+ alias to_uint to_i
524
555
 
525
556
  #
526
557
  # Inspects the IP.
@@ -529,7 +560,7 @@ module Ronin
529
560
  # The inspected IP object.
530
561
  #
531
562
  def inspect
532
- "#<#{self.class}: #{@address}>"
563
+ "#<#{self.class}: #{address}>"
533
564
  end
534
565
 
535
566
  end
@@ -40,7 +40,7 @@ module Ronin
40
40
  #
41
41
  # Enumerating over a IP-glob range:
42
42
  #
43
- # IPRange.each('10.0.1-3.*/24') { |ip| puts ip }
43
+ # IPRange.each('10.0.1-3.*') { |ip| puts ip }
44
44
  # # 10.0.1.1
45
45
  # # 10.0.1.2
46
46
  # # ...
@@ -75,7 +75,7 @@ module Ronin
75
75
  # ip_range = IPRange.new('10.0.0.1/24')
76
76
  #
77
77
  # @example Initializing an IP-glob range:
78
- # ip_range = IPRange.new('10.0.1-3.*/24')
78
+ # ip_range = IPRange.new('10.0.1-3.*')
79
79
  #
80
80
  def initialize(string)
81
81
  @range = if self.class.glob?(string) then Glob.new(string)
@@ -125,7 +125,7 @@ module Ronin
125
125
  # # 10.0.0.255
126
126
  #
127
127
  # @example Enumerating over a IP-glob range:
128
- # IPRange.each('10.0.1-3.*/24') { |ip| puts ip }
128
+ # IPRange.each('10.0.1-3.*') { |ip| puts ip }
129
129
  # # 10.0.1.1
130
130
  # # 10.0.1.2
131
131
  # # ...
@@ -228,7 +228,7 @@ module Ronin
228
228
  # # 10.0.0.255
229
229
  #
230
230
  # @example Enumerating over a IP-glob range:
231
- # ip_range = IPRange.new('10.0.1-3.*/24')
231
+ # ip_range = IPRange.new('10.0.1-3.*')
232
232
  # ip_range.each { |ip| puts ip }
233
233
  # # 10.0.1.1
234
234
  # # 10.0.1.2
@@ -267,6 +267,8 @@ module Ronin
267
267
  socket = tcp_connect(host,port,bind_host: bind_host,
268
268
  bind_port: bind_port)
269
269
  ssl_socket = ssl_socket(socket,**kwargs)
270
+
271
+ ssl_socket.hostname = host
270
272
  ssl_socket.connect
271
273
 
272
274
  if block_given?
@@ -115,7 +115,7 @@ module Ronin
115
115
  # # => #<Ronin::Support::Path:../../../../../../../etc/passwd>
116
116
  #
117
117
  def join(*names)
118
- joined_path = if root? then String.new
118
+ joined_path = if root? then String.new(encoding: Encoding::UTF_8)
119
119
  else self.to_s
120
120
  end
121
121
 
@@ -39,6 +39,10 @@ class String
39
39
  # @raise [Ronin::Support::Text::Homoglyph::NotViable]
40
40
  # No homoglyph replaceable characters were found in the String.
41
41
  #
42
+ # @example
43
+ # "microsoft".homoglyph
44
+ # # => "microsoft"
45
+ #
42
46
  # @see Ronin::Support::Text::Homoglyph.substitute
43
47
  #
44
48
  # @api public
@@ -68,6 +72,11 @@ class String
68
72
  # @return [Enumerator]
69
73
  # If no block is given, an Enumerator object will be returned.
70
74
  #
75
+ # @example
76
+ # "microsoft".each_homoglyph do |homoglyph|
77
+ # # ...
78
+ # end
79
+ #
71
80
  # @see Ronin::Support::Text::Homoglyph.each_substitution
72
81
  #
73
82
  # @api public
@@ -95,6 +104,30 @@ class String
95
104
  # @return [Array<String>]
96
105
  # All variation of the given String.
97
106
  #
107
+ # @example
108
+ # "microsoft".homoglyphs
109
+ # # =>
110
+ # # ["ⅿicrosoft",
111
+ # # "microsoft",
112
+ # # "mіcrosoft",
113
+ # # "mⅰcrosoft",
114
+ # # "microsoft",
115
+ # # "miϲrosoft",
116
+ # # "miсrosoft",
117
+ # # "miⅽrosoft",
118
+ # # "microsoft",
119
+ # # "microsoft",
120
+ # # "micrοsoft",
121
+ # # "microsοft",
122
+ # # "micrоsoft",
123
+ # # "microsоft",
124
+ # # "microsoft",
125
+ # # "microsoft",
126
+ # # "microѕoft",
127
+ # # "microsoft",
128
+ # # "microsoft",
129
+ # # "microsoft"]
130
+ #
98
131
  # @see Ronin::Support::Text::Homoglyph.each_substitution
99
132
  #
100
133
  # @api public
@@ -45,26 +45,26 @@ module Ronin
45
45
  # A regular expression for matching IPv6 Addresses.
46
46
  #
47
47
  # @since 1.0.0
48
- IPV6_ADDR = Regexp.union(
49
- /(?:[0-9a-f]{1,4}:){6}#{IPV4_ADDR}/,
50
- /(?:[0-9a-f]{1,4}:){5}[0-9a-f]{1,4}:#{IPV4_ADDR}/,
51
- /(?:[0-9a-f]{1,4}:){5}:[0-9a-f]{1,4}:#{IPV4_ADDR}/,
52
- /(?:[0-9a-f]{1,4}:){1,1}(?::[0-9a-f]{1,4}){1,4}:#{IPV4_ADDR}/,
53
- /(?:[0-9a-f]{1,4}:){1,2}(?::[0-9a-f]{1,4}){1,3}:#{IPV4_ADDR}/,
54
- /(?:[0-9a-f]{1,4}:){1,3}(?::[0-9a-f]{1,4}){1,2}:#{IPV4_ADDR}/,
55
- /(?:[0-9a-f]{1,4}:){1,4}(?::[0-9a-f]{1,4}){1,1}:#{IPV4_ADDR}/,
56
- /:(?::[0-9a-f]{1,4}){1,5}:#{IPV4_ADDR}/,
57
- /(?:(?:[0-9a-f]{1,4}:){1,5}|:):#{IPV4_ADDR}/,
58
- %r{(?:[0-9a-f]{1,4}:){1,1}(?::[0-9a-f]{1,4}){1,6}(?:/\d{1,3})?},
59
- %r{(?:[0-9a-f]{1,4}:){1,2}(?::[0-9a-f]{1,4}){1,5}(?:/\d{1,3})?},
60
- %r{(?:[0-9a-f]{1,4}:){1,3}(?::[0-9a-f]{1,4}){1,4}(?:/\d{1,3})?},
61
- %r{(?:[0-9a-f]{1,4}:){1,4}(?::[0-9a-f]{1,4}){1,3}(?:/\d{1,3})?},
62
- %r{(?:[0-9a-f]{1,4}:){1,5}(?::[0-9a-f]{1,4}){1,2}(?:/\d{1,3})?},
63
- %r{(?:[0-9a-f]{1,4}:){1,6}(?::[0-9a-f]{1,4}){1,1}(?:/\d{1,3})?},
64
- %r{[0-9a-f]{1,4}(?::[0-9a-f]{1,4}){7}(?:/\d{1,3})?},
65
- %r{:(?::[0-9a-f]{1,4}){1,7}(?:/\d{1,3})?},
66
- %r{(?:(?:[0-9a-f]{1,4}:){1,7}|:):(?:/\d{1,3})?}
67
- )
48
+ IPV6_ADDR = %r{
49
+ (?:[0-9a-f]{1,4}:){6}#{IPV4_ADDR}|
50
+ (?:[0-9a-f]{1,4}:){5}[0-9a-f]{1,4}:#{IPV4_ADDR}|
51
+ (?:[0-9a-f]{1,4}:){5}:[0-9a-f]{1,4}:#{IPV4_ADDR}|
52
+ (?:[0-9a-f]{1,4}:){1,1}(?::[0-9a-f]{1,4}){1,4}:#{IPV4_ADDR}|
53
+ (?:[0-9a-f]{1,4}:){1,2}(?::[0-9a-f]{1,4}){1,3}:#{IPV4_ADDR}|
54
+ (?:[0-9a-f]{1,4}:){1,3}(?::[0-9a-f]{1,4}){1,2}:#{IPV4_ADDR}|
55
+ (?:[0-9a-f]{1,4}:){1,4}(?::[0-9a-f]{1,4}){1,1}:#{IPV4_ADDR}|
56
+ :(?::[0-9a-f]{1,4}){1,5}:#{IPV4_ADDR}|
57
+ (?:(?:[0-9a-f]{1,4}:){1,5}|:):#{IPV4_ADDR}|
58
+ (?:[0-9a-f]{1,4}:){1,1}(?::[0-9a-f]{1,4}){1,6}(?:/\d{1,3})?|
59
+ (?:[0-9a-f]{1,4}:){1,2}(?::[0-9a-f]{1,4}){1,5}(?:/\d{1,3})?|
60
+ (?:[0-9a-f]{1,4}:){1,3}(?::[0-9a-f]{1,4}){1,4}(?:/\d{1,3})?|
61
+ (?:[0-9a-f]{1,4}:){1,4}(?::[0-9a-f]{1,4}){1,3}(?:/\d{1,3})?|
62
+ (?:[0-9a-f]{1,4}:){1,5}(?::[0-9a-f]{1,4}){1,2}(?:/\d{1,3})?|
63
+ (?:[0-9a-f]{1,4}:){1,6}(?::[0-9a-f]{1,4}){1,1}(?:/\d{1,3})?|
64
+ [0-9a-f]{1,4}(?::[0-9a-f]{1,4}){7}(?:/\d{1,3})?|
65
+ :(?::[0-9a-f]{1,4}){1,7}(?:/\d{1,3})?|
66
+ (?:(?:[0-9a-f]{1,4}:){1,7}|:):(?:/\d{1,3})?
67
+ }x
68
68
 
69
69
  # A regular expression for matching IP Addresses.
70
70
  #