@@ -7,8 +7,10 @@ import (
7
7
"log"
8
8
"os"
9
9
"path/filepath"
10
+ "runtime"
10
11
"scan2html/internal/common"
11
12
"scan2html/internal/epss"
13
+ "scan2html/internal/exploit"
12
14
"scan2html/internal/logger"
13
15
"strings"
14
16
"time"
@@ -25,10 +27,12 @@ func GenerateHtmlReport(pluginFlags common.Flags, version string) error {
25
27
26
28
reportName := pluginFlags ["--output" ]
27
29
_ , withEpss := pluginFlags ["--with-epss" ]
30
+ _ , withExploits := pluginFlags ["--with-exploits" ]
28
31
reportTitle := pluginFlags ["--report-title" ]
29
32
// Log input parameters for clarity
30
33
logger .Logger .Infof ("Base Directory: %s\n " , baseDir )
31
34
logger .Logger .Infof ("With EPSS: %t\n " , withEpss )
35
+ logger .Logger .Infof ("With Exploits: %t\n " , withExploits )
32
36
logger .Logger .Infof ("Report Title: %s\n " , reportTitle )
33
37
logger .Logger .Infof ("Report Name: %s\n " , reportName )
34
38
@@ -43,7 +47,7 @@ func GenerateHtmlReport(pluginFlags common.Flags, version string) error {
43
47
44
48
err = replaceTextByText (reportName , "TEMP_APP_VERSION" , version )
45
49
if err != nil {
46
- return fmt .Errorf ("failed to replace report title in %s: %v" , reportName , err )
50
+ return fmt .Errorf ("failed to replace app version in %s: %v" , reportName , err )
47
51
}
48
52
49
53
// Replace placeholders with actual content in the report file
@@ -57,26 +61,67 @@ func GenerateHtmlReport(pluginFlags common.Flags, version string) error {
57
61
}
58
62
59
63
// Handle EPSS data if enabled
64
+ // replaceTextByFile "$report_name" "\"TEMP_EPSS_DATA\"" "$epss_data"
65
+ // Schedule deletion of the EPSS data file upon function exit
66
+ shouldReturn , returnValue := handleEPSS (withEpss , reportName )
67
+ if shouldReturn {
68
+ return returnValue
69
+ }
70
+
71
+ shouldReturn , returnValue = handleExploit (withExploits , reportName )
72
+ if shouldReturn {
73
+ return returnValue
74
+ }
75
+
76
+ logger .Logger .Infof ("%s has been created successfully!\n " , reportName )
77
+ return nil
78
+ }
79
+
80
+ func handleEPSS (withEpss bool , reportName string ) (bool , error ) {
60
81
if withEpss {
61
82
logger .Logger .Infoln ("EPSS enabled!" )
62
83
var epssDataFile , err = epss .PrepareEpssData ()
63
84
if err != nil {
64
- return fmt .Errorf ("failed to prepare EPSS data: %v" , err )
85
+ return true , fmt .Errorf ("failed to prepare EPSS data: %v" , err )
65
86
}
66
87
67
- // replaceTextByFile "$report_name" "\"TEMP_EPSS_DATA\"" "$epss_data"
68
88
if err := replaceTextByFile (reportName , "\" TEMP_EPSS_DATA\" " , epssDataFile ); err != nil {
69
- return fmt .Errorf ("failed to replace EPSS data in %s: %v" , reportName , err )
89
+ return true , fmt .Errorf ("failed to replace EPSS data in %s: %v" , reportName , err )
70
90
}
71
91
72
92
logger .Logger .Infoln ("EPSS data imported!" )
73
93
74
- // Schedule deletion of the EPSS data file upon function exit
75
94
defer os .Remove (epssDataFile )
76
95
}
96
+ return false , nil
97
+ }
77
98
78
- logger .Logger .Infof ("%s has been created successfully!\n " , reportName )
79
- return nil
99
+ func handleExploit (withExploits bool , reportName string ) (bool , error ) {
100
+ if withExploits {
101
+ logger .Logger .Infoln ("Exploits enabled!" )
102
+ var exploitDataFile , err = exploit .PrepareExploitData ()
103
+ if err != nil {
104
+ return true , fmt .Errorf ("failed to prepare Exploits data: %v" , err )
105
+ }
106
+
107
+ if err := replaceTextByFile (reportName , "{TEMP_EXPLOITS:0}" , exploitDataFile ); err != nil {
108
+ return true , fmt .Errorf ("failed to replace Exploits data in %s: %v" , reportName , err )
109
+ }
110
+
111
+ logger .Logger .Infoln ("Exploits data imported!" )
112
+
113
+ defer os .Remove (exploitDataFile )
114
+ }
115
+ return false , nil
116
+ }
117
+
118
+ // replaceTextByFile replaces occurrences of search_text in the input file with content from replace_file.
119
+ func replaceTextByFile (inputFile , searchText , replaceFile string ) error {
120
+ replaceContent , err := os .ReadFile (replaceFile )
121
+ if err != nil {
122
+ return fmt .Errorf ("could not read file %s: %v" , replaceFile , err )
123
+ }
124
+ return replaceTextByText (inputFile , searchText , string (replaceContent ))
80
125
}
81
126
82
127
// replaceTextByText replaces occurrences of search_text in the input file with replace_content.
@@ -87,11 +132,11 @@ func replaceTextByText(inputFile, searchText, replaceContent string) error {
87
132
}
88
133
defer file .Close ()
89
134
90
- tempFile , err := os .CreateTemp ("" , "modified_" )
135
+ timestamp := time .Now ().Format ("2006_01_02_15_04_05_06" )
136
+ tempFile , err := os .CreateTemp ("" , fmt .Sprintf ("modified_%s" , timestamp ))
91
137
if err != nil {
92
138
return fmt .Errorf ("could not create temp file: %v" , err )
93
139
}
94
- defer tempFile .Close ()
95
140
96
141
reader := bufio .NewReader (file )
97
142
writer := bufio .NewWriter (tempFile )
@@ -119,45 +164,52 @@ func replaceTextByText(inputFile, searchText, replaceContent string) error {
119
164
return fmt .Errorf ("error writing to temp file: %v" , err )
120
165
}
121
166
122
-
123
167
return copyAndRemove (tempFile .Name (), inputFile )
124
168
}
125
169
126
170
func copyAndRemove (src , dst string ) error {
127
- // Open the source file
128
- sourceFile , err := os .Open (src )
129
- if err != nil {
130
- return err
131
- }
132
- defer sourceFile .Close ()
133
-
134
- // Create the destination file
135
- destFile , err := os .Create (dst )
136
- if err != nil {
137
- return err
138
- }
139
- defer destFile .Close ()
140
-
141
- // Copy the contents
142
- if _ , err := io .Copy (destFile , sourceFile ); err != nil {
143
- return err
144
- }
145
-
146
- // Close files before removal
147
- sourceFile .Close ()
148
- destFile .Close ()
149
-
150
- // Remove the source file
151
- return os .Remove (src )
152
- }
171
+ // Open the source file
172
+ sourceFile , err := os .Open (src )
173
+ if err != nil {
174
+ return fmt .Errorf ("failed to open source file %s: %v" , src , err )
175
+ }
176
+ defer sourceFile .Close ()
153
177
154
- // replaceTextByFile replaces occurrences of search_text in the input file with content from replace_file.
155
- func replaceTextByFile (inputFile , searchText , replaceFile string ) error {
156
- replaceContent , err := os .ReadFile (replaceFile )
178
+ // Create the destination file
179
+ destFile , err := os .Create (dst )
157
180
if err != nil {
158
- return fmt .Errorf ("could not read file %s: %v" , replaceFile , err )
181
+ return fmt .Errorf ("failed to create destination file %s: %v" , dst , err )
159
182
}
160
- return replaceTextByText (inputFile , searchText , string (replaceContent ))
183
+ defer destFile .Close ()
184
+
185
+ // Copy the contents
186
+ if _ , err := io .Copy (destFile , sourceFile ); err != nil {
187
+ return fmt .Errorf ("failed to copy contents from %s to %s: %v" , src , dst , err )
188
+ }
189
+
190
+ // Ensure all data is written to the destination file
191
+ if err := destFile .Sync (); err != nil {
192
+ return fmt .Errorf ("failed to sync destination file %s: %v" , dst , err )
193
+ }
194
+
195
+ // Close the destination file
196
+ if err := destFile .Close (); err != nil {
197
+ return fmt .Errorf ("failed to close destination file %s: %v" , dst , err )
198
+ }
199
+
200
+ // Close the source file
201
+ if err := sourceFile .Close (); err != nil {
202
+ return fmt .Errorf ("failed to close source file %s: %v" , src , err )
203
+ }
204
+
205
+ // Check if the operating system is Windows
206
+ if runtime .GOOS == "windows" {
207
+ // Remove the source file is failing on windows
208
+ return nil
209
+ }
210
+
211
+ defer os .Remove (src )
212
+ return nil
161
213
}
162
214
163
215
// generateReportName creates a unique report name based on timestamp if the file already exists.
0 commit comments