ronin-support 1.0.4 → 1.0.6
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.github/workflows/ruby.yml +1 -0
- data/.rubocop.yml +8 -0
- data/ChangeLog.md +19 -1
- data/lib/ronin/support/binary/stream/methods.rb +5 -1
- data/lib/ronin/support/encoding/base64.rb +2 -2
- data/lib/ronin/support/network/http.rb +5 -2
- data/lib/ronin/support/network/ip_range/cidr.rb +4 -15
- data/lib/ronin/support/network/ip_range/glob.rb +29 -26
- data/lib/ronin/support/network/ip_range/range.rb +3 -20
- data/lib/ronin/support/network/ip_range.rb +27 -18
- data/lib/ronin/support/network/pop3/mixin.rb +5 -2
- data/lib/ronin/support/network/smtp/mixin.rb +5 -2
- data/lib/ronin/support/network/ssl/mixin.rb +3 -3
- data/lib/ronin/support/network/tcp.rb +5 -2
- data/lib/ronin/support/network/tls/mixin.rb +3 -3
- data/lib/ronin/support/network/udp.rb +5 -2
- data/lib/ronin/support/version.rb +1 -1
- metadata +3 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 04b9f7e7aa3d25c5742621faaeba6ce51150d3959d82867d41901c7cd1a2af06
|
4
|
+
data.tar.gz: 4e081a47953f762edca8e267c6a31fc168cf8a91f93ce464f7586a1d3e81b2dc
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 5611fdbe096f30f8ad9a4d828b722c221e90b93a9e217e6fb9c3ca3eb54dc7103cb0d39e7b5b98f5a74192c6339adedad97c5c11f69bb5019b2ebc7ca0ef3b03
|
7
|
+
data.tar.gz: 107956428d0b34d47378c338143e70820cee6a62fedf24927157d5f06f16b4b978957fb02f945f7eabb75e897dc81a2ab58665fbcf56b072a7f7ad4493bb116a
|
data/.github/workflows/ruby.yml
CHANGED
data/.rubocop.yml
CHANGED
@@ -107,3 +107,11 @@ Naming/BinaryOperatorParameterName:
|
|
107
107
|
Lint/RescueException:
|
108
108
|
Exclude:
|
109
109
|
- 'lib/ronin/support/core_ext/kernel.rb'
|
110
|
+
|
111
|
+
# make an exception when we need to test the #each method directly
|
112
|
+
Style/MapIntoArray:
|
113
|
+
Exclude:
|
114
|
+
- 'spec/archive/zip/reader_spec.rb'
|
115
|
+
- 'spec/network/ip_range/cidr_spec.rb'
|
116
|
+
- 'spec/network/ip_range/glob_spec.rb'
|
117
|
+
- 'spec/network/ip_range_spec.rb'
|
data/ChangeLog.md
CHANGED
@@ -1,3 +1,22 @@
|
|
1
|
+
### 1.0.6 / 2024-06-19
|
2
|
+
|
3
|
+
* Fixed error messages in {Ronin::Support::Encoding::Base64.encode} and
|
4
|
+
{Ronin::Support::Encoding::Base64.decode}.
|
5
|
+
* Fixed {Ronin::Support::Network::IPRange::Glob#each} to support `*` in IPv6
|
6
|
+
glob ranges.
|
7
|
+
* {Ronin::Support::Network::TCP.connect},
|
8
|
+
{Ronin::Support::Network::UDP.connect}, and
|
9
|
+
{Ronin::Support::Network::HTTP.connect}, when given a block, now returns the
|
10
|
+
block's return value.
|
11
|
+
* {Ronin::Support::Network::TCP.connect} and
|
12
|
+
{Ronin::Support::Network::UDP.connect} properly closes the socket when passed
|
13
|
+
a block that raises an exception.
|
14
|
+
|
15
|
+
### 1.0.5 / 2023-12-27
|
16
|
+
|
17
|
+
* Fixed a bug in {Ronin::Support::Binary::Stream::Methods#read_string} on Ruby
|
18
|
+
3.3.0.
|
19
|
+
|
1
20
|
### 1.0.4 / 2023-12-15
|
2
21
|
|
3
22
|
* Fixed a bug in {Array#pack} where complex types (ex: `[[:uint32, 4], 10]`)
|
@@ -699,4 +718,3 @@
|
|
699
718
|
* Require combinatorics ~> 0.3.
|
700
719
|
* Require uri-query_params ~> 0.5, >= 0.5.2.
|
701
720
|
* Require data_paths ~> 0.2, >= 0.2.1.
|
702
|
-
|
@@ -111,7 +111,11 @@ module Ronin
|
|
111
111
|
# @api public
|
112
112
|
#
|
113
113
|
def read_string(length=nil)
|
114
|
-
new_string =
|
114
|
+
new_string = if (encoding = external_encoding)
|
115
|
+
String.new('', encoding: encoding)
|
116
|
+
else
|
117
|
+
String.new('')
|
118
|
+
end
|
115
119
|
|
116
120
|
if length
|
117
121
|
length.times do
|
@@ -52,7 +52,7 @@ module Ronin
|
|
52
52
|
when :url_safe then ::Base64.urlsafe_encode64(data)
|
53
53
|
when nil then ::Base64.encode64(data)
|
54
54
|
else
|
55
|
-
raise(ArgumentError,"Base64 mode must be either :string, :
|
55
|
+
raise(ArgumentError,"Base64 mode must be either :string, :url_safe, or nil: #{mode.inspect}")
|
56
56
|
end
|
57
57
|
end
|
58
58
|
|
@@ -74,7 +74,7 @@ module Ronin
|
|
74
74
|
when :url_safe then ::Base64.urlsafe_decode64(data)
|
75
75
|
when nil then ::Base64.decode64(data)
|
76
76
|
else
|
77
|
-
raise(ArgumentError,"Base64 mode must be either :string, :
|
77
|
+
raise(ArgumentError,"Base64 mode must be either :string, :url_safe, or nil: #{mode.inspect}")
|
78
78
|
end
|
79
79
|
end
|
80
80
|
end
|
@@ -31,7 +31,6 @@ module Ronin
|
|
31
31
|
# cidr.each { |ip puts }
|
32
32
|
# # 10.0.0.0
|
33
33
|
# # 10.0.0.1
|
34
|
-
# # 10.0.0.2
|
35
34
|
# # ...
|
36
35
|
# # 10.0.0.254
|
37
36
|
# # 10.0.0.255
|
@@ -151,8 +150,8 @@ module Ronin
|
|
151
150
|
#
|
152
151
|
# @example
|
153
152
|
# IPRange::CIDR.each('10.0.0.1/24') { |ip| puts ip }
|
153
|
+
# # 10.0.0.0
|
154
154
|
# # 10.0.0.1
|
155
|
-
# # 10.0.0.2
|
156
155
|
# # ...
|
157
156
|
# # 10.0.0.254
|
158
157
|
# # 10.0.0.255
|
@@ -174,17 +173,14 @@ module Ronin
|
|
174
173
|
#
|
175
174
|
# @return [self]
|
176
175
|
#
|
177
|
-
# @note
|
178
|
-
# This method will skip IPv4 addresses ending in `.0` or `.255`.
|
179
|
-
#
|
180
176
|
# @example
|
181
177
|
# cidr = IPAddr.new('10.1.1.1/24')
|
182
178
|
# cidr.each { |ip| puts ip }
|
179
|
+
# # 10.0.0.0
|
183
180
|
# # 10.0.0.1
|
184
|
-
# # 10.0.0.2
|
185
181
|
# # ...
|
186
|
-
# # 10.0.0.253
|
187
182
|
# # 10.0.0.254
|
183
|
+
# # 10.0.0.255
|
188
184
|
#
|
189
185
|
def each
|
190
186
|
return enum_for(__method__) unless block_given?
|
@@ -192,14 +188,7 @@ module Ronin
|
|
192
188
|
family_mask = MASKS[@family]
|
193
189
|
|
194
190
|
(0..((~@mask_addr) & family_mask)).each do |i|
|
195
|
-
|
196
|
-
|
197
|
-
# skip IPv4 addresses ending in .0 or .255
|
198
|
-
if (ipv4? && ((ip_uint & 0xff) == 0 || (ip_uint & 0xff) == 0xff))
|
199
|
-
next
|
200
|
-
end
|
201
|
-
|
202
|
-
yield _to_string(ip_uint)
|
191
|
+
yield _to_string(@addr | i)
|
203
192
|
end
|
204
193
|
|
205
194
|
return self
|
@@ -29,23 +29,23 @@ module Ronin
|
|
29
29
|
#
|
30
30
|
# ip_range = IPRange::Glob.new('10.0.1-3.*/24')
|
31
31
|
# ip_range.each { |ip| puts ip }
|
32
|
+
# # 10.0.1.0
|
32
33
|
# # 10.0.1.1
|
33
|
-
# # 10.0.1.2
|
34
34
|
# # ...
|
35
|
-
# # 10.0.1.253
|
36
35
|
# # 10.0.1.254
|
36
|
+
# # 10.0.1.255
|
37
37
|
# # ...
|
38
|
+
# # 10.0.2.0
|
38
39
|
# # 10.0.2.1
|
39
|
-
# # 10.0.2.2
|
40
40
|
# # ...
|
41
|
-
# # 10.0.2.253
|
42
41
|
# # 10.0.2.254
|
42
|
+
# # 10.0.2.255
|
43
43
|
# # ...
|
44
|
+
# # 10.0.3.0
|
44
45
|
# # 10.0.3.1
|
45
|
-
# # 10.0.3.2
|
46
46
|
# # ...
|
47
|
-
# # 10.0.3.253
|
48
47
|
# # 10.0.3.254
|
48
|
+
# # 10.0.3.255
|
49
49
|
#
|
50
50
|
# @api public
|
51
51
|
#
|
@@ -71,22 +71,25 @@ module Ronin
|
|
71
71
|
|
72
72
|
if @string.include?(':') # IPv6
|
73
73
|
@version = 6
|
74
|
-
@separator = ':'
|
75
74
|
@base = 16
|
76
75
|
@formatter = method(:format_ipv6_address)
|
76
|
+
|
77
|
+
separator = ':'
|
78
|
+
octet_range = (0..0xffff)
|
77
79
|
else # IPv4
|
78
80
|
@version = 4
|
79
|
-
@separator = '.'
|
80
81
|
@base = 10
|
81
82
|
@formatter = method(:format_ipv4_address)
|
83
|
+
|
84
|
+
separator = '.'
|
85
|
+
octet_range = (0..255)
|
82
86
|
end
|
83
87
|
|
84
|
-
@ranges = @string.split(
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
else [segment]
|
88
|
+
@ranges = @string.split(separator).map do |segment|
|
89
|
+
if segment == '*' then octet_range
|
90
|
+
elsif segment.include?(',') then parse_list(segment)
|
91
|
+
elsif segment.include?('-') then parse_range(segment)
|
92
|
+
else [segment]
|
90
93
|
end
|
91
94
|
end
|
92
95
|
end
|
@@ -123,23 +126,23 @@ module Ronin
|
|
123
126
|
#
|
124
127
|
# @example Enumerate through a IPv4 glob range:
|
125
128
|
# IPRange::Glob.each('10.0.1-3.*') { |ip| puts ip }
|
129
|
+
# # 10.0.1.0
|
126
130
|
# # 10.0.1.1
|
127
|
-
# # 10.0.1.2
|
128
131
|
# # ...
|
129
|
-
# # 10.0.1.253
|
130
132
|
# # 10.0.1.254
|
133
|
+
# # 10.0.1.255
|
131
134
|
# # ...
|
135
|
+
# # 10.0.2.0
|
132
136
|
# # 10.0.2.1
|
133
|
-
# # 10.0.2.2
|
134
137
|
# # ...
|
135
|
-
# # 10.0.2.253
|
136
138
|
# # 10.0.2.254
|
139
|
+
# # 10.0.2.255
|
137
140
|
# # ...
|
141
|
+
# # 10.0.3.0
|
138
142
|
# # 10.0.3.1
|
139
|
-
# # 10.0.3.2
|
140
143
|
# # ...
|
141
|
-
# # 10.0.3.253
|
142
144
|
# # 10.0.3.254
|
145
|
+
# # 10.0.3.255
|
143
146
|
#
|
144
147
|
# @example Enumerate through a globbed IPv6 range:
|
145
148
|
# IPRange::Glob.each('::ff::02-0a::c3') { |ip| puts ip }
|
@@ -181,23 +184,23 @@ module Ronin
|
|
181
184
|
# @example Enumerate through a IPv4 glob range:
|
182
185
|
# ip_range = IPRange::Glob.new('10.0.1-3.*')
|
183
186
|
# ip_range.each { |ip| puts ip }
|
187
|
+
# # 10.0.1.0
|
184
188
|
# # 10.0.1.1
|
185
|
-
# # 10.0.1.2
|
186
189
|
# # ...
|
187
|
-
# # 10.0.1.253
|
188
190
|
# # 10.0.1.254
|
191
|
+
# # 10.0.1.255
|
189
192
|
# # ...
|
193
|
+
# # 10.0.2.0
|
190
194
|
# # 10.0.2.1
|
191
|
-
# # 10.0.2.2
|
192
195
|
# # ...
|
193
|
-
# # 10.0.2.253
|
194
196
|
# # 10.0.2.254
|
197
|
+
# # 10.0.2.255
|
195
198
|
# # ...
|
199
|
+
# # 10.0.3.0
|
196
200
|
# # 10.0.3.1
|
197
|
-
# # 10.0.3.2
|
198
201
|
# # ...
|
199
|
-
# # 10.0.3.253
|
200
202
|
# # 10.0.3.254
|
203
|
+
# # 10.0.3.255
|
201
204
|
#
|
202
205
|
# @example Enumerate through a globbed IPv6 range:
|
203
206
|
# ip_range = IPRange::Glob.new('::ff::02-0a::c3')
|
@@ -171,26 +171,14 @@ module Ronin
|
|
171
171
|
# @return [Enumerator]
|
172
172
|
# If no block is given, an Enumerator will be returned.
|
173
173
|
#
|
174
|
-
# @note
|
175
|
-
# This method will skip IPv4 addresses ending in `.0` or `.255`.
|
176
|
-
#
|
177
174
|
# @example
|
178
|
-
# range = IPRange::Range.new('1.1.1.
|
175
|
+
# range = IPRange::Range.new('1.1.1.1','1.1.3.42')
|
179
176
|
# range.each { |ip| puts ip }
|
180
177
|
# # 1.1.1.1
|
181
178
|
# # 1.1.1.2
|
182
179
|
# # ...
|
183
|
-
# # 1.1.
|
184
|
-
# # 1.1.
|
185
|
-
#
|
186
|
-
# @example
|
187
|
-
# range IPRange::Range.new('1.1.1.100','1.1.3.200')
|
188
|
-
# range.each { |ip| puts ip }
|
189
|
-
# # 1.1.1.100
|
190
|
-
# # 1.1.1.101
|
191
|
-
# # ...
|
192
|
-
# # 1.1.3.199
|
193
|
-
# # 1.1.3.200
|
180
|
+
# # 1.1.3.41
|
181
|
+
# # 1.1.3.42
|
194
182
|
#
|
195
183
|
def each
|
196
184
|
return enum_for(__method__) unless block_given?
|
@@ -198,11 +186,6 @@ module Ronin
|
|
198
186
|
ipaddr = @begin.clone
|
199
187
|
|
200
188
|
(@begin_uint..@end_uint).each do |ip_uint|
|
201
|
-
# skip IPv4 addresses ending in .0 or .255
|
202
|
-
if (ipv4? && ((ip_uint & 0xff) == 0 || (ip_uint & 0xff) == 0xff))
|
203
|
-
next
|
204
|
-
end
|
205
|
-
|
206
189
|
ipaddr.send(:set,ip_uint)
|
207
190
|
yield ipaddr.to_s
|
208
191
|
end
|
@@ -41,23 +41,23 @@ module Ronin
|
|
41
41
|
# Enumerating over a IP-glob range:
|
42
42
|
#
|
43
43
|
# IPRange.each('10.0.1-3.*') { |ip| puts ip }
|
44
|
+
# # 10.0.1.0
|
44
45
|
# # 10.0.1.1
|
45
|
-
# # 10.0.1.2
|
46
46
|
# # ...
|
47
|
-
# # 10.0.1.253
|
48
47
|
# # 10.0.1.254
|
48
|
+
# # 10.0.1.255
|
49
49
|
# # ...
|
50
|
+
# # 10.0.2.0
|
50
51
|
# # 10.0.2.1
|
51
|
-
# # 10.0.2.2
|
52
52
|
# # ...
|
53
|
-
# # 10.0.2.253
|
54
53
|
# # 10.0.2.254
|
54
|
+
# # 10.0.2.255
|
55
55
|
# # ...
|
56
|
+
# # 10.0.3.0
|
56
57
|
# # 10.0.3.1
|
57
|
-
# # 10.0.3.2
|
58
58
|
# # ...
|
59
|
-
# # 10.0.3.253
|
60
59
|
# # 10.0.3.254
|
60
|
+
# # 10.0.3.255
|
61
61
|
#
|
62
62
|
# @api public
|
63
63
|
#
|
@@ -126,23 +126,23 @@ module Ronin
|
|
126
126
|
#
|
127
127
|
# @example Enumerating over a IP-glob range:
|
128
128
|
# IPRange.each('10.0.1-3.*') { |ip| puts ip }
|
129
|
+
# # 10.0.1.0
|
129
130
|
# # 10.0.1.1
|
130
|
-
# # 10.0.1.2
|
131
131
|
# # ...
|
132
|
-
# # 10.0.1.253
|
133
132
|
# # 10.0.1.254
|
133
|
+
# # 10.0.1.255
|
134
134
|
# # ...
|
135
|
+
# # 10.0.2.0
|
135
136
|
# # 10.0.2.1
|
136
|
-
# # 10.0.2.2
|
137
137
|
# # ...
|
138
|
-
# # 10.0.2.253
|
139
138
|
# # 10.0.2.254
|
139
|
+
# # 10.0.2.255
|
140
140
|
# # ...
|
141
|
+
# # 10.0.3.0
|
141
142
|
# # 10.0.3.1
|
142
|
-
# # 10.0.3.2
|
143
143
|
# # ...
|
144
|
-
# # 10.0.3.253
|
145
144
|
# # 10.0.3.254
|
145
|
+
# # 10.0.3.255
|
146
146
|
#
|
147
147
|
# @see #each
|
148
148
|
#
|
@@ -181,6 +181,9 @@ module Ronin
|
|
181
181
|
#
|
182
182
|
# @return [String]
|
183
183
|
#
|
184
|
+
# @see CIDR#string
|
185
|
+
# @see Glob#string
|
186
|
+
#
|
184
187
|
def string
|
185
188
|
@range.string
|
186
189
|
end
|
@@ -190,6 +193,9 @@ module Ronin
|
|
190
193
|
#
|
191
194
|
# @return [Boolean]
|
192
195
|
#
|
196
|
+
# @see CIDR#ipv4?
|
197
|
+
# @see Glob#ipv4?
|
198
|
+
#
|
193
199
|
def ipv4?
|
194
200
|
@range.ipv4?
|
195
201
|
end
|
@@ -199,6 +205,9 @@ module Ronin
|
|
199
205
|
#
|
200
206
|
# @return [Boolean]
|
201
207
|
#
|
208
|
+
# @see CIDR#ipv6?
|
209
|
+
# @see Glob#ipv6?
|
210
|
+
#
|
202
211
|
def ipv6?
|
203
212
|
@range.ipv6?
|
204
213
|
end
|
@@ -230,23 +239,23 @@ module Ronin
|
|
230
239
|
# @example Enumerating over a IP-glob range:
|
231
240
|
# ip_range = IPRange.new('10.0.1-3.*')
|
232
241
|
# ip_range.each { |ip| puts ip }
|
242
|
+
# # 10.0.1.0
|
233
243
|
# # 10.0.1.1
|
234
|
-
# # 10.0.1.2
|
235
244
|
# # ...
|
236
|
-
# # 10.0.1.253
|
237
245
|
# # 10.0.1.254
|
246
|
+
# # 10.0.1.255
|
238
247
|
# # ...
|
248
|
+
# # 10.0.2.0
|
239
249
|
# # 10.0.2.1
|
240
|
-
# # 10.0.2.2
|
241
250
|
# # ...
|
242
|
-
# # 10.0.2.253
|
243
251
|
# # 10.0.2.254
|
252
|
+
# # 10.0.2.255
|
244
253
|
# # ...
|
254
|
+
# # 10.0.3.0
|
245
255
|
# # 10.0.3.1
|
246
|
-
# # 10.0.3.2
|
247
256
|
# # ...
|
248
|
-
# # 10.0.3.253
|
249
257
|
# # 10.0.3.254
|
258
|
+
# # 10.0.3.255
|
250
259
|
#
|
251
260
|
# @see CIDR#each
|
252
261
|
# @see Glob#each
|
@@ -108,7 +108,7 @@ module Ronin
|
|
108
108
|
# Path to the CA certificate file or directory.
|
109
109
|
#
|
110
110
|
# @return [OpenSSL::SSL::SSLSocket]
|
111
|
-
#
|
111
|
+
# The new SSL Socket.
|
112
112
|
#
|
113
113
|
# @api public
|
114
114
|
#
|
@@ -246,7 +246,7 @@ module Ronin
|
|
246
246
|
# The new SSL Socket.
|
247
247
|
#
|
248
248
|
# @return [OpenSSL::SSL::SSLSocket, nil]
|
249
|
-
#
|
249
|
+
# The new SSL Socket. If a block is given, then `nil` will be
|
250
250
|
# returned.
|
251
251
|
#
|
252
252
|
# @example
|
@@ -573,7 +573,7 @@ module Ronin
|
|
573
573
|
# Path to the CA certificate file or directory.
|
574
574
|
#
|
575
575
|
# @return [OpenSSL::SSL::SSLSocket]
|
576
|
-
#
|
576
|
+
# The new SSL Socket.
|
577
577
|
#
|
578
578
|
# @api public
|
579
579
|
#
|
@@ -107,7 +107,7 @@ module Ronin
|
|
107
107
|
# Path to the CA certificate file or directory.
|
108
108
|
#
|
109
109
|
# @return [OpenSSL::SSL::SSLSocket]
|
110
|
-
#
|
110
|
+
# The new SSL Socket.
|
111
111
|
#
|
112
112
|
# @api public
|
113
113
|
#
|
@@ -233,7 +233,7 @@ module Ronin
|
|
233
233
|
# The new SSL Socket.
|
234
234
|
#
|
235
235
|
# @return [OpenSSL::SSL::SSLSocket, nil]
|
236
|
-
#
|
236
|
+
# The new SSL Socket. If a block is given, then `nil` will be
|
237
237
|
# returned.
|
238
238
|
#
|
239
239
|
# @example
|
@@ -519,7 +519,7 @@ module Ronin
|
|
519
519
|
# * `:client_once`
|
520
520
|
#
|
521
521
|
# @return [OpenSSL::SSL::SSLSocket]
|
522
|
-
#
|
522
|
+
# The new SSL Socket.
|
523
523
|
#
|
524
524
|
# @api public
|
525
525
|
#
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: ronin-support
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.0.
|
4
|
+
version: 1.0.6
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Postmodern
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2024-06-20 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: chars
|
@@ -470,7 +470,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
470
470
|
- !ruby/object:Gem::Version
|
471
471
|
version: '0'
|
472
472
|
requirements: []
|
473
|
-
rubygems_version: 3.3.
|
473
|
+
rubygems_version: 3.3.27
|
474
474
|
signing_key:
|
475
475
|
specification_version: 4
|
476
476
|
summary: A support library for ronin-rb.
|