1use regex::Regex;
2use serde::{Deserialize, Serialize};
3use std::fs;
4use walkdir::WalkDir;
5
6#[derive(Debug, Deserialize, Serialize)]
7pub struct Signature {
8 pub signature: String,
9 pub filetypes: Vec<String>,
10 pub description: String,
11}
12
13#[derive(Debug)]
14pub struct MatchResult {
15 pub id: usize,
16 pub file: String,
17 pub filetype: String,
18 pub search: String,
19 pub match_str: String,
20 pub hits: String,
21 pub line: usize,
22}
23
24pub fn find_matches(signatures: Vec<Signature>, directory: &str) -> Vec<MatchResult> {
25 let mut matches = Vec::new();
26 let mut id_counter = 1;
27
28 for entry in WalkDir::new(directory) {
29 let entry = entry.unwrap();
30 let path = entry.path();
31 let extension = path
32 .extension()
33 .unwrap_or_default()
34 .to_str()
35 .unwrap_or_default();
36
37 if !signatures
38 .iter()
39 .any(|s| s.filetypes.contains(&extension.to_string()))
40 {
41 continue;
42 }
43 let content = fs::read_to_string(path).unwrap();
44 for signature in &signatures {
45 if !signature.filetypes.contains(&extension.to_string()) {
46 continue;
47 }
48 let regex = Regex::new(&signature.signature).unwrap();
49 for (i, line) in content.lines().enumerate() {
50 for capture in regex.captures_iter(line) {
51 let match_str = capture.get(0).unwrap().as_str().to_string();
52 let result = MatchResult {
53 id: id_counter,
54 file: path.to_str().unwrap_or_default().to_string(),
55 filetype: extension.to_string(),
56 search: signature.signature.to_string(),
57 hits: line.to_string(),
58 match_str,
59 line: i + 1,
60 };
61 matches.push(result);
62 id_counter += 1;
63 }
64 }
65 }
66 }
67
68 matches
69}