ronin-code-sql 2.0.0.beta1
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/.editorconfig +11 -0
- data/.github/workflows/ruby.yml +27 -0
- data/.gitignore +11 -0
- data/.mailmap +1 -0
- data/.rspec +1 -0
- data/.ruby-version +1 -0
- data/.yardopts +1 -0
- data/COPYING.txt +165 -0
- data/ChangeLog.md +104 -0
- data/Gemfile +28 -0
- data/README.md +212 -0
- data/Rakefile +30 -0
- data/gemspec.yml +25 -0
- data/lib/ronin/code/sql/binary_expr.rb +53 -0
- data/lib/ronin/code/sql/clause.rb +74 -0
- data/lib/ronin/code/sql/clauses.rb +310 -0
- data/lib/ronin/code/sql/emittable.rb +88 -0
- data/lib/ronin/code/sql/emitter.rb +406 -0
- data/lib/ronin/code/sql/field.rb +110 -0
- data/lib/ronin/code/sql/fields.rb +82 -0
- data/lib/ronin/code/sql/function.rb +53 -0
- data/lib/ronin/code/sql/functions.rb +1265 -0
- data/lib/ronin/code/sql/injection.rb +168 -0
- data/lib/ronin/code/sql/injection_expr.rb +113 -0
- data/lib/ronin/code/sql/literal.rb +40 -0
- data/lib/ronin/code/sql/literals.rb +83 -0
- data/lib/ronin/code/sql/operators.rb +384 -0
- data/lib/ronin/code/sql/statement.rb +72 -0
- data/lib/ronin/code/sql/statement_list.rb +112 -0
- data/lib/ronin/code/sql/statements.rb +117 -0
- data/lib/ronin/code/sql/unary_expr.rb +38 -0
- data/lib/ronin/code/sql/version.rb +28 -0
- data/lib/ronin/code/sql.rb +96 -0
- data/ronin-code-sql.gemspec +62 -0
- data/spec/spec_helper.rb +3 -0
- data/spec/sql/binary_expr_examples.rb +25 -0
- data/spec/sql/binary_expr_spec.rb +5 -0
- data/spec/sql/clause_examples.rb +43 -0
- data/spec/sql/clause_spec.rb +31 -0
- data/spec/sql/clauses_spec.rb +47 -0
- data/spec/sql/emittable_spec.rb +41 -0
- data/spec/sql/emitter_spec.rb +533 -0
- data/spec/sql/field_spec.rb +103 -0
- data/spec/sql/fields_spec.rb +40 -0
- data/spec/sql/function_examples.rb +30 -0
- data/spec/sql/function_spec.rb +25 -0
- data/spec/sql/functions_spec.rb +113 -0
- data/spec/sql/injection_expr_spec.rb +98 -0
- data/spec/sql/injection_spec.rb +172 -0
- data/spec/sql/literal_spec.rb +5 -0
- data/spec/sql/literals_spec.rb +46 -0
- data/spec/sql/operators_spec.rb +44 -0
- data/spec/sql/statement_examples.rb +39 -0
- data/spec/sql/statement_list_spec.rb +48 -0
- data/spec/sql/statement_spec.rb +38 -0
- data/spec/sql/statements_spec.rb +22 -0
- data/spec/sql/unary_expr_examples.rb +20 -0
- data/spec/sql/unary_expr_spec.rb +5 -0
- data/spec/sql_spec.rb +18 -0
- metadata +157 -0
@@ -0,0 +1,406 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
#
|
3
|
+
# ronin-code-sql - A Ruby DSL for crafting SQL Injections.
|
4
|
+
#
|
5
|
+
# Copyright (c) 2007-2022 Hal Brodigan (postmodern.mod3 at gmail.com)
|
6
|
+
#
|
7
|
+
# ronin-code-sql 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-code-sql 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-code-sql. If not, see <https://www.gnu.org/licenses/>.
|
19
|
+
#
|
20
|
+
|
21
|
+
require 'ronin/support/encoding/sql'
|
22
|
+
|
23
|
+
module Ronin
|
24
|
+
module Code
|
25
|
+
module SQL
|
26
|
+
#
|
27
|
+
# Generates raw SQL.
|
28
|
+
#
|
29
|
+
# @api private
|
30
|
+
#
|
31
|
+
class Emitter
|
32
|
+
|
33
|
+
# The case to use when emitting keywords
|
34
|
+
attr_reader :case
|
35
|
+
|
36
|
+
# String to use for white-space
|
37
|
+
attr_reader :space
|
38
|
+
|
39
|
+
# Type of String quotes to use
|
40
|
+
attr_reader :quotes
|
41
|
+
|
42
|
+
#
|
43
|
+
# Initializes the SQL Emitter.
|
44
|
+
#
|
45
|
+
# @param [String] space
|
46
|
+
# String to use for white-space.
|
47
|
+
#
|
48
|
+
# @param [:single, :double] quotes
|
49
|
+
# Type of quotes to use for Strings.
|
50
|
+
#
|
51
|
+
# @param [Hash{Symbol => Object}] kwargs
|
52
|
+
# Emitter options.
|
53
|
+
#
|
54
|
+
# @option kwargs [:lower, :upper, :random, nil] :case
|
55
|
+
# Case for keywords.
|
56
|
+
#
|
57
|
+
def initialize(space: ' ', quotes: :single, **kwargs)
|
58
|
+
@case = kwargs[:case] # HACK: because `case` is a ruby keyword
|
59
|
+
@space = space
|
60
|
+
@quotes = quotes
|
61
|
+
end
|
62
|
+
|
63
|
+
#
|
64
|
+
# Emits a SQL keyword.
|
65
|
+
#
|
66
|
+
# @param [Symbol, Array<Symbol>] keyword
|
67
|
+
# The SQL keyword.
|
68
|
+
#
|
69
|
+
# @return [String]
|
70
|
+
# The raw SQL.
|
71
|
+
#
|
72
|
+
def emit_keyword(keyword)
|
73
|
+
keyword = Array(keyword).join(@space)
|
74
|
+
|
75
|
+
case @case
|
76
|
+
when :upper then keyword.upcase
|
77
|
+
when :lower then keyword.downcase
|
78
|
+
when :random
|
79
|
+
keyword.tap do
|
80
|
+
(keyword.length / 2).times do
|
81
|
+
index = rand(keyword.length)
|
82
|
+
keyword[index] = keyword[index].swapcase
|
83
|
+
end
|
84
|
+
end
|
85
|
+
else
|
86
|
+
keyword
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
#
|
91
|
+
# Emits a SQL operator.
|
92
|
+
#
|
93
|
+
# @param [Array<Symbol>, Symbol] op
|
94
|
+
# The operator symbol.
|
95
|
+
#
|
96
|
+
# @return [String]
|
97
|
+
# The raw SQL.
|
98
|
+
#
|
99
|
+
def emit_operator(op)
|
100
|
+
case op
|
101
|
+
when /^\W+$/ then op.to_s
|
102
|
+
else emit_keyword(op)
|
103
|
+
end
|
104
|
+
end
|
105
|
+
|
106
|
+
#
|
107
|
+
# Emits the `NULL` value.
|
108
|
+
#
|
109
|
+
# @return [String]
|
110
|
+
#
|
111
|
+
def emit_null
|
112
|
+
emit_keyword(:NULL)
|
113
|
+
end
|
114
|
+
|
115
|
+
#
|
116
|
+
# Emits a `false` value.
|
117
|
+
#
|
118
|
+
# @return [String]
|
119
|
+
# The raw SQL.
|
120
|
+
#
|
121
|
+
def emit_false
|
122
|
+
"1=0"
|
123
|
+
end
|
124
|
+
|
125
|
+
#
|
126
|
+
# Emits a `true` value.
|
127
|
+
#
|
128
|
+
# @return [String]
|
129
|
+
# The raw SQL.
|
130
|
+
#
|
131
|
+
def emit_true
|
132
|
+
"1=1"
|
133
|
+
end
|
134
|
+
|
135
|
+
#
|
136
|
+
# Emits a SQL Integer.
|
137
|
+
#
|
138
|
+
# @param [Integer] int
|
139
|
+
# The Integer.
|
140
|
+
#
|
141
|
+
# @return [String]
|
142
|
+
# The raw SQL.
|
143
|
+
#
|
144
|
+
def emit_integer(int)
|
145
|
+
int.to_s
|
146
|
+
end
|
147
|
+
|
148
|
+
#
|
149
|
+
# Emits a SQL Decimal.
|
150
|
+
#
|
151
|
+
# @param [Float] decimal
|
152
|
+
# The decimal.
|
153
|
+
#
|
154
|
+
# @return [String]
|
155
|
+
# The raw SQL.
|
156
|
+
#
|
157
|
+
def emit_decimal(decimal)
|
158
|
+
decimal.to_s
|
159
|
+
end
|
160
|
+
|
161
|
+
#
|
162
|
+
# Emits a SQL String.
|
163
|
+
#
|
164
|
+
# @param [String] string
|
165
|
+
# The String.
|
166
|
+
#
|
167
|
+
# @return [String]
|
168
|
+
# The raw SQL.
|
169
|
+
#
|
170
|
+
def emit_string(string)
|
171
|
+
Support::Encoding::SQL.escape(string, quotes: @quotes)
|
172
|
+
end
|
173
|
+
|
174
|
+
#
|
175
|
+
# Emits a SQL field.
|
176
|
+
#
|
177
|
+
# @param [Field, Symbol, String] field
|
178
|
+
# The SQL field.
|
179
|
+
#
|
180
|
+
# @return [String]
|
181
|
+
# The raw SQL.
|
182
|
+
#
|
183
|
+
def emit_field(field)
|
184
|
+
name = emit_keyword(field.name)
|
185
|
+
|
186
|
+
if field.parent
|
187
|
+
name = "#{emit_field(field.parent)}.#{name}"
|
188
|
+
end
|
189
|
+
|
190
|
+
return name
|
191
|
+
end
|
192
|
+
|
193
|
+
#
|
194
|
+
# Emits a list of elements.
|
195
|
+
#
|
196
|
+
# @param [#map] list
|
197
|
+
# The list of elements.
|
198
|
+
#
|
199
|
+
# @return [String]
|
200
|
+
# The raw SQL.
|
201
|
+
#
|
202
|
+
def emit_list(list)
|
203
|
+
'(' + list.map { |element| emit(element) }.join(',') + ')'
|
204
|
+
end
|
205
|
+
|
206
|
+
#
|
207
|
+
# Emits a list of columns and assigned values.
|
208
|
+
#
|
209
|
+
# @param [Hash{Field,Symbol => Object}] values
|
210
|
+
# The column names and values.
|
211
|
+
#
|
212
|
+
# @return [String]
|
213
|
+
# The raw SQL.
|
214
|
+
#
|
215
|
+
def emit_assignments(values)
|
216
|
+
values.map { |key,value|
|
217
|
+
"#{emit_keyword(key)}=#{emit(value)}"
|
218
|
+
}.join(',')
|
219
|
+
end
|
220
|
+
|
221
|
+
#
|
222
|
+
# Emits a value used in an expression.
|
223
|
+
#
|
224
|
+
# @param [Statement, #to_sql] operand
|
225
|
+
# The operand to emit.
|
226
|
+
#
|
227
|
+
# @return [String]
|
228
|
+
# The raw SQL.
|
229
|
+
#
|
230
|
+
# @since 1.1.0
|
231
|
+
#
|
232
|
+
def emit_argument(operand)
|
233
|
+
case operand
|
234
|
+
when Statement then "(#{emit_statement(operand)})"
|
235
|
+
else emit(operand)
|
236
|
+
end
|
237
|
+
end
|
238
|
+
|
239
|
+
#
|
240
|
+
# Emits a SQL expression.
|
241
|
+
#
|
242
|
+
# @param [BinaryExpr, UnaryExpr] expr
|
243
|
+
# The SQL expression.
|
244
|
+
#
|
245
|
+
# @return [String]
|
246
|
+
# The raw SQL.
|
247
|
+
#
|
248
|
+
def emit_expression(expr)
|
249
|
+
op = emit_operator(expr.operator)
|
250
|
+
|
251
|
+
case expr
|
252
|
+
when BinaryExpr
|
253
|
+
left, right = emit_argument(expr.left), emit_argument(expr.right)
|
254
|
+
|
255
|
+
case op
|
256
|
+
when /^\W+$/ then "#{left}#{op}#{right}"
|
257
|
+
else [left, op, right].join(@space)
|
258
|
+
end
|
259
|
+
when UnaryExpr
|
260
|
+
operand = emit_argument(expr.operand)
|
261
|
+
|
262
|
+
case expr.operator
|
263
|
+
when /^\W+$/ then "#{op}#{operand}"
|
264
|
+
else [op, operand].join(@space)
|
265
|
+
end
|
266
|
+
end
|
267
|
+
end
|
268
|
+
|
269
|
+
#
|
270
|
+
# Emits a SQL function.
|
271
|
+
#
|
272
|
+
# @param [Function] function
|
273
|
+
# The SQL function.
|
274
|
+
#
|
275
|
+
# @return [String]
|
276
|
+
# The raw SQL.
|
277
|
+
#
|
278
|
+
def emit_function(function)
|
279
|
+
name = emit_keyword(function.name)
|
280
|
+
arguments = function.arguments.map { |value| emit_argument(value) }
|
281
|
+
|
282
|
+
return "#{name}(#{arguments.join(',')})"
|
283
|
+
end
|
284
|
+
|
285
|
+
#
|
286
|
+
# Emits a SQL object.
|
287
|
+
#
|
288
|
+
# @param [#to_sql] object
|
289
|
+
# The SQL object.
|
290
|
+
#
|
291
|
+
# @return [String]
|
292
|
+
# The raw SQL.
|
293
|
+
#
|
294
|
+
# @raise [ArgumentError]
|
295
|
+
# Could not emit an unknown SQL object.
|
296
|
+
#
|
297
|
+
def emit(object)
|
298
|
+
case object
|
299
|
+
when NilClass then emit_null
|
300
|
+
when TrueClass then emit_true
|
301
|
+
when FalseClass then emit_false
|
302
|
+
when Integer then emit_integer(object)
|
303
|
+
when Float then emit_decimal(object)
|
304
|
+
when String then emit_string(object)
|
305
|
+
when Literal then emit(object.value)
|
306
|
+
when Symbol then emit_keyword(object)
|
307
|
+
when Field then emit_field(object)
|
308
|
+
when Array then emit_list(object)
|
309
|
+
when Hash then emit_assignments(object)
|
310
|
+
when BinaryExpr, UnaryExpr then emit_expression(object)
|
311
|
+
when Function then emit_function(object)
|
312
|
+
when Clause then emit_clause(object)
|
313
|
+
when Statement then emit_statement(object)
|
314
|
+
when StatementList then emit_statement_list(object)
|
315
|
+
else
|
316
|
+
if object.respond_to?(:to_sql)
|
317
|
+
object.to_sql
|
318
|
+
else
|
319
|
+
raise(ArgumentError,"cannot emit #{object.class}")
|
320
|
+
end
|
321
|
+
end
|
322
|
+
end
|
323
|
+
|
324
|
+
#
|
325
|
+
# Emits a SQL Clause.
|
326
|
+
#
|
327
|
+
# @param [Clause] clause
|
328
|
+
# The SQL Clause.
|
329
|
+
#
|
330
|
+
# @return [String]
|
331
|
+
# The raw SQL.
|
332
|
+
#
|
333
|
+
def emit_clause(clause)
|
334
|
+
sql = emit_keyword(clause.keyword)
|
335
|
+
|
336
|
+
unless clause.argument.nil?
|
337
|
+
sql << @space << emit_argument(clause.argument)
|
338
|
+
end
|
339
|
+
|
340
|
+
return sql
|
341
|
+
end
|
342
|
+
|
343
|
+
#
|
344
|
+
# Emits multiple SQL Clauses.
|
345
|
+
#
|
346
|
+
# @param [Array<Clause>] clauses
|
347
|
+
# The clauses to emit.
|
348
|
+
#
|
349
|
+
# @return [String]
|
350
|
+
# The emitted clauses.
|
351
|
+
#
|
352
|
+
def emit_clauses(clauses)
|
353
|
+
clauses.map { |clause| emit_clause(clause) }.join(@space)
|
354
|
+
end
|
355
|
+
|
356
|
+
#
|
357
|
+
# Emits a SQL Statement.
|
358
|
+
#
|
359
|
+
# @param [Statement] stmt
|
360
|
+
# The SQL Statement.
|
361
|
+
#
|
362
|
+
# @return [String]
|
363
|
+
# The raw SQL.
|
364
|
+
#
|
365
|
+
def emit_statement(stmt)
|
366
|
+
sql = emit_keyword(stmt.keyword)
|
367
|
+
|
368
|
+
unless stmt.argument.nil?
|
369
|
+
case stmt.argument
|
370
|
+
when Array
|
371
|
+
sql << @space << if stmt.argument.length == 1
|
372
|
+
emit_argument(stmt.argument[0])
|
373
|
+
else
|
374
|
+
emit_list(stmt.argument)
|
375
|
+
end
|
376
|
+
else
|
377
|
+
sql << @space << emit_argument(stmt.argument)
|
378
|
+
end
|
379
|
+
end
|
380
|
+
|
381
|
+
unless stmt.clauses.empty?
|
382
|
+
sql << @space << emit_clauses(stmt.clauses)
|
383
|
+
end
|
384
|
+
|
385
|
+
return sql
|
386
|
+
end
|
387
|
+
|
388
|
+
#
|
389
|
+
# Emits a full SQL statement list.
|
390
|
+
#
|
391
|
+
# @param [StatementList] list
|
392
|
+
# The SQL statement list.
|
393
|
+
#
|
394
|
+
# @return [String]
|
395
|
+
# The raw SQL.
|
396
|
+
#
|
397
|
+
def emit_statement_list(list)
|
398
|
+
list.statements.map { |stmt|
|
399
|
+
emit_statement(stmt)
|
400
|
+
}.join(";#{@space}")
|
401
|
+
end
|
402
|
+
|
403
|
+
end
|
404
|
+
end
|
405
|
+
end
|
406
|
+
end
|
@@ -0,0 +1,110 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
#
|
3
|
+
# ronin-code-sql - A Ruby DSL for crafting SQL Injections.
|
4
|
+
#
|
5
|
+
# Copyright (c) 2007-2022 Hal Brodigan (postmodern.mod3 at gmail.com)
|
6
|
+
#
|
7
|
+
# ronin-code-sql 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-code-sql 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-code-sql. If not, see <https://www.gnu.org/licenses/>.
|
19
|
+
#
|
20
|
+
|
21
|
+
require 'ronin/code/sql/operators'
|
22
|
+
require 'ronin/code/sql/emittable'
|
23
|
+
|
24
|
+
module Ronin
|
25
|
+
module Code
|
26
|
+
module SQL
|
27
|
+
#
|
28
|
+
# Represents a SQL column, table or database name.
|
29
|
+
#
|
30
|
+
# @api semipublic
|
31
|
+
#
|
32
|
+
class Field < Struct.new(:name,:parent)
|
33
|
+
|
34
|
+
include Operators
|
35
|
+
include Emittable
|
36
|
+
|
37
|
+
#
|
38
|
+
# Initializes the new field.
|
39
|
+
#
|
40
|
+
# @param [String] name
|
41
|
+
# The name of the field.
|
42
|
+
#
|
43
|
+
# @param [Field] parent
|
44
|
+
# The parent of the field.
|
45
|
+
#
|
46
|
+
def initialize(name,parent=nil)
|
47
|
+
super(name.to_s,parent)
|
48
|
+
end
|
49
|
+
|
50
|
+
#
|
51
|
+
# Parses a field.
|
52
|
+
#
|
53
|
+
# @param [String] name
|
54
|
+
#
|
55
|
+
# @return [Field]
|
56
|
+
# The parsed field.
|
57
|
+
#
|
58
|
+
def self.parse(name)
|
59
|
+
names = name.to_s.split('.',3)
|
60
|
+
field = nil
|
61
|
+
|
62
|
+
names.each { |name| field = new(name,field) }
|
63
|
+
|
64
|
+
return field
|
65
|
+
end
|
66
|
+
|
67
|
+
alias to_str to_s
|
68
|
+
|
69
|
+
protected
|
70
|
+
|
71
|
+
#
|
72
|
+
# Allows accessing columns from tables or tables from databases.
|
73
|
+
#
|
74
|
+
# @param [Symbol] name
|
75
|
+
# The sub-field name.
|
76
|
+
#
|
77
|
+
# @param [Array] arguments
|
78
|
+
# Additional mehtod arguments.
|
79
|
+
#
|
80
|
+
# @return [Field]
|
81
|
+
# The sub-field for the given name.
|
82
|
+
#
|
83
|
+
# @raise [ArgumentError]
|
84
|
+
# The method missing call was given additional arguments.
|
85
|
+
#
|
86
|
+
# @raise [NoMethodError]
|
87
|
+
# Cannot access a column from another column.
|
88
|
+
#
|
89
|
+
# @example
|
90
|
+
# db.users
|
91
|
+
#
|
92
|
+
# @example
|
93
|
+
# users.id
|
94
|
+
#
|
95
|
+
def method_missing(name,*arguments)
|
96
|
+
unless arguments.empty?
|
97
|
+
raise(ArgumentError,"canot access columns or tables with arguments")
|
98
|
+
end
|
99
|
+
|
100
|
+
if (self.parent.nil? || self.parent.parent.nil?)
|
101
|
+
Field.new(name,self)
|
102
|
+
else
|
103
|
+
raise(NoMethodError,"cannot access columns from other columns")
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
107
|
+
end
|
108
|
+
end
|
109
|
+
end
|
110
|
+
end
|
@@ -0,0 +1,82 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
#
|
3
|
+
# ronin-code-sql - A Ruby DSL for crafting SQL Injections.
|
4
|
+
#
|
5
|
+
# Copyright (c) 2007-2022 Hal Brodigan (postmodern.mod3 at gmail.com)
|
6
|
+
#
|
7
|
+
# ronin-code-sql 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-code-sql 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-code-sql. If not, see <https://www.gnu.org/licenses/>.
|
19
|
+
#
|
20
|
+
|
21
|
+
require 'ronin/code/sql/field'
|
22
|
+
|
23
|
+
module Ronin
|
24
|
+
module Code
|
25
|
+
module SQL
|
26
|
+
#
|
27
|
+
# Allows creating {Field Fields} via {#method_missing}.
|
28
|
+
#
|
29
|
+
# @api public
|
30
|
+
#
|
31
|
+
module Fields
|
32
|
+
#
|
33
|
+
# Specifies that {#method_missing} will catch all missing methods.
|
34
|
+
#
|
35
|
+
# @param [Symbol] name
|
36
|
+
# The method name that is being checked.
|
37
|
+
#
|
38
|
+
# @param [Boolean] include_private
|
39
|
+
#
|
40
|
+
# @return [true]
|
41
|
+
#
|
42
|
+
def respond_to_missing?(name,include_private)
|
43
|
+
true
|
44
|
+
end
|
45
|
+
|
46
|
+
#
|
47
|
+
# @return [nil]
|
48
|
+
#
|
49
|
+
def to_ary
|
50
|
+
end
|
51
|
+
|
52
|
+
protected
|
53
|
+
|
54
|
+
#
|
55
|
+
# Allows specifying databases, tables or columns.
|
56
|
+
#
|
57
|
+
# @param [Symbol] name
|
58
|
+
# The field name to access.
|
59
|
+
#
|
60
|
+
# @param [Array] arguments
|
61
|
+
# Additional method arguments.
|
62
|
+
#
|
63
|
+
# @return [Field]
|
64
|
+
# The field object.
|
65
|
+
#
|
66
|
+
# @example
|
67
|
+
# db.users
|
68
|
+
#
|
69
|
+
# @example
|
70
|
+
# users.id
|
71
|
+
#
|
72
|
+
def method_missing(name,*arguments,&block)
|
73
|
+
if (arguments.empty? && block.nil?)
|
74
|
+
Field.new(name)
|
75
|
+
else
|
76
|
+
super
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
@@ -0,0 +1,53 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
#
|
3
|
+
# ronin-code-sql - A Ruby DSL for crafting SQL Injections.
|
4
|
+
#
|
5
|
+
# Copyright (c) 2007-2022 Hal Brodigan (postmodern.mod3 at gmail.com)
|
6
|
+
#
|
7
|
+
# ronin-code-sql 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-code-sql 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-code-sql. If not, see <https://www.gnu.org/licenses/>.
|
19
|
+
#
|
20
|
+
|
21
|
+
require 'ronin/code/sql/operators'
|
22
|
+
require 'ronin/code/sql/emittable'
|
23
|
+
|
24
|
+
module Ronin
|
25
|
+
module Code
|
26
|
+
module SQL
|
27
|
+
#
|
28
|
+
# Represents a SQL function call.
|
29
|
+
#
|
30
|
+
# @api semipublic
|
31
|
+
#
|
32
|
+
class Function < Struct.new(:name,:arguments)
|
33
|
+
|
34
|
+
include Operators
|
35
|
+
include Emittable
|
36
|
+
|
37
|
+
#
|
38
|
+
# Creates a new Function object.
|
39
|
+
#
|
40
|
+
# @param [Symbol] name
|
41
|
+
# The name of the function.
|
42
|
+
#
|
43
|
+
# @param [Array] arguments
|
44
|
+
# The arguments of the function.
|
45
|
+
#
|
46
|
+
def initialize(name,*arguments)
|
47
|
+
super(name,arguments)
|
48
|
+
end
|
49
|
+
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|