ronin-support-web 0.1.0.rc1
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 +7 -0
- data/.document +4 -0
- data/.github/workflows/ruby.yml +47 -0
- data/.gitignore +13 -0
- data/.rspec +1 -0
- data/.rubocop.yml +19 -0
- data/.ruby-version +1 -0
- data/.yardopts +1 -0
- data/COPYING.txt +165 -0
- data/ChangeLog.md +10 -0
- data/Gemfile +36 -0
- data/README.md +321 -0
- data/Rakefile +31 -0
- data/gemspec.yml +31 -0
- data/lib/ronin/support/web/agent/mixin.rb +361 -0
- data/lib/ronin/support/web/agent.rb +1386 -0
- data/lib/ronin/support/web/html/mixin.rb +115 -0
- data/lib/ronin/support/web/html.rb +116 -0
- data/lib/ronin/support/web/mixin.rb +40 -0
- data/lib/ronin/support/web/version.rb +28 -0
- data/lib/ronin/support/web/websocket/client.rb +129 -0
- data/lib/ronin/support/web/websocket/mixin.rb +888 -0
- data/lib/ronin/support/web/websocket/server.rb +212 -0
- data/lib/ronin/support/web/websocket/socket.rb +185 -0
- data/lib/ronin/support/web/websocket/url_methods.rb +91 -0
- data/lib/ronin/support/web/websocket.rb +360 -0
- data/lib/ronin/support/web/xml/mixin.rb +111 -0
- data/lib/ronin/support/web/xml.rb +110 -0
- data/lib/ronin/support/web.rb +43 -0
- data/ronin-support-web.gemspec +62 -0
- metadata +150 -0
@@ -0,0 +1,360 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
#
|
3
|
+
# ronin-support-web - A web support library for ronin-rb.
|
4
|
+
#
|
5
|
+
# Copyright (c) 2023-2024 Hal Brodigan (postmodern.mod3@gmail.com)
|
6
|
+
#
|
7
|
+
# ronin-support-web is free software: you can redistribute it and/or modify
|
8
|
+
# it under the terms of the GNU Lesser General Public License as published
|
9
|
+
# by the Free Software Foundation, either version 3 of the License, or
|
10
|
+
# (at your option) any later version.
|
11
|
+
#
|
12
|
+
# ronin-support-web is distributed in the hope that it will be useful,
|
13
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
14
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
15
|
+
# GNU Lesser General Public License for more details.
|
16
|
+
#
|
17
|
+
# You should have received a copy of the GNU Lesser General Public License
|
18
|
+
# along with ronin-support-web. If not, see <https://www.gnu.org/licenses/>.
|
19
|
+
#
|
20
|
+
|
21
|
+
require 'ronin/support/web/websocket/client'
|
22
|
+
require 'ronin/support/web/websocket/server'
|
23
|
+
require 'ronin/support/web/websocket/mixin'
|
24
|
+
|
25
|
+
require 'ronin/support/network/tcp'
|
26
|
+
require 'ronin/support/network/ssl'
|
27
|
+
|
28
|
+
module Ronin
|
29
|
+
module Support
|
30
|
+
module Web
|
31
|
+
#
|
32
|
+
# WebSocket helper methods.
|
33
|
+
#
|
34
|
+
module WebSocket
|
35
|
+
# @!macro [new] ssl_kwargs
|
36
|
+
# @option ssl [1, 1.1, 1.2, String, Symbol, nil] :version
|
37
|
+
# The SSL version to use.
|
38
|
+
#
|
39
|
+
# @option ssl [Symbol, Boolean] :verify
|
40
|
+
# Specifies whether to verify the SSL certificate.
|
41
|
+
# May be one of the following:
|
42
|
+
#
|
43
|
+
# * `:none`
|
44
|
+
# * `:peer`
|
45
|
+
# * `:fail_if_no_peer_cert`
|
46
|
+
# * `:client_once`
|
47
|
+
#
|
48
|
+
# @option ssl [Crypto::Key::RSA, OpenSSL::PKey::RSA, nil] :key
|
49
|
+
# The RSA key to use for the SSL context.
|
50
|
+
#
|
51
|
+
# @option ssl [String] :key_file
|
52
|
+
# The path to the SSL `.key` file.
|
53
|
+
#
|
54
|
+
# @option ssl [Crypto::Cert, OpenSSL::X509::Certificate, nil] :cert
|
55
|
+
# The X509 certificate to use for the SSL context.
|
56
|
+
#
|
57
|
+
# @option ssl [String] :cert_file
|
58
|
+
# The path to the SSL `.crt` file.
|
59
|
+
#
|
60
|
+
# @option ssl [String] :ca_bundle
|
61
|
+
# Path to the CA certificate file or directory.
|
62
|
+
|
63
|
+
# @!macro [new] client_kwargs
|
64
|
+
# @option kwargs [String, nil] :bind_host
|
65
|
+
# The optional host to bind the server socket to.
|
66
|
+
#
|
67
|
+
# @option kwargs [Integer, nil] :bind_port
|
68
|
+
# The optioanl port to bind the server socket to. If not
|
69
|
+
# specified, it will default to the port of the URL.
|
70
|
+
#
|
71
|
+
# @!macro ssl_kwargs
|
72
|
+
|
73
|
+
#
|
74
|
+
# Tests whether the WebSocket is open.
|
75
|
+
#
|
76
|
+
# @param [String, URI::WS, URI::WSS] url
|
77
|
+
# The `ws://` or `wss://` URL to connect to.
|
78
|
+
#
|
79
|
+
# @param [Hash{Symbol => Object}] ssl
|
80
|
+
# Additional keyword arguments for
|
81
|
+
# `Ronin::Support::Network::SSL.connect`.
|
82
|
+
#
|
83
|
+
# @param [Hash{Symbol => Object}] kwargs
|
84
|
+
# Additional keyword arguments for {Client#initialize}.
|
85
|
+
#
|
86
|
+
# @!macro client_kwargs
|
87
|
+
#
|
88
|
+
# @return [Boolean, nil]
|
89
|
+
# Specifies whether the WebSocket is open.
|
90
|
+
# If the connection was not accepted, `nil` will be returned.
|
91
|
+
#
|
92
|
+
# @api public
|
93
|
+
#
|
94
|
+
def self.open?(url, ssl: {}, **kwargs)
|
95
|
+
uri = URI(url)
|
96
|
+
host = uri.host
|
97
|
+
port = uri.port
|
98
|
+
|
99
|
+
case uri.scheme
|
100
|
+
when 'ws'
|
101
|
+
Support::Network::TCP.open?(host,port,**kwargs)
|
102
|
+
when 'wss'
|
103
|
+
Support::Network::SSL.open?(host,port,**kwargs,**ssl)
|
104
|
+
else
|
105
|
+
raise(ArgumentError,"unsupported WebSocket URI scheme: #{url.inspect}")
|
106
|
+
end
|
107
|
+
end
|
108
|
+
|
109
|
+
# Connects to a websocket.
|
110
|
+
#
|
111
|
+
# @param [String, URI::WS, URI::WSS] url
|
112
|
+
# The `ws://` or `wss://` URL to connect to.
|
113
|
+
#
|
114
|
+
# @param [Hash{Symbol => Object}] ssl
|
115
|
+
# Additional keyword arguments for
|
116
|
+
# `Ronin::Support::Network::SSL.connect`.
|
117
|
+
#
|
118
|
+
# @param [Hash{Symbol => Object}] kwargs
|
119
|
+
# Additional keyword arguments for {Client#initialize}.
|
120
|
+
#
|
121
|
+
# @!macro client_kwargs
|
122
|
+
#
|
123
|
+
# @yield [websocket]
|
124
|
+
# If a block is given, then it will be passed the WebSocket
|
125
|
+
# connection. Once the block has returned, the WebSocket connection
|
126
|
+
# will be closed.
|
127
|
+
#
|
128
|
+
# @yieldparam [Client] websocket
|
129
|
+
# The WebSocket connection.
|
130
|
+
#
|
131
|
+
# @return [Client]
|
132
|
+
# The WebSocket connection.
|
133
|
+
#
|
134
|
+
# @example Connecting to a WebSocket server:
|
135
|
+
# websocket_connect('ws://websocket-echo.com')
|
136
|
+
# # => #<Ronin::Support::Web::WebSocket::Client: ...>
|
137
|
+
#
|
138
|
+
# @example Creating a temporary WebSocket connection:
|
139
|
+
# websocket_connect('ws://websocket-echo.com') do |websocket|
|
140
|
+
# # ...
|
141
|
+
# end
|
142
|
+
#
|
143
|
+
# @api public
|
144
|
+
#
|
145
|
+
def self.connect(url, ssl: {}, **kwargs)
|
146
|
+
client = Client.new(url, ssl: ssl, **kwargs)
|
147
|
+
|
148
|
+
if block_given?
|
149
|
+
yield client
|
150
|
+
client.close
|
151
|
+
else
|
152
|
+
client
|
153
|
+
end
|
154
|
+
end
|
155
|
+
|
156
|
+
#
|
157
|
+
# Connects to the WebSocket and sends the data.
|
158
|
+
#
|
159
|
+
# @param [String] data
|
160
|
+
# The data to send to the WebSocet.
|
161
|
+
#
|
162
|
+
# @param [String, URI::WS, URI::WSS] url
|
163
|
+
# The `ws://` or `wss://` URL to connect to.
|
164
|
+
#
|
165
|
+
# @param [:text, :binary, :ping, :pong, :close] type
|
166
|
+
# The data frame type.
|
167
|
+
#
|
168
|
+
# @param [Hash{Symbol => Object}] ssl
|
169
|
+
# Additional keyword arguments for
|
170
|
+
# `Ronin::Support::Network::SSL.connect`.
|
171
|
+
#
|
172
|
+
# @param [Hash{Symbol => Object}] kwargs
|
173
|
+
# Additional keyword arguments for {Client#initialize}.
|
174
|
+
#
|
175
|
+
# @!macro client_kwargs
|
176
|
+
#
|
177
|
+
# @yield [websocket]
|
178
|
+
# If a block is given, then it will be passed the WebSocket
|
179
|
+
# connection. Once the block has returned, the WebSocket connection
|
180
|
+
# will be closed.
|
181
|
+
#
|
182
|
+
# @yieldparam [Client] websocket
|
183
|
+
# The WebSocket connection.
|
184
|
+
#
|
185
|
+
# @return [Client]
|
186
|
+
# The WebSocket connection.
|
187
|
+
#
|
188
|
+
# @api public
|
189
|
+
#
|
190
|
+
def self.connect_and_send(data,url, type: :text, ssl: {}, **kwargs)
|
191
|
+
client = connect(url, ssl: ssl, **kwargs)
|
192
|
+
client.send(data, type: type)
|
193
|
+
|
194
|
+
yield client if block_given?
|
195
|
+
return client
|
196
|
+
end
|
197
|
+
|
198
|
+
#
|
199
|
+
# Connects to the WebSocket, sends the data, and closes the connection.
|
200
|
+
#
|
201
|
+
# @param [String] data
|
202
|
+
# The data to send to the WebSocet.
|
203
|
+
#
|
204
|
+
# @param [String, URI::WS, URI::WSS] url
|
205
|
+
# The `ws://` or `wss://` URL to connect to.
|
206
|
+
#
|
207
|
+
# @param [:text, :binary, :ping, :pong, :close] type
|
208
|
+
# The data frame type.
|
209
|
+
#
|
210
|
+
# @param [Hash{Symbol => Object}] ssl
|
211
|
+
# Additional keyword arguments for
|
212
|
+
# `Ronin::Support::Network::SSL.connect`.
|
213
|
+
#
|
214
|
+
# @param [Hash{Symbol => Object}] kwargs
|
215
|
+
# Additional keyword arguments for {Client#initialize}.
|
216
|
+
#
|
217
|
+
# @!macro client_kwargs
|
218
|
+
#
|
219
|
+
# @return [true]
|
220
|
+
#
|
221
|
+
# @api public
|
222
|
+
#
|
223
|
+
def self.send(data,url, type: :text, ssl: {}, **kwargs)
|
224
|
+
connect(url, ssl: ssl, **kwargs) do |client|
|
225
|
+
client.send(data, type: type)
|
226
|
+
end
|
227
|
+
|
228
|
+
return true
|
229
|
+
end
|
230
|
+
|
231
|
+
# @!macro [new] server_kwargs
|
232
|
+
# @option kwargs [String, nil] :bind_host
|
233
|
+
# The optional host to bind the server socket to.
|
234
|
+
#
|
235
|
+
# @option kwargs [Integer, nil] :bind_port
|
236
|
+
# The optioanl port to bind the server socket to. If not
|
237
|
+
# specified, it will default to the port of the URL.
|
238
|
+
#
|
239
|
+
# @option kwargs [Integer] :backlog (5)
|
240
|
+
# The maximum backlog of pending connections.
|
241
|
+
#
|
242
|
+
# @!macro ssl_kwargs
|
243
|
+
|
244
|
+
#
|
245
|
+
# Starts a WebSocket server.
|
246
|
+
#
|
247
|
+
# @param [String, URI::WS, URI::WSS] url
|
248
|
+
# The `ws://` or `wss://` URL to connect to.
|
249
|
+
#
|
250
|
+
# @param [Hash{Symbol => Object}] ssl
|
251
|
+
# Additional keyword arguments for
|
252
|
+
# `Ronin::Support::Network::SSL.server`.
|
253
|
+
#
|
254
|
+
# @param [Hash{Symbol => Object}] kwargs
|
255
|
+
# Additional keyword arguments for {Server#initialize}.
|
256
|
+
#
|
257
|
+
# @!macro server_kwargs
|
258
|
+
#
|
259
|
+
# @yield [server]
|
260
|
+
# If a block is given, then it will be passed the WebSocket server.
|
261
|
+
# Once the block has returned, the WebSocket server will be closed.
|
262
|
+
#
|
263
|
+
# @yieldparam [Server] server
|
264
|
+
# The WebSocket server.
|
265
|
+
#
|
266
|
+
# @return [Server]
|
267
|
+
# The WebSocket server.
|
268
|
+
#
|
269
|
+
# @api public
|
270
|
+
#
|
271
|
+
def self.server(url, ssl: {}, **kwargs)
|
272
|
+
server = Server.new(url, ssl: ssl, **kwargs)
|
273
|
+
|
274
|
+
if block_given?
|
275
|
+
yield server
|
276
|
+
server.close
|
277
|
+
else
|
278
|
+
server
|
279
|
+
end
|
280
|
+
end
|
281
|
+
|
282
|
+
#
|
283
|
+
# Creates a new WebSocket server listening on a given host and port,
|
284
|
+
# accepting clients in a loop.
|
285
|
+
#
|
286
|
+
# @param [String, URI::WS, URI::WSS] url
|
287
|
+
# The `ws://` or `wss://` URL to connect to.
|
288
|
+
#
|
289
|
+
# @param [Hash{Symbol => Object}] ssl
|
290
|
+
# Additional keyword arguments for
|
291
|
+
# `Ronin::Support::Network::SSL.server`.
|
292
|
+
#
|
293
|
+
# @param [Hash{Symbol => Object}] kwargs
|
294
|
+
# Additional keyword arguments for {Server#initialize}.
|
295
|
+
#
|
296
|
+
# @!macro server_kwargs
|
297
|
+
#
|
298
|
+
# @yield [client]
|
299
|
+
# The given block will be passed the newly connected WebSocket
|
300
|
+
# client. After the block has finished, the WebSocket client will be
|
301
|
+
# closed.
|
302
|
+
#
|
303
|
+
# @yieldparam [Server::Client] client
|
304
|
+
# A newly connected WebSocket client.
|
305
|
+
#
|
306
|
+
# @return [nil]
|
307
|
+
#
|
308
|
+
# @api public
|
309
|
+
#
|
310
|
+
def self.server_loop(url, ssl: {}, **kwargs)
|
311
|
+
server(url, ssl: ssl, **kwargs) do |server|
|
312
|
+
loop do
|
313
|
+
client = server.accept
|
314
|
+
|
315
|
+
yield client if block_given?
|
316
|
+
client.close
|
317
|
+
end
|
318
|
+
end
|
319
|
+
end
|
320
|
+
|
321
|
+
#
|
322
|
+
# Opens a WebSocket server, accepts a single connection, yields it to
|
323
|
+
# the given block, then closes both the connection and the server.
|
324
|
+
#
|
325
|
+
# @param [String, URI::WS, URI::WSS] url
|
326
|
+
# The `ws://` or `wss://` URL to connect to.
|
327
|
+
#
|
328
|
+
# @param [Hash{Symbol => Object}] ssl
|
329
|
+
# Additional keyword arguments for
|
330
|
+
# `Ronin::Support::Network::SSL.server`.
|
331
|
+
#
|
332
|
+
# @param [Hash{Symbol => Object}] kwargs
|
333
|
+
# Additional keyword arguments for {Server#initialize}.
|
334
|
+
#
|
335
|
+
# @!macro server_kwargs
|
336
|
+
#
|
337
|
+
# @yield [client]
|
338
|
+
# The given block will be passed the newly connected WebSocket
|
339
|
+
# client. After the block has finished, the WebSocket client will be
|
340
|
+
# closed.
|
341
|
+
#
|
342
|
+
# @yieldparam [Server::Client] client
|
343
|
+
# A newly connected WebSocket client.
|
344
|
+
#
|
345
|
+
# @return [nil]
|
346
|
+
#
|
347
|
+
# @api public
|
348
|
+
#
|
349
|
+
def self.accept(url, ssl: {}, **kwargs)
|
350
|
+
server(url, ssl: ssl, **kwargs) do |server|
|
351
|
+
client = server.accept
|
352
|
+
|
353
|
+
yield client if block_given?
|
354
|
+
client.close
|
355
|
+
end
|
356
|
+
end
|
357
|
+
end
|
358
|
+
end
|
359
|
+
end
|
360
|
+
end
|
@@ -0,0 +1,111 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
#
|
3
|
+
# ronin-support-web - A web support library for ronin-rb.
|
4
|
+
#
|
5
|
+
# Copyright (c) 2023-2024 Hal Brodigan (postmodern.mod3@gmail.com)
|
6
|
+
#
|
7
|
+
# ronin-support-web is free software: you can redistribute it and/or modify
|
8
|
+
# it under the terms of the GNU Lesser General Public License as published
|
9
|
+
# by the Free Software Foundation, either version 3 of the License, or
|
10
|
+
# (at your option) any later version.
|
11
|
+
#
|
12
|
+
# ronin-support-web is distributed in the hope that it will be useful,
|
13
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
14
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
15
|
+
# GNU Lesser General Public License for more details.
|
16
|
+
#
|
17
|
+
# You should have received a copy of the GNU Lesser General Public License
|
18
|
+
# along with ronin-support-web. If not, see <https://www.gnu.org/licenses/>.
|
19
|
+
#
|
20
|
+
|
21
|
+
require 'ronin/support/web/xml'
|
22
|
+
|
23
|
+
module Ronin
|
24
|
+
module Support
|
25
|
+
module Web
|
26
|
+
module XML
|
27
|
+
#
|
28
|
+
# Provides helper methods for working with XML.
|
29
|
+
#
|
30
|
+
# @api public
|
31
|
+
#
|
32
|
+
module Mixin
|
33
|
+
#
|
34
|
+
# Parses the body of a document into a HTML document object.
|
35
|
+
#
|
36
|
+
# @param [String, IO] xml
|
37
|
+
# The XML to parse.
|
38
|
+
#
|
39
|
+
# @yield [doc]
|
40
|
+
# If a block is given, it will be passed the newly created document
|
41
|
+
# object.
|
42
|
+
#
|
43
|
+
# @yieldparam [Nokogiri::XML::Document] doc
|
44
|
+
# The new XML document object.
|
45
|
+
#
|
46
|
+
# @return [Nokogiri::XML::Document]
|
47
|
+
# The new HTML document object.
|
48
|
+
#
|
49
|
+
# @see http://rubydoc.info/gems/nokogiri/Nokogiri/XML/Document
|
50
|
+
# @see XML.parse
|
51
|
+
#
|
52
|
+
def xml_parse(xml,&block)
|
53
|
+
XML.parse(xml,&block)
|
54
|
+
end
|
55
|
+
|
56
|
+
#
|
57
|
+
# Opens an XML file.
|
58
|
+
#
|
59
|
+
# @param [String] path
|
60
|
+
# The path to the XML file.
|
61
|
+
#
|
62
|
+
# @yield [doc]
|
63
|
+
# If a block is given, it will be passed the newly created document
|
64
|
+
# object.
|
65
|
+
#
|
66
|
+
# @yieldparam [Nokogiri::XML::Document] doc
|
67
|
+
# The new XML document object.
|
68
|
+
#
|
69
|
+
# @return [Nokogiri::XML::Document]
|
70
|
+
# The parsed XML file.
|
71
|
+
#
|
72
|
+
# @example
|
73
|
+
# doc = XML.open('index.xml')
|
74
|
+
# # => #<Nokogiri::XML::Document:...>
|
75
|
+
#
|
76
|
+
# @see http://rubydoc.info/gems/nokogiri/Nokogiri/XML/Document
|
77
|
+
# @see XML.open
|
78
|
+
#
|
79
|
+
def xml_open(path,&block)
|
80
|
+
XML.open(path,&block)
|
81
|
+
end
|
82
|
+
|
83
|
+
alias open_xml xml_open
|
84
|
+
|
85
|
+
#
|
86
|
+
# Creates a new `Nokogiri::XML::Builder`.
|
87
|
+
#
|
88
|
+
# @yield []
|
89
|
+
# The block that will be used to construct the XML document.
|
90
|
+
#
|
91
|
+
# @return [Nokogiri::XML::Builder]
|
92
|
+
# The new XML builder object.
|
93
|
+
#
|
94
|
+
# @example
|
95
|
+
# xml_build do
|
96
|
+
# root {
|
97
|
+
# foo(id: 'bar')
|
98
|
+
# }
|
99
|
+
# end
|
100
|
+
#
|
101
|
+
# @see http://rubydoc.info/gems/nokogiri/Nokogiri/XML/Builder
|
102
|
+
# @see XML.build
|
103
|
+
#
|
104
|
+
def xml_build(&block)
|
105
|
+
XML.build(&block)
|
106
|
+
end
|
107
|
+
end
|
108
|
+
end
|
109
|
+
end
|
110
|
+
end
|
111
|
+
end
|
@@ -0,0 +1,110 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
#
|
3
|
+
# ronin-support-web - A web support library for ronin-rb.
|
4
|
+
#
|
5
|
+
# Copyright (c) 2023-2024 Hal Brodigan (postmodern.mod3@gmail.com)
|
6
|
+
#
|
7
|
+
# ronin-support-web is free software: you can redistribute it and/or modify
|
8
|
+
# it under the terms of the GNU Lesser General Public License as published
|
9
|
+
# by the Free Software Foundation, either version 3 of the License, or
|
10
|
+
# (at your option) any later version.
|
11
|
+
#
|
12
|
+
# ronin-support-web is distributed in the hope that it will be useful,
|
13
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
14
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
15
|
+
# GNU Lesser General Public License for more details.
|
16
|
+
#
|
17
|
+
# You should have received a copy of the GNU Lesser General Public License
|
18
|
+
# along with ronin-support-web. If not, see <https://www.gnu.org/licenses/>.
|
19
|
+
#
|
20
|
+
|
21
|
+
require 'nokogiri'
|
22
|
+
|
23
|
+
module Ronin
|
24
|
+
module Support
|
25
|
+
module Web
|
26
|
+
#
|
27
|
+
# XML helper methods.
|
28
|
+
#
|
29
|
+
module XML
|
30
|
+
#
|
31
|
+
# Parses the body of a document into a HTML document object.
|
32
|
+
#
|
33
|
+
# @param [String, IO] xml
|
34
|
+
# The XML to parse.
|
35
|
+
#
|
36
|
+
# @yield [doc]
|
37
|
+
# If a block is given, it will be passed the newly created document
|
38
|
+
# object.
|
39
|
+
#
|
40
|
+
# @yieldparam [Nokogiri::XML::Document] doc
|
41
|
+
# The new XML document object.
|
42
|
+
#
|
43
|
+
# @return [Nokogiri::XML::Document]
|
44
|
+
# The new HTML document object.
|
45
|
+
#
|
46
|
+
# @see http://rubydoc.info/gems/nokogiri/Nokogiri/XML/Document
|
47
|
+
#
|
48
|
+
# @api public
|
49
|
+
#
|
50
|
+
def self.parse(xml)
|
51
|
+
doc = Nokogiri::XML.parse(xml)
|
52
|
+
yield doc if block_given?
|
53
|
+
return doc
|
54
|
+
end
|
55
|
+
|
56
|
+
#
|
57
|
+
# Opens an XML file.
|
58
|
+
#
|
59
|
+
# @param [String] path
|
60
|
+
# The path to the XML file.
|
61
|
+
#
|
62
|
+
# @yield [doc]
|
63
|
+
# If a block is given, it will be passed the newly created document
|
64
|
+
# object.
|
65
|
+
#
|
66
|
+
# @yieldparam [Nokogiri::XML::Document] doc
|
67
|
+
# The new XML document object.
|
68
|
+
#
|
69
|
+
# @return [Nokogiri::XML::Document]
|
70
|
+
# The parsed XML file.
|
71
|
+
#
|
72
|
+
# @example
|
73
|
+
# doc = XML.open('data.xml')
|
74
|
+
# # => #<Nokogiri::XML::Document:...>
|
75
|
+
#
|
76
|
+
# @api public
|
77
|
+
#
|
78
|
+
def self.open(path)
|
79
|
+
doc = Nokogiri::XML(File.open(path))
|
80
|
+
yield doc if block_given?
|
81
|
+
return doc
|
82
|
+
end
|
83
|
+
|
84
|
+
#
|
85
|
+
# Creates a new `Nokogiri::XML::Builder`.
|
86
|
+
#
|
87
|
+
# @yield []
|
88
|
+
# The block that will be used to construct the XML document.
|
89
|
+
#
|
90
|
+
# @return [Nokogiri::XML::Builder]
|
91
|
+
# The new XML builder object.
|
92
|
+
#
|
93
|
+
# @example
|
94
|
+
# XML.build do
|
95
|
+
# root {
|
96
|
+
# foo(id: 'bar')
|
97
|
+
# }
|
98
|
+
# end
|
99
|
+
#
|
100
|
+
# @see http://rubydoc.info/gems/nokogiri/Nokogiri/XML/Builder
|
101
|
+
#
|
102
|
+
# @api public
|
103
|
+
#
|
104
|
+
def self.build(&block)
|
105
|
+
Nokogiri::XML::Builder.new(&block)
|
106
|
+
end
|
107
|
+
end
|
108
|
+
end
|
109
|
+
end
|
110
|
+
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
#
|
3
|
+
# ronin-support-web - A web support library for ronin-rb.
|
4
|
+
#
|
5
|
+
# Copyright (c) 2023-2024 Hal Brodigan (postmodern.mod3@gmail.com)
|
6
|
+
#
|
7
|
+
# ronin-support-web is free software: you can redistribute it and/or modify
|
8
|
+
# it under the terms of the GNU Lesser General Public License as published
|
9
|
+
# by the Free Software Foundation, either version 3 of the License, or
|
10
|
+
# (at your option) any later version.
|
11
|
+
#
|
12
|
+
# ronin-support-web is distributed in the hope that it will be useful,
|
13
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
14
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
15
|
+
# GNU Lesser General Public License for more details.
|
16
|
+
#
|
17
|
+
# You should have received a copy of the GNU Lesser General Public License
|
18
|
+
# along with ronin-support-web. If not, see <https://www.gnu.org/licenses/>.
|
19
|
+
#
|
20
|
+
|
21
|
+
require 'ronin/support/web/xml'
|
22
|
+
require 'ronin/support/web/html'
|
23
|
+
require 'ronin/support/web/mixin'
|
24
|
+
require 'ronin/support/web/version'
|
25
|
+
|
26
|
+
module Ronin
|
27
|
+
module Support
|
28
|
+
#
|
29
|
+
# Top-level namespace for `ronin-support-web`.
|
30
|
+
#
|
31
|
+
# ## Example
|
32
|
+
#
|
33
|
+
# require 'ronin/support/web'
|
34
|
+
# include Ronin::Support::Web
|
35
|
+
#
|
36
|
+
# html_parse "<html>...</html>"
|
37
|
+
# # => #<Nokogiri::HTML::Document: ...>
|
38
|
+
#
|
39
|
+
module Web
|
40
|
+
include Mixin
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
@@ -0,0 +1,62 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'yaml'
|
4
|
+
|
5
|
+
Gem::Specification.new do |gem|
|
6
|
+
gemspec = YAML.load_file('gemspec.yml')
|
7
|
+
|
8
|
+
gem.name = gemspec.fetch('name')
|
9
|
+
gem.version = gemspec.fetch('version') do
|
10
|
+
lib_dir = File.join(File.dirname(__FILE__),'lib')
|
11
|
+
$LOAD_PATH << lib_dir unless $LOAD_PATH.include?(lib_dir)
|
12
|
+
|
13
|
+
require 'ronin/support/web/version'
|
14
|
+
Ronin::Support::Web::VERSION
|
15
|
+
end
|
16
|
+
|
17
|
+
gem.summary = gemspec['summary']
|
18
|
+
gem.description = gemspec['description']
|
19
|
+
gem.licenses = Array(gemspec['license'])
|
20
|
+
gem.authors = Array(gemspec['authors'])
|
21
|
+
gem.email = gemspec['email']
|
22
|
+
gem.homepage = gemspec['homepage']
|
23
|
+
gem.metadata = gemspec['metadata'] if gemspec['metadata']
|
24
|
+
|
25
|
+
glob = ->(patterns) { gem.files & Dir[*patterns] }
|
26
|
+
|
27
|
+
gem.files = `git ls-files`.split($/)
|
28
|
+
gem.files = glob[gemspec['files']] if gemspec['files']
|
29
|
+
gem.files += Array(gemspec['generated_files'])
|
30
|
+
# exclude test files from the packages gem
|
31
|
+
gem.files -= glob[gemspec['test_files'] || 'spec/{**/}*']
|
32
|
+
|
33
|
+
gem.executables = gemspec.fetch('executables') do
|
34
|
+
glob['bin/*'].map { |path| File.basename(path) }
|
35
|
+
end
|
36
|
+
|
37
|
+
gem.extensions = glob[gemspec['extensions'] || 'ext/**/extconf.rb']
|
38
|
+
gem.extra_rdoc_files = glob[gemspec['extra_doc_files'] || '*.{txt,md}']
|
39
|
+
|
40
|
+
gem.require_paths = Array(gemspec.fetch('require_paths') {
|
41
|
+
%w[ext lib].select { |dir| File.directory?(dir) }
|
42
|
+
})
|
43
|
+
|
44
|
+
gem.requirements = gemspec['requirements']
|
45
|
+
gem.required_ruby_version = gemspec['required_ruby_version']
|
46
|
+
gem.required_rubygems_version = gemspec['required_rubygems_version']
|
47
|
+
gem.post_install_message = gemspec['post_install_message']
|
48
|
+
|
49
|
+
split = ->(string) { string.split(/,\s*/) }
|
50
|
+
|
51
|
+
if gemspec['dependencies']
|
52
|
+
gemspec['dependencies'].each do |name,versions|
|
53
|
+
gem.add_dependency(name,split[versions])
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
if gemspec['development_dependencies']
|
58
|
+
gemspec['development_dependencies'].each do |name,versions|
|
59
|
+
gem.add_development_dependency(name,split[versions])
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|