ronin-core 0.1.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.
Files changed (109) hide show
  1. checksums.yaml +7 -0
  2. data/.document +5 -0
  3. data/.github/workflows/ruby.yml +41 -0
  4. data/.gitignore +12 -0
  5. data/.rspec +1 -0
  6. data/.rubocop.yml +160 -0
  7. data/.ruby-version +1 -0
  8. data/.yardopts +1 -0
  9. data/COPYING.txt +165 -0
  10. data/ChangeLog.md +11 -0
  11. data/Gemfile +30 -0
  12. data/README.md +299 -0
  13. data/Rakefile +34 -0
  14. data/examples/ruby_shell.rb +11 -0
  15. data/gemspec.yml +28 -0
  16. data/lib/ronin/core/class_registry.rb +246 -0
  17. data/lib/ronin/core/cli/command.rb +87 -0
  18. data/lib/ronin/core/cli/command_shell/command.rb +110 -0
  19. data/lib/ronin/core/cli/command_shell.rb +345 -0
  20. data/lib/ronin/core/cli/generator/options/author.rb +106 -0
  21. data/lib/ronin/core/cli/generator/options/description.rb +54 -0
  22. data/lib/ronin/core/cli/generator/options/reference.rb +60 -0
  23. data/lib/ronin/core/cli/generator/options/summary.rb +54 -0
  24. data/lib/ronin/core/cli/generator.rb +238 -0
  25. data/lib/ronin/core/cli/logging.rb +59 -0
  26. data/lib/ronin/core/cli/options/param.rb +68 -0
  27. data/lib/ronin/core/cli/options/values/arches.rb +45 -0
  28. data/lib/ronin/core/cli/options/values/oses.rb +32 -0
  29. data/lib/ronin/core/cli/printing/arch.rb +71 -0
  30. data/lib/ronin/core/cli/printing/metadata.rb +113 -0
  31. data/lib/ronin/core/cli/printing/os.rb +54 -0
  32. data/lib/ronin/core/cli/printing/params.rb +69 -0
  33. data/lib/ronin/core/cli/ruby_shell.rb +131 -0
  34. data/lib/ronin/core/cli/shell.rb +186 -0
  35. data/lib/ronin/core/git.rb +73 -0
  36. data/lib/ronin/core/home.rb +86 -0
  37. data/lib/ronin/core/metadata/authors/author.rb +241 -0
  38. data/lib/ronin/core/metadata/authors.rb +120 -0
  39. data/lib/ronin/core/metadata/description.rb +100 -0
  40. data/lib/ronin/core/metadata/id.rb +88 -0
  41. data/lib/ronin/core/metadata/references.rb +87 -0
  42. data/lib/ronin/core/metadata/summary.rb +78 -0
  43. data/lib/ronin/core/metadata/version.rb +74 -0
  44. data/lib/ronin/core/params/exceptions.rb +38 -0
  45. data/lib/ronin/core/params/mixin.rb +317 -0
  46. data/lib/ronin/core/params/param.rb +137 -0
  47. data/lib/ronin/core/params/types/boolean.rb +64 -0
  48. data/lib/ronin/core/params/types/enum.rb +107 -0
  49. data/lib/ronin/core/params/types/float.rb +68 -0
  50. data/lib/ronin/core/params/types/integer.rb +100 -0
  51. data/lib/ronin/core/params/types/numeric.rb +106 -0
  52. data/lib/ronin/core/params/types/regexp.rb +67 -0
  53. data/lib/ronin/core/params/types/string.rb +118 -0
  54. data/lib/ronin/core/params/types/type.rb +54 -0
  55. data/lib/ronin/core/params/types/uri.rb +72 -0
  56. data/lib/ronin/core/params/types.rb +62 -0
  57. data/lib/ronin/core/params.rb +19 -0
  58. data/lib/ronin/core/version.rb +24 -0
  59. data/ronin-core.gemspec +59 -0
  60. data/spec/class_registry_spec.rb +224 -0
  61. data/spec/cli/command_shell/command_spec.rb +113 -0
  62. data/spec/cli/command_shell_spec.rb +1114 -0
  63. data/spec/cli/command_spec.rb +16 -0
  64. data/spec/cli/fixtures/irb_command +8 -0
  65. data/spec/cli/fixtures/template/dir/file1.txt +1 -0
  66. data/spec/cli/fixtures/template/dir/file2.txt +1 -0
  67. data/spec/cli/fixtures/template/file.erb +1 -0
  68. data/spec/cli/fixtures/template/file.txt +1 -0
  69. data/spec/cli/generator/options/author_spec.rb +121 -0
  70. data/spec/cli/generator/options/description_spec.rb +45 -0
  71. data/spec/cli/generator/options/reference_spec.rb +53 -0
  72. data/spec/cli/generator/options/summary_spec.rb +45 -0
  73. data/spec/cli/generator_spec.rb +244 -0
  74. data/spec/cli/logging_spec.rb +95 -0
  75. data/spec/cli/options/param_spec.rb +67 -0
  76. data/spec/cli/options/values/arches_spec.rb +62 -0
  77. data/spec/cli/printing/arch_spec.rb +130 -0
  78. data/spec/cli/printing/metadata_spec.rb +211 -0
  79. data/spec/cli/printing/os_spec.rb +64 -0
  80. data/spec/cli/printing/params_spec.rb +63 -0
  81. data/spec/cli/ruby_shell.rb +99 -0
  82. data/spec/cli/shell_spec.rb +211 -0
  83. data/spec/fixtures/example_class_registry/base_class.rb +9 -0
  84. data/spec/fixtures/example_class_registry/classes/loaded_class.rb +9 -0
  85. data/spec/fixtures/example_class_registry/classes/name_mismatch.rb +9 -0
  86. data/spec/fixtures/example_class_registry/classes/no_module.rb +4 -0
  87. data/spec/fixtures/example_class_registry.rb +8 -0
  88. data/spec/git_spec.rb +58 -0
  89. data/spec/home_spec.rb +64 -0
  90. data/spec/metadata/authors/author_spec.rb +335 -0
  91. data/spec/metadata/authors_spec.rb +126 -0
  92. data/spec/metadata/description_spec.rb +74 -0
  93. data/spec/metadata/id_spec.rb +92 -0
  94. data/spec/metadata/references_spec.rb +100 -0
  95. data/spec/metadata/summary_spec.rb +74 -0
  96. data/spec/metadata/version_spec.rb +72 -0
  97. data/spec/params/mixin_spec.rb +484 -0
  98. data/spec/params/param_spec.rb +164 -0
  99. data/spec/params/types/boolean_spec.rb +56 -0
  100. data/spec/params/types/enum_spec.rb +94 -0
  101. data/spec/params/types/float_spec.rb +107 -0
  102. data/spec/params/types/integer_spec.rb +155 -0
  103. data/spec/params/types/numeric_spec.rb +138 -0
  104. data/spec/params/types/regexp_spec.rb +64 -0
  105. data/spec/params/types/string_spec.rb +174 -0
  106. data/spec/params/types/type_spec.rb +14 -0
  107. data/spec/params/types/uri_spec.rb +62 -0
  108. data/spec/spec_helper.rb +11 -0
  109. metadata +252 -0
@@ -0,0 +1,107 @@
1
+ # frozen_string_literal: true
2
+ #
3
+ # Copyright (c) 2021-2022 Hal Brodigan (postmodern.mod3 at gmail.com)
4
+ #
5
+ # ronin-core is free software: you can redistribute it and/or modify
6
+ # it under the terms of the GNU Lesser General Public License as published
7
+ # by the Free Software Foundation, either version 3 of the License, or
8
+ # (at your option) any later version.
9
+ #
10
+ # ronin-core is distributed in the hope that it will be useful,
11
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
12
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
+ # GNU Lesser General Public License for more details.
14
+ #
15
+ # You should have received a copy of the GNU Lesser General Public License
16
+ # along with ronin-core. If not, see <https://www.gnu.org/licenses/>.
17
+ #
18
+
19
+ require 'ronin/core/params/types/type'
20
+
21
+ module Ronin
22
+ module Core
23
+ module Params
24
+ module Types
25
+ #
26
+ # Represents a mapping of Ruby values to their String equivalents.
27
+ #
28
+ class Enum < Type
29
+
30
+ # The values of the enum.
31
+ #
32
+ # @return [Array<Object>]
33
+ #
34
+ # @api semipublic
35
+ attr_reader :values
36
+
37
+ #
38
+ # Initializes the enum type.
39
+ #
40
+ # @param [Array<Object>] values
41
+ # The values of the enum type.
42
+ #
43
+ # @raise [ArgumentError]
44
+ # Cannot initialize an enum type with an empty Array of values.
45
+ #
46
+ # @api semipublic
47
+ #
48
+ def initialize(values)
49
+ if values.empty?
50
+ raise(ArgumentError,"cannot initialize an empty Enum")
51
+ end
52
+
53
+ @values = values
54
+ @map = Hash[values.map { |value| [value.to_s, value] }]
55
+ end
56
+
57
+ #
58
+ # Creates a new enum.
59
+ #
60
+ # @param [Array<Object>] values
61
+ # List of enum values.
62
+ #
63
+ # @return [Enum]
64
+ # The newly created enum object.
65
+ #
66
+ # @api public
67
+ #
68
+ def self.[](*values)
69
+ new(values)
70
+ end
71
+
72
+ #
73
+ # Coerces the value into one of the enum values.
74
+ #
75
+ # @param [::String, ::Symbol, Object] value
76
+ #
77
+ # @return [Symbol]
78
+ # The coerced value.
79
+ #
80
+ # @raise [ValidationError]
81
+ # The value was not a valid enum value or a String that maps to an
82
+ # enum value.
83
+ #
84
+ # @api private
85
+ #
86
+ def coerce(value)
87
+ case value
88
+ when ::Symbol
89
+ unless @values.include?(value)
90
+ raise(ValidationError,"unknown value (#{value.inspect})")
91
+ end
92
+
93
+ value
94
+ when ::String
95
+ @map.fetch(value) do
96
+ raise(ValidationError,"unknown value (#{value.inspect})")
97
+ end
98
+ else
99
+ raise(ValidationError,"value must be either a Symbol or a String (#{value.inspect})")
100
+ end
101
+ end
102
+
103
+ end
104
+ end
105
+ end
106
+ end
107
+ end
@@ -0,0 +1,68 @@
1
+ # frozen_string_literal: true
2
+ #
3
+ # Copyright (c) 2021-2022 Hal Brodigan (postmodern.mod3 at gmail.com)
4
+ #
5
+ # ronin-core is free software: you can redistribute it and/or modify
6
+ # it under the terms of the GNU Lesser General Public License as published
7
+ # by the Free Software Foundation, either version 3 of the License, or
8
+ # (at your option) any later version.
9
+ #
10
+ # ronin-core is distributed in the hope that it will be useful,
11
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
12
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
+ # GNU Lesser General Public License for more details.
14
+ #
15
+ # You should have received a copy of the GNU Lesser General Public License
16
+ # along with ronin-core. If not, see <https://www.gnu.org/licenses/>.
17
+ #
18
+
19
+ require 'ronin/core/params/types/numeric'
20
+
21
+ module Ronin
22
+ module Core
23
+ module Params
24
+ module Types
25
+ #
26
+ # Represents a true/false param.
27
+ #
28
+ class Float < Numeric
29
+
30
+ #
31
+ # Coerces a value into a Float value.
32
+ #
33
+ # @param [::Float, ::String, #to_f, Object] value
34
+ # The value to coerce.
35
+ #
36
+ # @return [::Float]
37
+ # The coerced Float value.
38
+ #
39
+ # @raise [ValidationError]
40
+ # The value was not a Float, a String, or was not within {#range},
41
+ # or below {#min}, or above {#max}.
42
+ #
43
+ # @api private
44
+ #
45
+ def coerce(value)
46
+ case value
47
+ when ::Float
48
+ super(value)
49
+ when ::String
50
+ if value =~ /\A[+-]?\d+(?:\.\d+)?\z/
51
+ super(value.to_f)
52
+ else
53
+ raise(ValidationError,"value contains non-numeric characters (#{value.inspect})")
54
+ end
55
+ else
56
+ if value.respond_to?(:to_f)
57
+ super(value.to_f)
58
+ else
59
+ raise(ValidationError,"value does not define a #to_f method (#{value.inspect})")
60
+ end
61
+ end
62
+ end
63
+
64
+ end
65
+ end
66
+ end
67
+ end
68
+ end
@@ -0,0 +1,100 @@
1
+ # frozen_string_literal: true
2
+ #
3
+ # Copyright (c) 2021-2022 Hal Brodigan (postmodern.mod3 at gmail.com)
4
+ #
5
+ # ronin-core is free software: you can redistribute it and/or modify
6
+ # it under the terms of the GNU Lesser General Public License as published
7
+ # by the Free Software Foundation, either version 3 of the License, or
8
+ # (at your option) any later version.
9
+ #
10
+ # ronin-core is distributed in the hope that it will be useful,
11
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
12
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
+ # GNU Lesser General Public License for more details.
14
+ #
15
+ # You should have received a copy of the GNU Lesser General Public License
16
+ # along with ronin-core. If not, see <https://www.gnu.org/licenses/>.
17
+ #
18
+
19
+ require 'ronin/core/params/types/numeric'
20
+
21
+ module Ronin
22
+ module Core
23
+ module Params
24
+ module Types
25
+ #
26
+ # Represents a numeric value.
27
+ #
28
+ class Integer < Numeric
29
+
30
+ #
31
+ # Coerces a String into an Integer value.
32
+ #
33
+ # @param [::Integer, ::String, #to_i, Object] value
34
+ # The given value to coerce.
35
+ #
36
+ # @return [::Integer]
37
+ # The coerced Integer value.
38
+ #
39
+ # @raise [ValidationError]
40
+ # The value was not an Integer, a String, or was not within
41
+ # {#range}, or below {#min}, or above {#max}.
42
+ #
43
+ # @api private
44
+ #
45
+ def coerce(value)
46
+ case value
47
+ when ::Integer then super(value)
48
+ when ::String
49
+ case value
50
+ when /\A[+-]?\d+\z/
51
+ super(value.to_i)
52
+ when /\A[+-]?0b[01]+\z/
53
+ super(parse_binary(value))
54
+ when /\A[+-]?(?:0x)?[0-9A-Fa-f]+\z/
55
+ super(parse_hexadecimal(value))
56
+ else
57
+ raise(ValidationError,"value contains non-numeric characters (#{value.inspect})")
58
+ end
59
+ else
60
+ if value.respond_to?(:to_i)
61
+ super(value.to_i)
62
+ else
63
+ raise(ValidationError,"value does not define a #to_i method (#{value.inspect})")
64
+ end
65
+ end
66
+ end
67
+
68
+ private
69
+
70
+ #
71
+ # Parses a binary string.
72
+ #
73
+ # @param [::String] string
74
+ #
75
+ # @return [::Integer]
76
+ #
77
+ def parse_binary(string)
78
+ integer = string.sub(/\A[+-]?0b/,'').to_i(2)
79
+ integer = -integer if string.start_with?('-')
80
+ integer
81
+ end
82
+
83
+ #
84
+ # Parses a hexadecimal string.
85
+ #
86
+ # @param [::String] string
87
+ #
88
+ # @return [::Integer]
89
+ #
90
+ def parse_hexadecimal(string)
91
+ integer = string.sub(/\A[+-]?(?:0x)?/,'').to_i(16)
92
+ integer = -integer if string.start_with?('-')
93
+ integer
94
+ end
95
+
96
+ end
97
+ end
98
+ end
99
+ end
100
+ end
@@ -0,0 +1,106 @@
1
+ # frozen_string_literal: true
2
+ #
3
+ # Copyright (c) 2021-2022 Hal Brodigan (postmodern.mod3 at gmail.com)
4
+ #
5
+ # ronin-core is free software: you can redistribute it and/or modify
6
+ # it under the terms of the GNU Lesser General Public License as published
7
+ # by the Free Software Foundation, either version 3 of the License, or
8
+ # (at your option) any later version.
9
+ #
10
+ # ronin-core is distributed in the hope that it will be useful,
11
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
12
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
+ # GNU Lesser General Public License for more details.
14
+ #
15
+ # You should have received a copy of the GNU Lesser General Public License
16
+ # along with ronin-core. If not, see <https://www.gnu.org/licenses/>.
17
+ #
18
+
19
+ require 'ronin/core/params/types/type'
20
+
21
+ module Ronin
22
+ module Core
23
+ module Params
24
+ module Types
25
+ #
26
+ # Represents a true/false param.
27
+ #
28
+ class Numeric < Type
29
+
30
+ # The optional minimum value.
31
+ #
32
+ # @return [::Integer, nil]
33
+ #
34
+ # @api private
35
+ attr_reader :min
36
+
37
+ # The optional maximum value.
38
+ #
39
+ # @return [::Integer, nil]
40
+ #
41
+ # @api private
42
+ attr_reader :max
43
+
44
+ # The optional range of acceptable numbers.
45
+ #
46
+ # @return [Range, nil]
47
+ #
48
+ # @api private
49
+ attr_reader :range
50
+
51
+ #
52
+ # Initializes the numeric value.
53
+ #
54
+ # @param [::Integer, nil] min
55
+ # Optional minimum value for the integer param.
56
+ #
57
+ # @param [::Integer, nil] max
58
+ # Optional maximum value for the integer param.
59
+ #
60
+ # @param [Range] range
61
+ # Optional range of acceptable integers.
62
+ #
63
+ def initialize(min: nil, max: nil, range: nil)
64
+ @min = min
65
+ @max = max
66
+ @range = range
67
+ end
68
+
69
+ #
70
+ # Validates a numeric value.
71
+ #
72
+ # @param [::Integer, ::Float] value
73
+ # The value to validate.
74
+ #
75
+ # @return [::Integer, ::Float]
76
+ # The validated value.
77
+ #
78
+ # @raise [ValidationError]
79
+ # The value was not within {#range}, or below {#min}, or above
80
+ # {#max}.
81
+ #
82
+ # @abstract
83
+ #
84
+ def coerce(value)
85
+ if @range
86
+ unless @range.include?(value)
87
+ raise(ValidationError,"value is not within the range of acceptable values #{@range.begin}-#{@range.end} (#{value.inspect})")
88
+ end
89
+ else
90
+ if @min && (value < @min)
91
+ raise(ValidationError,"value is below minimum value of #{@min} (#{value.inspect})")
92
+ end
93
+
94
+ if @max && (value > @max)
95
+ raise(ValidationError,"value is above maximum value of #{@max} (#{value.inspect})")
96
+ end
97
+ end
98
+
99
+ return value
100
+ end
101
+
102
+ end
103
+ end
104
+ end
105
+ end
106
+ end
@@ -0,0 +1,67 @@
1
+ # frozen_string_literal: true
2
+ #
3
+ # Copyright (c) 2021-2022 Hal Brodigan (postmodern.mod3 at gmail.com)
4
+ #
5
+ # ronin-core is free software: you can redistribute it and/or modify
6
+ # it under the terms of the GNU Lesser General Public License as published
7
+ # by the Free Software Foundation, either version 3 of the License, or
8
+ # (at your option) any later version.
9
+ #
10
+ # ronin-core is distributed in the hope that it will be useful,
11
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
12
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
+ # GNU Lesser General Public License for more details.
14
+ #
15
+ # You should have received a copy of the GNU Lesser General Public License
16
+ # along with ronin-core. If not, see <https://www.gnu.org/licenses/>.
17
+ #
18
+
19
+ require 'ronin/core/params/types/type'
20
+
21
+ module Ronin
22
+ module Core
23
+ module Params
24
+ module Types
25
+ #
26
+ # Represents a Regexp type.
27
+ #
28
+ class Regexp < Type
29
+
30
+ #
31
+ # Parses the String value.
32
+ #
33
+ # @param [::String, ::Regexp, Object] value
34
+ # The String value to coerce.
35
+ #
36
+ # @return [Regexp]
37
+ # The coerced Regexp value.
38
+ #
39
+ # @raise [ValidationError]
40
+ # The value was not a Regexp, a String, or a String that could not
41
+ # be parsed by `Regexp.new`.
42
+ #
43
+ # @api private
44
+ #
45
+ def coerce(value)
46
+ case value
47
+ when ::Regexp then value
48
+ when ::String
49
+ unless (value.start_with?('/') && value.end_with?('/'))
50
+ raise(ValidationError,"value must be of the format '/.../' (#{value.inspect})")
51
+ end
52
+
53
+ begin
54
+ ::Regexp.new(value[1..-2])
55
+ rescue RegexpError
56
+ raise(ValidationError,"value is not a valid Regexp (#{value.inspect})")
57
+ end
58
+ else
59
+ raise(ValidationError,"value must be either a String or a Regexp (#{value.inspect})")
60
+ end
61
+ end
62
+
63
+ end
64
+ end
65
+ end
66
+ end
67
+ end
@@ -0,0 +1,118 @@
1
+ # frozen_string_literal: true
2
+ #
3
+ # Copyright (c) 2021-2022 Hal Brodigan (postmodern.mod3 at gmail.com)
4
+ #
5
+ # ronin-core is free software: you can redistribute it and/or modify
6
+ # it under the terms of the GNU Lesser General Public License as published
7
+ # by the Free Software Foundation, either version 3 of the License, or
8
+ # (at your option) any later version.
9
+ #
10
+ # ronin-core is distributed in the hope that it will be useful,
11
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
12
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
+ # GNU Lesser General Public License for more details.
14
+ #
15
+ # You should have received a copy of the GNU Lesser General Public License
16
+ # along with ronin-core. If not, see <https://www.gnu.org/licenses/>.
17
+ #
18
+
19
+ require 'ronin/core/params/types/type'
20
+
21
+ module Ronin
22
+ module Core
23
+ module Params
24
+ module Types
25
+ #
26
+ # Represents a string type.
27
+ #
28
+ class String < Type
29
+
30
+ # Optional regexp to validate values with.
31
+ #
32
+ # @return [::Regexp, nil]
33
+ attr_reader :format
34
+
35
+ #
36
+ # Initializes the value.
37
+ #
38
+ # @param [::Boolean] allow_empty
39
+ # Specifies whether the argument may accept empty values.
40
+ #
41
+ # @param [::Boolean] allow_blank
42
+ # Specifies whether the argument may accept blank values.
43
+ #
44
+ # @param [(::Regexp, ::String), nil] format
45
+ # Optional regular expression to validate the given param value.
46
+ #
47
+ def initialize(allow_empty: false, allow_blank: false, format: nil)
48
+ @allow_empty = allow_empty
49
+ @allow_blank = allow_blank
50
+
51
+ @format = format
52
+ end
53
+
54
+ #
55
+ # Specifies whether the param may accept empty values.
56
+ #
57
+ # @return [::Boolean]
58
+ #
59
+ # @api private
60
+ #
61
+ def allow_empty?
62
+ @allow_empty
63
+ end
64
+
65
+ #
66
+ # Specifies whether the param may accept blank values.
67
+ #
68
+ # @return [::Boolean]
69
+ #
70
+ # @api private
71
+ #
72
+ def allow_blank?
73
+ @allow_blank
74
+ end
75
+
76
+ #
77
+ # Validates the given value.
78
+ #
79
+ # @param [Object] value
80
+ # The given value to validate.
81
+ #
82
+ # @return [::String]
83
+ # The coerced String.
84
+ #
85
+ # @raise [ValidationError]
86
+ # The given value was not a String and did not define a `#to_s`
87
+ # method, or was a String that did not match {#format}.
88
+ #
89
+ # @api private
90
+ #
91
+ def coerce(value)
92
+ case value
93
+ when Enumerable
94
+ raise(ValidationError,"cannot convert an Enumerable into a String (#{value.inspect})")
95
+ else
96
+ unless value.respond_to?(:to_s)
97
+ raise(ValidationError,"value does not define a #to_s method (#{value.inspect})")
98
+ end
99
+
100
+ string = value.to_s
101
+
102
+ if @format && string !~ @format
103
+ raise(ValidationError,"does not match the format (#{string.inspect})")
104
+ elsif (string.empty? && !allow_empty?)
105
+ raise(ValidationError,"value cannot be empty")
106
+ elsif (string =~ /\A\s+\z/ && !allow_blank?)
107
+ raise(ValidationError,"value cannot contain all whitespace (#{string.inspect})")
108
+ end
109
+
110
+ return string
111
+ end
112
+ end
113
+
114
+ end
115
+ end
116
+ end
117
+ end
118
+ end
@@ -0,0 +1,54 @@
1
+ # frozen_string_literal: true
2
+ #
3
+ # Copyright (c) 2021-2022 Hal Brodigan (postmodern.mod3 at gmail.com)
4
+ #
5
+ # ronin-core is free software: you can redistribute it and/or modify
6
+ # it under the terms of the GNU Lesser General Public License as published
7
+ # by the Free Software Foundation, either version 3 of the License, or
8
+ # (at your option) any later version.
9
+ #
10
+ # ronin-core is distributed in the hope that it will be useful,
11
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
12
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
+ # GNU Lesser General Public License for more details.
14
+ #
15
+ # You should have received a copy of the GNU Lesser General Public License
16
+ # along with ronin-core. If not, see <https://www.gnu.org/licenses/>.
17
+ #
18
+
19
+ require 'ronin/core/params/exceptions'
20
+
21
+ module Ronin
22
+ module Core
23
+ module Params
24
+ module Types
25
+ #
26
+ # The base type for all command-line argument types.
27
+ #
28
+ # @api private
29
+ #
30
+ class Type
31
+
32
+ #
33
+ # The default coerce method.
34
+ #
35
+ # @param [Object] value
36
+ # The value to coerce.
37
+ #
38
+ # @return [Object]
39
+ # The coerced value.
40
+ #
41
+ # @raise [ValidationError]
42
+ # The given value was invalid.
43
+ #
44
+ # @abstract
45
+ #
46
+ def coerce(value)
47
+ raise(NotImplementedError,"#{self.class}##{__method__} method was not implemented")
48
+ end
49
+
50
+ end
51
+ end
52
+ end
53
+ end
54
+ end
@@ -0,0 +1,72 @@
1
+ # frozen_string_literal: true
2
+ #
3
+ # Copyright (c) 2021-2022 Hal Brodigan (postmodern.mod3 at gmail.com)
4
+ #
5
+ # ronin-core is free software: you can redistribute it and/or modify
6
+ # it under the terms of the GNU Lesser General Public License as published
7
+ # by the Free Software Foundation, either version 3 of the License, or
8
+ # (at your option) any later version.
9
+ #
10
+ # ronin-core is distributed in the hope that it will be useful,
11
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
12
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
+ # GNU Lesser General Public License for more details.
14
+ #
15
+ # You should have received a copy of the GNU Lesser General Public License
16
+ # along with ronin-core. If not, see <https://www.gnu.org/licenses/>.
17
+ #
18
+
19
+ require 'ronin/core/params/types/type'
20
+
21
+ require 'uri'
22
+
23
+ module Ronin
24
+ module Core
25
+ module Params
26
+ module Types
27
+ #
28
+ # Represents a URL type.
29
+ #
30
+ class URI < Type
31
+
32
+ #
33
+ # Parses the String value.
34
+ #
35
+ # @param [::String, ::URI, Object] value
36
+ # The String value to coerce.
37
+ #
38
+ # @return [::URI]
39
+ # The coerced URI value.
40
+ #
41
+ # @raise [ValidationError]
42
+ # The given value was invalid.
43
+ #
44
+ # @api private
45
+ #
46
+ def coerce(value)
47
+ case value
48
+ when ::URI then value
49
+ when ::String
50
+ if value.empty?
51
+ raise(ValidationError,"value must not be empty")
52
+ end
53
+
54
+ unless value =~ /\A[a-z]+:/
55
+ raise(ValidationError,"value must start with a 'scheme:' (#{value.inspect})")
56
+ end
57
+
58
+ begin
59
+ ::URI.parse(value)
60
+ rescue ::URI::InvalidURIError
61
+ raise(ValidationError,"value is not a valid URI (#{value.inspect})")
62
+ end
63
+ else
64
+ raise(ValidationError,"value must be either a String or a URI (#{value.inspect})")
65
+ end
66
+ end
67
+
68
+ end
69
+ end
70
+ end
71
+ end
72
+ end