Skip to content

Commit a3afc9e

Browse files
authored
OutputEngine: Console Output Updated
Signed-off-by: John Andersen <[email protected]>
1 parent ea5ca34 commit a3afc9e

File tree

2 files changed

+139
-1
lines changed

2 files changed

+139
-1
lines changed

cve_bin_tool/OutputEngine.py

+92-1
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,14 @@
77

88

99
class OutputEngine(object):
10+
11+
# Max space for each console tabular cell
12+
MODULENAME_MAX = 18
13+
VERSION_MAX = 9
14+
CVE_NUMBER_MAX = 18
15+
CVE_SEVERITY_MAX = 9
16+
DOTS = "..."
17+
1018
def __init__(self, filename=None, modules=None, logger=None):
1119
if logger is None:
1220
logger = LOGGER.getChild(self.__class__.__name__)
@@ -27,8 +35,10 @@ def output_cves(self, outfile, output=None):
2735
"""
2836
if output == "json":
2937
self.output_json(outfile)
30-
else: # csv, console, or anything else that is unrecognised
38+
elif output == "csv":
3139
self.output_csv(outfile)
40+
else: # console, or anything else that is unrecognised
41+
self.output_console(outfile)
3242

3343
def formatted_modules(self):
3444
""" Returns self.modules converted into form
@@ -62,6 +72,87 @@ def output_csv(self, outfile):
6272
row = [modulename, version, cve_number, cve_severity]
6373
writer.writerow(row)
6474

75+
def write_console(self, modulename, version, cve_number, cve_severity, outfile):
76+
""" Output Module, Version, CVE_Number, Severity to the console in tabular form"""
77+
78+
if len(modulename) > (self.MODULENAME_MAX - len(self.DOTS)):
79+
modulename = modulename[: self.MODULENAME_MAX - len(self.DOTS)] + self.DOTS
80+
81+
# Calculate length of -- modulename, version, cve_number, cve_severity
82+
modulename_len = len(modulename)
83+
version_len = len(str(version))
84+
cve_number_len = len(cve_number)
85+
cve_severity_len = len(cve_severity)
86+
87+
# Generate all the fields with appropriate space to be fit into tabular form
88+
modulename = f"{modulename}{' '* (self.MODULENAME_MAX - modulename_len)}"
89+
version = f"{version}{' '* (self.VERSION_MAX - version_len)}"
90+
cve_number = f"{cve_number}{' '* (self.CVE_NUMBER_MAX - cve_number_len)}"
91+
cve_severity = (
92+
f"{cve_severity}{' '* (self.CVE_SEVERITY_MAX - cve_severity_len)}"
93+
)
94+
95+
# End string marks end for the previous length data
96+
end_string = f"+{'-'*(self.MODULENAME_MAX + 2)}+{'-'*(self.VERSION_MAX + 2)}+{'-'*(self.CVE_NUMBER_MAX + 2)}+{'-'*(self.CVE_SEVERITY_MAX + 2)}+\n"
97+
98+
# string generate the details in tabular form
99+
string = f"| {modulename} | {version} | {cve_number} | {cve_severity} |\n"
100+
101+
# Write String and End String to the console
102+
outfile.write(string)
103+
outfile.write(end_string)
104+
105+
def output_console(self, outfile):
106+
""" Output list of CVEs in a tabular format """
107+
108+
# Now contains the time at which report is generated
109+
now = datetime.now().strftime("%Y-%m-%d %H:%m:%S")
110+
111+
# The main heading containing CVE-Bin-Tool logo
112+
heading = f"""
113+
+=================================================================+
114+
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
115+
+=================================================================+
116+
|| ____ __ __ _____ ______ __ __ _ ||
117+
|| /$$$$| \$\ /$/ |$$$$$| |$$$$$$\ |$$| |$$\ |$| ||
118+
|| |$$ \$\ /$/ |$____ |$____$/ |$$| |$$$\ |$| ||
119+
|| |$$ \$\ /$/ |$$$$$| == |$$$$$$\ |$$| |$|\$\|$| ||
120+
|| |$$ \$\/$/ |$____ `` |$_____$ |$$| |$| \$$$| ||
121+
|| \$$$$| \$$/ |$$$$$| |$$$$$$/ |$4| |$| \$$| ||
122+
|| ````` `` `````` `````` ``` `` ``` ||
123+
|| ____________ ________ ________ __ ||
124+
|| |$$$$$$$$$$$$| /$$$$$$$$\ /$$$$$$$$\ |$$| ||
125+
|| |$$| |$$| |$$| |$$| |$$| |$$| ||
126+
|| |$$| |$$| |$$| |$$| |$$| |$$| ||
127+
|| |$$| |$$| |$$| |$$| |$$| |$$| ||
128+
|| |$$| |$$| |$$| |$$| |$$| |$$|_______ ||
129+
|| |$$| \$$$$$$$$/ \$$$$$$$$/ |$$$$$$$$$$| ||
130+
|| ```` ```````` ```````` ```````````` ||
131+
+=================================================================+
132+
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
133+
+=================================================================+
134+
135+
+=================================================================+
136+
| Report Generated:{now} |
137+
+=================================================================+
138+
139+
+=================================================================+
140+
| MODULE NAME | VERSION | CVE NUMBER | SEVERITY |
141+
+=================================================================+
142+
"""
143+
144+
# Outputs Heading to the console
145+
outfile.write(heading)
146+
147+
# for every module that is scanned -- output to the console
148+
for modulename, versions in self.modules.items():
149+
for version, cve_list in versions.items():
150+
for cve_number, cve_severity in cve_list.items():
151+
# call to the write_console function for each module,version
152+
self.write_console(
153+
modulename, version, cve_number, cve_severity, outfile
154+
)
155+
65156
def output_file(self, output="csv"):
66157

67158
""" Generate a file for list of CVE """

test/test_output_engine.py

+47
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
import io
66
import json
77
import csv
8+
import sys
89

910
from cve_bin_tool.OutputEngine import OutputEngine
1011

@@ -59,3 +60,49 @@ def test_output_csv(self):
5960
read_modules[modulename][version] = {}
6061
read_modules[modulename][version][cve_number] = severity
6162
self.assertEqual(read_modules, self.MOCK_MODULES)
63+
64+
def test_output_console(self):
65+
"""Test Formatting Output as console"""
66+
67+
# list of mock modules having length greater than the current Respective Max Length
68+
mock_module_names = [
69+
"ABCDEFGHIJKLMNOPQRS",
70+
"ABCDEFGHIJKLMNOPQR",
71+
"ABCDEFGHIJKLMNOPQ",
72+
"ABCDEFGHIJKLMNOP",
73+
"ABCDEFGHIJKLMNO",
74+
"ABCDEFGHIJKLMN",
75+
"glibc",
76+
"I'm a different module",
77+
]
78+
79+
# generate output
80+
for name in mock_module_names:
81+
self.output_engine.write_console(
82+
name, "0.0.1", "CVE-2018-12381", "HIGH", self.mock_file
83+
)
84+
85+
# expected output
86+
output_modules = """| ABCDEFGHIJKLMNO... | 0.0.1 | CVE-2018-12381 | HIGH |
87+
+--------------------+-----------+--------------------+-----------+
88+
| ABCDEFGHIJKLMNO... | 0.0.1 | CVE-2018-12381 | HIGH |
89+
+--------------------+-----------+--------------------+-----------+
90+
| ABCDEFGHIJKLMNO... | 0.0.1 | CVE-2018-12381 | HIGH |
91+
+--------------------+-----------+--------------------+-----------+
92+
| ABCDEFGHIJKLMNO... | 0.0.1 | CVE-2018-12381 | HIGH |
93+
+--------------------+-----------+--------------------+-----------+
94+
| ABCDEFGHIJKLMNO | 0.0.1 | CVE-2018-12381 | HIGH |
95+
+--------------------+-----------+--------------------+-----------+
96+
| ABCDEFGHIJKLMN | 0.0.1 | CVE-2018-12381 | HIGH |
97+
+--------------------+-----------+--------------------+-----------+
98+
| glibc | 0.0.1 | CVE-2018-12381 | HIGH |
99+
+--------------------+-----------+--------------------+-----------+
100+
| I'm a different... | 0.0.1 | CVE-2018-12381 | HIGH |
101+
+--------------------+-----------+--------------------+-----------+
102+
"""
103+
self.mock_file.seek(0) # reset file position
104+
105+
output = self.mock_file.getvalue().split("\n")
106+
for i, line in enumerate(output_modules.split("\n")):
107+
with self.subTest(i=i):
108+
self.assertEqual(line, output[i])

0 commit comments

Comments
 (0)