1
1
use std:: { env, thread} ;
2
2
use std:: process:: { Command , Stdio } ;
3
3
use std:: io:: { self , BufRead } ;
4
+ use rand:: Rng ;
4
5
use regex:: Regex ;
5
6
use clap:: Parser ;
6
- use std:: fs;
7
+ use std:: fs:: { self , File } ;
7
8
use std:: io:: Write ;
8
9
9
10
mod linux;
@@ -26,7 +27,9 @@ pub struct Antivirus {
26
27
home_dir : String ,
27
28
google_chat_url : String ,
28
29
summary : String ,
29
- args : Args
30
+ infected_files : String ,
31
+ args : Args ,
32
+ tmp_file : String
30
33
}
31
34
32
35
fn is_clamav_installed ( ) -> io:: Result < bool > {
@@ -37,6 +40,14 @@ fn is_clamav_installed() -> io::Result<bool> {
37
40
Ok ( !output. stdout . is_empty ( ) )
38
41
}
39
42
43
+ fn generate_random_file_name ( ) -> String {
44
+ let mut rng = rand:: thread_rng ( ) ;
45
+ let random_string: String = ( 0 ..10 )
46
+ . map ( |_| rng. sample ( rand:: distributions:: Alphanumeric ) as char )
47
+ . collect ( ) ;
48
+ format ! ( "/tmp/{}.txt" , random_string)
49
+ }
50
+
40
51
fn handle_freshclam_copy ( path : & str ) -> std:: io:: Result < ( ) > {
41
52
let sample_path = format ! ( "{}/freshclam.conf.sample" , path) ;
42
53
let config_path = & format ! ( "{}/freshclam.conf" , path) ;
@@ -178,6 +189,8 @@ impl Antivirus {
178
189
Self {
179
190
home_dir : env:: var ( "HOME" ) . expect ( "Failed to get HOME directory" ) ,
180
191
summary : String :: new ( ) ,
192
+ infected_files : String :: new ( ) ,
193
+ tmp_file : generate_random_file_name ( ) ,
181
194
google_chat_url,
182
195
args
183
196
}
@@ -195,8 +208,8 @@ impl Antivirus {
195
208
"--archive-verbose" ,
196
209
"--alert-exceeds-max=yes" ,
197
210
"--alert-encrypted=yes" ,
198
- "--max-filesize=4095M " ,
199
- "--max-scansize=4095M " ,
211
+ "--max-filesize=10000M " ,
212
+ "--max-scansize=10000M " ,
200
213
"--max-files=1000000" ,
201
214
"--max-recursion=512" ,
202
215
"--max-htmlnotags=256M" ,
@@ -212,6 +225,7 @@ impl Antivirus {
212
225
. expect ( "Failed to execute clamscan" ) ;
213
226
214
227
let regex_patterns = vec ! [
228
+ Regex :: new( r": FOUND$" ) . unwrap( ) ,
215
229
Regex :: new( r"^----------- SCAN SUMMARY -----------" ) . unwrap( ) ,
216
230
Regex :: new( r"^Known viruses:" ) . unwrap( ) ,
217
231
Regex :: new( r"^Engine version:" ) . unwrap( ) ,
@@ -225,6 +239,10 @@ impl Antivirus {
225
239
Regex :: new( r"^End Date:" ) . unwrap( ) ,
226
240
] ;
227
241
242
+ let infected_regex_patterns = vec ! [
243
+ Regex :: new( r": FOUND$" ) . unwrap( ) ,
244
+ ] ;
245
+
228
246
self . summary . push_str ( & format ! ( "{}\n \n " , self . home_dir) ) ;
229
247
230
248
if let Some ( stdout) = child. stdout . take ( ) {
@@ -236,6 +254,9 @@ impl Antivirus {
236
254
if regex_patterns. iter ( ) . any ( |regex| regex. is_match ( & line) ) {
237
255
self . summary . push_str ( & format ! ( "{}\n " , line) ) ;
238
256
}
257
+ if infected_regex_patterns. iter ( ) . any ( |regex| regex. is_match ( & line) ) {
258
+ self . infected_files . push_str ( & format ! ( "{}\n " , line) ) ;
259
+ }
239
260
} ,
240
261
Err ( err) => eprintln ! ( "Error reading line: {}" , err) ,
241
262
}
@@ -248,37 +269,44 @@ impl Antivirus {
248
269
249
270
}
250
271
251
- pub async fn notify ( & self ) {
272
+ pub async fn notify ( & mut self ) {
252
273
if self . google_chat_url != "" {
253
-
254
- let message = format ! ( r#"{{"text": "{}"}}"# , self . summary) ;
255
-
256
- let output = Command :: new ( "curl" )
257
- . arg ( "-X" )
258
- . arg ( "POST" )
259
- . arg ( "-H" )
260
- . arg ( "Content-Type: application/json" )
261
- . arg ( "-d" )
262
- . arg ( message)
263
- . arg ( & self . google_chat_url )
264
- . output ( )
265
- . expect ( "Failed to execute curl" ) ;
266
-
267
- if output. status . success ( ) {
268
- println ! ( "Message sent successfully to google chat!" ) ;
269
- } else {
270
- println ! ( "Failed to send message." ) ;
274
+ self . google_chat ( & self . summary ) ;
275
+ if self . infected_files != "" {
276
+ self . infected_files . push_str ( & format ! ( "\n Result Output: {}\n " , self . tmp_file) ) ;
277
+ self . google_chat ( & self . infected_files ) ;
271
278
}
272
279
}
273
280
}
274
281
275
- // fn generate_random_file_name() -> String {
276
- // let mut rng = rand::thread_rng();
277
- // let random_string: String = (0..10)
278
- // .map(|_| rng.sample(rand::distributions::Alphanumeric) as char)
279
- // .collect();
280
- // format!("/tmp/{}.txt", random_string)
281
- // }
282
+ fn google_chat ( & self , message : & String ) {
283
+ let send_message = format ! ( r#"{{"text": "{}"}}"# , message) ;
284
+
285
+ let output = Command :: new ( "curl" )
286
+ . arg ( "-X" )
287
+ . arg ( "POST" )
288
+ . arg ( "-H" )
289
+ . arg ( "Content-Type: application/json" )
290
+ . arg ( "-d" )
291
+ . arg ( send_message)
292
+ . arg ( & self . google_chat_url )
293
+ . output ( )
294
+ . expect ( "Failed to execute curl" ) ;
295
+
296
+ if output. status . success ( ) {
297
+ println ! ( "Message sent successfully to google chat!" ) ;
298
+ } else {
299
+ println ! ( "Failed to send message." ) ;
300
+ }
301
+ }
282
302
303
+ pub fn save_infected_file_on_temp ( & self ) {
304
+ let mut output = File :: create ( & self . tmp_file ) . unwrap ( ) ;
305
+
306
+ write ! ( output, "{}" , self . summary) . unwrap ( ) ;
307
+ if self . infected_files != "" {
308
+ write ! ( output, "{}" , self . infected_files) . unwrap ( ) ;
309
+ }
310
+ }
283
311
284
312
}
0 commit comments