sastbox_sdk 1.0.0
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/README.md +0 -0
- data/lib/sastbox-sdk.rb +26 -0
- data/lib/sastbox-sdk/codebase.rb +9 -0
- data/lib/sastbox-sdk/cwe_constants.rb +87 -0
- data/lib/sastbox-sdk/cwe_detector.rb +202 -0
- data/lib/sastbox-sdk/opt_parser.rb +45 -0
- data/lib/sastbox-sdk/printer.rb +86 -0
- data/lib/sastbox-sdk/reporter_sarif.rb +112 -0
- data/lib/sastbox-sdk/runner.rb +55 -0
- data/lib/sastbox-sdk/scanner.rb +152 -0
- data/lib/sastbox-sdk/severity_calculator.rb +82 -0
- data/lib/sastbox-sdk/snippet.rb +107 -0
- data/spec/samples/low.php +21 -0
- data/spec/samples/sarif-2.1.0-rtm.5.json +3370 -0
- data/spec/sastbox-sdk/codebase_spec.rb +7 -0
- data/spec/sastbox-sdk/cwe_constants_spec.rb +7 -0
- data/spec/sastbox-sdk/cwe_detector_spec.rb +216 -0
- data/spec/sastbox-sdk/opt_parser_spec.rb +47 -0
- data/spec/sastbox-sdk/printer_spec.rb +59 -0
- data/spec/sastbox-sdk/reporter_sarif_spec.rb +57 -0
- data/spec/sastbox-sdk/runner_spec.rb +92 -0
- data/spec/sastbox-sdk/scanner_spec.rb +238 -0
- data/spec/sastbox-sdk/severity_calculator_spec.rb +126 -0
- data/spec/sastbox-sdk/snippet_spec.rb +175 -0
- data/spec/sastbox-sdk_spec.rb +8 -0
- data/spec/spec_helper.rb +109 -0
- metadata +96 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 9b33ef5c1d3c97a2991c9dcb76b13a3c414df8f545ff3f085b3ebed0f9d7f496
|
4
|
+
data.tar.gz: d4c5e354f401f469062f5310cd449980b8e1394bf26931696d0a0e2cf053c9f4
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 8784202c7700c39863d9bd94a7d59cac86a16d6a6ebcdba1574f148ed909520743c48c431abb8d9f3fac0eda27dc67a42aeffa3d93653940e1a04939289b3a59
|
7
|
+
data.tar.gz: 94c3e307ce99bd94c381db15f6c278dd816f638c4a9cdbf37962777289535b38d7b0abef9a803feb1af2a59ce18b9dc5b6b734493b9057bb46ea184c5359fc0d
|
data/README.md
ADDED
File without changes
|
data/lib/sastbox-sdk.rb
ADDED
@@ -0,0 +1,26 @@
|
|
1
|
+
require 'base64'
|
2
|
+
require 'digest'
|
3
|
+
require 'json'
|
4
|
+
require 'open3'
|
5
|
+
require 'optparse'
|
6
|
+
require 'ostruct'
|
7
|
+
require 'timeout'
|
8
|
+
require 'tmpdir'
|
9
|
+
require 'securerandom'
|
10
|
+
|
11
|
+
require_relative 'sastbox-sdk/cwe_constants'
|
12
|
+
require_relative 'sastbox-sdk/cwe_detector'
|
13
|
+
require_relative 'sastbox-sdk/snippet'
|
14
|
+
require_relative 'sastbox-sdk/reporter_sarif'
|
15
|
+
require_relative 'sastbox-sdk/opt_parser'
|
16
|
+
require_relative 'sastbox-sdk/printer'
|
17
|
+
require_relative 'sastbox-sdk/runner'
|
18
|
+
require_relative 'sastbox-sdk/severity_calculator'
|
19
|
+
require_relative 'sastbox-sdk/scanner'
|
20
|
+
|
21
|
+
|
22
|
+
module SastBox
|
23
|
+
VERSION = '2.0.0'
|
24
|
+
SDK_VERSION = '0.0.1'
|
25
|
+
end
|
26
|
+
|
@@ -0,0 +1,87 @@
|
|
1
|
+
module SastBox
|
2
|
+
module Cwe
|
3
|
+
UNDEF = 0
|
4
|
+
IMPROPER_INPUT_VALIDATION = 20
|
5
|
+
PATH_TRAVERSAL = 22
|
6
|
+
EXTERNAL_CONTROL_FILE_NAME = 73
|
7
|
+
OS_COMMAND_INJECTION = 78
|
8
|
+
XSS = 79
|
9
|
+
BASIC_XSS = 80
|
10
|
+
SQL_INJECTION = 89
|
11
|
+
LDAP_INJECTION = 90
|
12
|
+
CODE_INJECTION = 94
|
13
|
+
EVAL_INJECTION = 95
|
14
|
+
PHP_REMOTE_FILE_INCLUSION = 98
|
15
|
+
RESPONSE_SPLITTING = 113
|
16
|
+
IMPROPER_RESTRICTION_MEMORY_BOUNDS = 119
|
17
|
+
USE_OF_EXTERNALLY_CONTROLLED_FORMAT_STRING = 134
|
18
|
+
IMPROPER_WILDCARD_NEUTRALIZATION = 155
|
19
|
+
INCORRECT_REGEX = 185
|
20
|
+
INTEGER_OVERFLOW = 190
|
21
|
+
EXPOSURE_SENSITIVE_INFO = 200
|
22
|
+
TIMING_DISCREPANCY = 208
|
23
|
+
ERROR_CONTAINING_SENSITIVE_INFO = 209
|
24
|
+
UNPROTECTED_STORAGE_OF_CREDENTIALS = 256
|
25
|
+
HARD_CODED_PASSWORD = 259
|
26
|
+
IMPROPER_ACCESS_CONTROL = 284
|
27
|
+
IMPROPER_AUTHORIZATION = 285
|
28
|
+
IMPROPER_AUTHENTICATION = 287
|
29
|
+
IMPROPER_CERT_VALIDATION = 295
|
30
|
+
CLEARTEXT_STORAGE_OF_SENSITIVE_INFORMATION = 312
|
31
|
+
CLEARTEXT_TRANSMISSION = 319
|
32
|
+
INADEQUATE_ENCRYPTION_STRENGTH = 326
|
33
|
+
BROKEN_CRYPTO = 327
|
34
|
+
INSUFFICIENT_RANDOM_VALUES = 330
|
35
|
+
INSUFFICIENT_ENTROPY = 331
|
36
|
+
WEAK_PRNG = 338
|
37
|
+
IMPROPER_VERIFICATION_OF_SIGNATURE = 347
|
38
|
+
CSRF = 352
|
39
|
+
TOCTOU = 367
|
40
|
+
DIVIDE_BY_ZERO = 369
|
41
|
+
INSECURE_TEMP_FILE = 377
|
42
|
+
SESSION_FIXATION = 384
|
43
|
+
ERROR_CONDITION_WITHOUT_ACTION = 390
|
44
|
+
RESOURCE_CONSUMPTION = 400
|
45
|
+
IMPROPER_RESOURCE_SHUTDOWN_OR_RELEASE = 404
|
46
|
+
UNRESTRICTED_UPLOAD_OF_FILE_WITH_DANGEROUS_TYPE = 434
|
47
|
+
UNINITIALIZED_VARIABLE = 457
|
48
|
+
UNSAFE_REFLECTION = 470
|
49
|
+
NULL_POINTER_DEREFERENCE = 476
|
50
|
+
OBSOLETE_FUNCTION = 477
|
51
|
+
DATA_LEAK_BETWEEN_SESSIONS = 488
|
52
|
+
ACTIVE_DEBUG_CODE = 489
|
53
|
+
DOWNLOAD_OF_CODE_WITHOUT_INTEGRITY_CHECK = 494
|
54
|
+
EXPOSURE_OF_SYSTEM_DATA = 497
|
55
|
+
DESERIALIZATION_OF_UNTRUSTED_DATA = 502
|
56
|
+
WEAK_PASSWORD_REQUIREMENT = 521
|
57
|
+
SENSITIVE_INFO_LOG_FILE = 532
|
58
|
+
USE_OF_PERSISTENT_COOKIES = 539
|
59
|
+
SUSPICIOUS_COMMENT = 546
|
60
|
+
OPEN_REDIRECT = 601
|
61
|
+
MULTIPLE_BINDS = 605
|
62
|
+
IMPROPER_RESTRICTION_OF_XML_EXTERNAL_ENTITY_REFERENCE = 611
|
63
|
+
SENSITIVE_INFO_IN_SOURCE_CODE_COMMENTS = 615
|
64
|
+
AUTHORIZATION_BYPASS_THROUGH_KEY = 639
|
65
|
+
XPATH_INJECTION = 643
|
66
|
+
XQUERY_INJECTION = 652
|
67
|
+
EXPOSURE_RESOURCE_WRONG_SPHERE = 668
|
68
|
+
USE_OF_POTENTIALLY_DANGEROUS_FUNCTION = 676
|
69
|
+
PROTECTION_MECHANISM_FAILURE = 693
|
70
|
+
IMPROPER_CHECK_OF_EXCEPT_COND = 703
|
71
|
+
INCORRECT_PERMISSION_ASSIGNMENT = 732
|
72
|
+
EXPOSED_DANGEROUS_METHOD_OR_FUNCTION = 749
|
73
|
+
SELECTION_OF_LESS_SECURE_ALGORITHM_DURING_NEGOTIATION = 757
|
74
|
+
UNSALTED_ONE_WAY_HASH = 759
|
75
|
+
REGEX_WITHOUT_ANCHORS = 777
|
76
|
+
RELIANCE_ON_UNTRUSTED_INPUTS_IN_A_SECURITY_DECISION = 807
|
77
|
+
INCLUSION_FUNCTIONALITY_UNTRUSTED_SPHERE = 829
|
78
|
+
IMPROPER_CONTROL_DYNAMIC_ATTR = 915
|
79
|
+
SSRF = 918
|
80
|
+
USING_COMPONENTS_WITH_KNOWN_VULNERABILITIES = 937
|
81
|
+
SENSITIVE_COOKIE_WITHOUT_HTTPONLY_FLAG = 1004
|
82
|
+
IMPROPER_RESTRICTION_OF_RENDERED_UI_LAYERS_OF_FRAMES = 1021
|
83
|
+
USE_OF_WEB_LINK_TO_UNTRUSTED_TARGET = 1022
|
84
|
+
SECURITY_MISCONFIGURATION = 1032
|
85
|
+
USE_OF_UNMAINTAINED_THIRD_PARTY_COMPONENTS = 1104
|
86
|
+
end
|
87
|
+
end
|
@@ -0,0 +1,202 @@
|
|
1
|
+
require 'set'
|
2
|
+
|
3
|
+
module SastBox
|
4
|
+
module Cwe
|
5
|
+
|
6
|
+
def cwe_found?(issue, patterns, cwe)
|
7
|
+
patterns.each do |pattern|
|
8
|
+
@alternative_titles.each do |title|
|
9
|
+
if title.include? pattern
|
10
|
+
issue[:cwe_id] = cwe
|
11
|
+
return true
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
return false
|
16
|
+
end
|
17
|
+
|
18
|
+
def detected_sql_injection?(issue)
|
19
|
+
patterns = [
|
20
|
+
'sql injection',
|
21
|
+
'sqlinj',
|
22
|
+
'sqli',
|
23
|
+
'sql inj'
|
24
|
+
]
|
25
|
+
cwe_found?(issue, patterns, SastBox::Cwe::SQL_INJECTION)
|
26
|
+
end
|
27
|
+
|
28
|
+
def detected_xss?(issue)
|
29
|
+
patterns = [
|
30
|
+
'xss',
|
31
|
+
'cross-site scripting',
|
32
|
+
'cross site scripting',
|
33
|
+
'html injection'
|
34
|
+
]
|
35
|
+
cwe_found?(issue, patterns, SastBox::Cwe::XSS)
|
36
|
+
end
|
37
|
+
|
38
|
+
def detected_cmd_injection?(issue)
|
39
|
+
patterns = [
|
40
|
+
'command injection',
|
41
|
+
'command execution',
|
42
|
+
'cmd injection',
|
43
|
+
'cmd execution',
|
44
|
+
'cmd exec',
|
45
|
+
'shell injection',
|
46
|
+
'shell metacharacters'
|
47
|
+
]
|
48
|
+
cwe_found?(issue, patterns, SastBox::Cwe::OS_COMMAND_INJECTION)
|
49
|
+
end
|
50
|
+
|
51
|
+
def detected_code_injection?(issue)
|
52
|
+
patterns = [
|
53
|
+
'code injection',
|
54
|
+
'code execution',
|
55
|
+
'code exec',
|
56
|
+
'code inj'
|
57
|
+
]
|
58
|
+
cwe_found?(issue, patterns, SastBox::Cwe::CODE_INJECTION)
|
59
|
+
end
|
60
|
+
|
61
|
+
def detected_session_fixation?(issue)
|
62
|
+
patterns = [
|
63
|
+
'session fixation',
|
64
|
+
]
|
65
|
+
cwe_found?(issue, patterns, SastBox::Cwe::SESSION_FIXATION)
|
66
|
+
end
|
67
|
+
|
68
|
+
def detected_csrf?(issue)
|
69
|
+
patterns = [
|
70
|
+
'csrf',
|
71
|
+
'xsrf',
|
72
|
+
'cross site request forgery',
|
73
|
+
'session riding',
|
74
|
+
'cross site reference forgery',
|
75
|
+
]
|
76
|
+
cwe_found?(issue, patterns, SastBox::Cwe::CSRF)
|
77
|
+
end
|
78
|
+
|
79
|
+
def detected_deserialization?(issue)
|
80
|
+
patterns = [
|
81
|
+
'deserializ',
|
82
|
+
'unmarshaling',
|
83
|
+
'unpickling',
|
84
|
+
'php object injection'
|
85
|
+
]
|
86
|
+
cwe_found?(issue, patterns, SastBox::Cwe::DESERIALIZATION_OF_UNTRUSTED_DATA)
|
87
|
+
end
|
88
|
+
|
89
|
+
def detected_path_traversal?(issue)
|
90
|
+
patterns = [
|
91
|
+
'path traversal',
|
92
|
+
'traversal',
|
93
|
+
'pathtraversal'
|
94
|
+
]
|
95
|
+
cwe_found?(issue, patterns, SastBox::Cwe::PATH_TRAVERSAL)
|
96
|
+
end
|
97
|
+
|
98
|
+
def detected_hardcoded_password?(issue)
|
99
|
+
patterns = [
|
100
|
+
'hard-coded'
|
101
|
+
]
|
102
|
+
cwe_found?(issue, patterns, SastBox::Cwe::HARD_CODED_PASSWORD)
|
103
|
+
end
|
104
|
+
|
105
|
+
def detected_null_ptr_deref?(issue)
|
106
|
+
patterns = [
|
107
|
+
'null pointer deref'
|
108
|
+
]
|
109
|
+
cwe_found?(issue, patterns, SastBox::Cwe::NULL_POINTER_DEREFERENCE)
|
110
|
+
end
|
111
|
+
|
112
|
+
def detected_broken_crypto?(issue)
|
113
|
+
patterns = [
|
114
|
+
'weak cipher',
|
115
|
+
'weak crypto',
|
116
|
+
'insecure cipher',
|
117
|
+
'insecure crypto',
|
118
|
+
'insecure encryption',
|
119
|
+
'broken cipher',
|
120
|
+
'broken crypto',
|
121
|
+
'weak hash',
|
122
|
+
'insecure hash',
|
123
|
+
'broken hash',
|
124
|
+
]
|
125
|
+
cwe_found?(issue, patterns, SastBox::Cwe::BROKEN_CRYPTO)
|
126
|
+
end
|
127
|
+
|
128
|
+
def detected_improper_authorization?(issue)
|
129
|
+
patterns = [
|
130
|
+
'improper authorization',
|
131
|
+
'no authorization',
|
132
|
+
'broken authorization',
|
133
|
+
]
|
134
|
+
cwe_found?(issue, patterns, SastBox::Cwe::IMPROPER_AUTHORIZATION)
|
135
|
+
end
|
136
|
+
|
137
|
+
def detected_improper_authentication?(issue)
|
138
|
+
patterns = [
|
139
|
+
'improper authentication',
|
140
|
+
'no authentication',
|
141
|
+
'broken authentication',
|
142
|
+
]
|
143
|
+
cwe_found?(issue, patterns, SastBox::Cwe::IMPROPER_AUTHENTICATION)
|
144
|
+
end
|
145
|
+
|
146
|
+
def detected_improper_input_validation?(issue)
|
147
|
+
patterns = [
|
148
|
+
'input validation',
|
149
|
+
'data validation',
|
150
|
+
]
|
151
|
+
cwe_found?(issue, patterns, SastBox::Cwe::IMPROPER_INPUT_VALIDATION)
|
152
|
+
end
|
153
|
+
|
154
|
+
def detected_unrestricted_file_upload?(issue)
|
155
|
+
patterns = [
|
156
|
+
'unrestricted upload',
|
157
|
+
'unrestricted file upload',
|
158
|
+
]
|
159
|
+
cwe_found?(issue, patterns, SastBox::Cwe::UNRESTRICTED_UPLOAD_OF_FILE_WITH_DANGEROUS_TYPE)
|
160
|
+
end
|
161
|
+
|
162
|
+
def cwe_start_heuristics(issue)
|
163
|
+
alternative_titles(issue)
|
164
|
+
issue[:cwe_id] = SastBox::Cwe::UNDEF
|
165
|
+
return if detected_sql_injection?(issue)
|
166
|
+
return if detected_xss?(issue)
|
167
|
+
return if detected_cmd_injection?(issue)
|
168
|
+
return if detected_code_injection?(issue)
|
169
|
+
return if detected_session_fixation?(issue)
|
170
|
+
return if detected_csrf?(issue)
|
171
|
+
return if detected_deserialization?(issue)
|
172
|
+
return if detected_path_traversal?(issue)
|
173
|
+
return if detected_hardcoded_password?(issue)
|
174
|
+
return if detected_null_ptr_deref?(issue)
|
175
|
+
return if detected_broken_crypto?(issue)
|
176
|
+
return if detected_improper_authorization?(issue)
|
177
|
+
return if detected_improper_authentication?(issue)
|
178
|
+
return if detected_improper_input_validation?(issue)
|
179
|
+
return if detected_unrestricted_file_upload?(issue)
|
180
|
+
end
|
181
|
+
|
182
|
+
def alternative_titles(issue)
|
183
|
+
@alternative_titles = Set.new
|
184
|
+
@alternative_titles << issue[:title].downcase
|
185
|
+
|
186
|
+
@alternative_titles << @alternative_titles.first.split('_').join(' ')
|
187
|
+
@alternative_titles << @alternative_titles.first.split('-').join(' ')
|
188
|
+
@alternative_titles << @alternative_titles.first.gsub("hard coded", "hard-coded")
|
189
|
+
@alternative_titles << @alternative_titles.first.gsub("hardcoded", "hard-coded")
|
190
|
+
@alternative_titles
|
191
|
+
end
|
192
|
+
|
193
|
+
def guess_cwe(issue)
|
194
|
+
if issue.key?(:cwe_id)
|
195
|
+
cwe_start_heuristics(issue) if [SastBox::Cwe::UNDEF, -1, nil].include?(issue[:cwe_id])
|
196
|
+
else
|
197
|
+
cwe_start_heuristics(issue)
|
198
|
+
end
|
199
|
+
end
|
200
|
+
|
201
|
+
end
|
202
|
+
end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
require 'optparse'
|
2
|
+
require 'ostruct'
|
3
|
+
|
4
|
+
module SastBox
|
5
|
+
module OptParser
|
6
|
+
def parse_opts(args)
|
7
|
+
@opts = OpenStruct.new
|
8
|
+
@opts.verbose = false
|
9
|
+
@opts.info = false
|
10
|
+
@opts.color = true
|
11
|
+
@opts.diff_hashes = []
|
12
|
+
@opts.diff_quick = false
|
13
|
+
@opts.timeout = 200 * 60
|
14
|
+
|
15
|
+
opt_parser = OptionParser.new do |opts|
|
16
|
+
opts.on('-c', '--codebase=CODEBASE', 'Codebase to be scanned') do |codebase|
|
17
|
+
@opts.codebase = codebase
|
18
|
+
end
|
19
|
+
|
20
|
+
opts.on('-o', '--output=OUTPUT', 'Output path to save SARIF result') do |output|
|
21
|
+
@opts.output = output
|
22
|
+
end
|
23
|
+
|
24
|
+
opts.on("-v", '--[no-]verbose', 'Run verbosely') do |v|
|
25
|
+
@opts.verbose = v
|
26
|
+
end
|
27
|
+
|
28
|
+
opts.on('-t', '--timeout=TIMEOUT', Integer, "Control timeout (default: #{@opts.timeout/60} mins per scanner)") do |timeout|
|
29
|
+
@opts.timeout = timeout * 60
|
30
|
+
end
|
31
|
+
|
32
|
+
opts.on("-i", '--info', 'Info about the scanner') do
|
33
|
+
@opts.info = true
|
34
|
+
end
|
35
|
+
|
36
|
+
opts.on('-n', '--[no-]color', 'Enable/disable coloring') do |v|
|
37
|
+
@opts.color = v
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
opt_parser.parse!(args)
|
42
|
+
@opts
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
@@ -0,0 +1,86 @@
|
|
1
|
+
require 'colored'
|
2
|
+
require 'date'
|
3
|
+
|
4
|
+
module SastBox
|
5
|
+
module Printer
|
6
|
+
|
7
|
+
def enable_color(flag = true)
|
8
|
+
@color = flag
|
9
|
+
end
|
10
|
+
|
11
|
+
def print_title(s, level = 0)
|
12
|
+
pad = " " * (level * 4)
|
13
|
+
out_s = "#{pad}[*] #{s}"
|
14
|
+
if @color
|
15
|
+
puts out_s.bold.blue
|
16
|
+
else
|
17
|
+
puts out_s
|
18
|
+
end
|
19
|
+
@logger.info(out_s) if instance_variable_defined?("@logger")
|
20
|
+
end
|
21
|
+
|
22
|
+
def print_normal(s, level = 0)
|
23
|
+
pad = " " * (level * 4)
|
24
|
+
out_s = "#{pad}#{s}"
|
25
|
+
puts out_s
|
26
|
+
@logger.info(out_s) if instance_variable_defined?("@logger")
|
27
|
+
end
|
28
|
+
|
29
|
+
def print_success(s, level = 0)
|
30
|
+
pad = " " * (level * 4)
|
31
|
+
out_s = "#{pad}[SUCCESS] #{s}"
|
32
|
+
if @color
|
33
|
+
puts out_s.bold.green
|
34
|
+
else
|
35
|
+
puts out_s
|
36
|
+
end
|
37
|
+
@logger.info(out_s) if instance_variable_defined?("@logger")
|
38
|
+
end
|
39
|
+
|
40
|
+
def print_error(s, level = 0)
|
41
|
+
pad = " " * (level * 4)
|
42
|
+
out_s = "#{pad}[ ERROR ] #{s}"
|
43
|
+
if @color
|
44
|
+
puts out_s.bold.red
|
45
|
+
else
|
46
|
+
puts out_s
|
47
|
+
end
|
48
|
+
@logger.error(out_s) if instance_variable_defined?("@logger")
|
49
|
+
end
|
50
|
+
|
51
|
+
def print_with_label(s, label, level = 0)
|
52
|
+
pad = " " * (level * 4)
|
53
|
+
out_s = "#{pad}[#{label}] #{s}"
|
54
|
+
puts out_s
|
55
|
+
@logger.info(out_s) if instance_variable_defined?("@logger")
|
56
|
+
end
|
57
|
+
|
58
|
+
def print_debug(s, level = 0)
|
59
|
+
pad = " " * (level * 4)
|
60
|
+
now = DateTime.now.strftime('%d/%m/%Y %H:%M:%S.%3N')
|
61
|
+
out_s = "#{pad}DEBUG|#{now}| #{s}"
|
62
|
+
if @color
|
63
|
+
puts out_s.bold.yellow
|
64
|
+
else
|
65
|
+
puts out_s
|
66
|
+
end
|
67
|
+
@logger.debug(out_s) if instance_variable_defined?("@logger")
|
68
|
+
end
|
69
|
+
|
70
|
+
def print_warning(s, level = 0)
|
71
|
+
pad = " " * (level * 4)
|
72
|
+
out_s = "#{pad}[WARNING] #{s}"
|
73
|
+
if @color
|
74
|
+
puts out_s.bold.yellow
|
75
|
+
else
|
76
|
+
puts out_s
|
77
|
+
end
|
78
|
+
@logger.info(out_s) if instance_variable_defined?("@logger")
|
79
|
+
end
|
80
|
+
|
81
|
+
def self.included(base)
|
82
|
+
#base.instance_variable_set(:@color, true)
|
83
|
+
end
|
84
|
+
|
85
|
+
end
|
86
|
+
end
|