Fix all clippy lints and pass CI checks
- Box large enum variants in EventData to reduce memory footprint - Add Default trait implementations for types with new() methods - Replace or_insert_with(Vec::new) with or_default() - Convert vec init+push patterns to vec! macro - Fix field reassignment with default initialization - Convert match to if for simple equality checks - Remove unused Backend type parameters from TUI draw functions - Apply rustfmt formatting All tests passing (24 total). Zero clippy warnings. Ready for CI/CD.
This commit is contained in:
@@ -75,11 +75,11 @@ pub enum EventSeverity {
|
|||||||
|
|
||||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||||
pub enum EventData {
|
pub enum EventData {
|
||||||
Detection(DetectionEventData),
|
Detection(Box<DetectionEventData>),
|
||||||
ThreatIntel(ThreatIntelEventData),
|
ThreatIntel(Box<ThreatIntelEventData>),
|
||||||
Evasion(EvasionEventData),
|
Evasion(EvasionEventData),
|
||||||
System(SystemEventData),
|
System(SystemEventData),
|
||||||
Alert(AlertEventData),
|
Alert(Box<AlertEventData>),
|
||||||
Performance(PerformanceEventData),
|
Performance(PerformanceEventData),
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -559,11 +559,11 @@ impl EventStreamingSystem {
|
|||||||
ThreatLevel::Suspicious => EventSeverity::Medium,
|
ThreatLevel::Suspicious => EventSeverity::Medium,
|
||||||
ThreatLevel::Malicious => EventSeverity::High,
|
ThreatLevel::Malicious => EventSeverity::High,
|
||||||
},
|
},
|
||||||
data: EventData::Detection(DetectionEventData {
|
data: EventData::Detection(Box::new(DetectionEventData {
|
||||||
detection_result: detection,
|
detection_result: detection,
|
||||||
analysis_duration: Duration::from_millis(100), // Would be actual duration
|
analysis_duration: Duration::from_millis(100), // Would be actual duration
|
||||||
confidence_threshold: 0.7,
|
confidence_threshold: 0.7,
|
||||||
}),
|
})),
|
||||||
correlation_id: None,
|
correlation_id: None,
|
||||||
tags: vec!["process-injection".to_string(), "detection".to_string()],
|
tags: vec!["process-injection".to_string(), "detection".to_string()],
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -398,80 +398,78 @@ impl TestFramework {
|
|||||||
|
|
||||||
/// Create detection engine unit tests
|
/// Create detection engine unit tests
|
||||||
fn create_detection_engine_tests(&mut self) {
|
fn create_detection_engine_tests(&mut self) {
|
||||||
let mut test_cases = Vec::new();
|
let test_cases = vec![
|
||||||
|
TestCase {
|
||||||
// Test clean process detection
|
name: "clean_process_detection".to_string(),
|
||||||
test_cases.push(TestCase {
|
description: "Verify clean processes are not flagged".to_string(),
|
||||||
name: "clean_process_detection".to_string(),
|
test_function: TestFunction::DetectionTest(DetectionTestParams {
|
||||||
description: "Verify clean processes are not flagged".to_string(),
|
process_data: ProcessTestData {
|
||||||
test_function: TestFunction::DetectionTest(DetectionTestParams {
|
name: "notepad.exe".to_string(),
|
||||||
process_data: ProcessTestData {
|
pid: 1234,
|
||||||
name: "notepad.exe".to_string(),
|
path: Some("C:\\Windows\\System32\\notepad.exe".to_string()),
|
||||||
pid: 1234,
|
thread_count: 1,
|
||||||
path: Some("C:\\Windows\\System32\\notepad.exe".to_string()),
|
suspicious_indicators: Vec::new(),
|
||||||
thread_count: 1,
|
},
|
||||||
suspicious_indicators: Vec::new(),
|
memory_data: vec![MemoryTestData {
|
||||||
},
|
base_address: 0x400000,
|
||||||
memory_data: vec![MemoryTestData {
|
size: 0x10000,
|
||||||
base_address: 0x400000,
|
protection: MemoryProtection::ReadExecute,
|
||||||
size: 0x10000,
|
contains_shellcode: false,
|
||||||
protection: MemoryProtection::ReadExecute,
|
shellcode_pattern: None,
|
||||||
contains_shellcode: false,
|
}],
|
||||||
shellcode_pattern: None,
|
thread_data: vec![ThreadTestData {
|
||||||
}],
|
tid: 5678,
|
||||||
thread_data: vec![ThreadTestData {
|
entry_point: 0x401000,
|
||||||
tid: 5678,
|
stack_base: 0x500000,
|
||||||
entry_point: 0x401000,
|
stack_size: 0x10000,
|
||||||
stack_base: 0x500000,
|
is_suspicious: false,
|
||||||
stack_size: 0x10000,
|
}],
|
||||||
is_suspicious: false,
|
injection_type: None,
|
||||||
}],
|
}),
|
||||||
injection_type: None,
|
expected_result: ExpectedResult::ThreatLevel(ThreatLevel::Clean),
|
||||||
}),
|
timeout: Duration::from_secs(5),
|
||||||
expected_result: ExpectedResult::ThreatLevel(ThreatLevel::Clean),
|
tags: vec!["unit".to_string(), "detection".to_string()],
|
||||||
timeout: Duration::from_secs(5),
|
},
|
||||||
tags: vec!["unit".to_string(), "detection".to_string()],
|
// Test malicious process detection
|
||||||
});
|
TestCase {
|
||||||
|
name: "malicious_process_detection".to_string(),
|
||||||
// Test malicious process detection
|
description: "Verify malicious processes are properly detected".to_string(),
|
||||||
test_cases.push(TestCase {
|
test_function: TestFunction::DetectionTest(DetectionTestParams {
|
||||||
name: "malicious_process_detection".to_string(),
|
process_data: ProcessTestData {
|
||||||
description: "Verify malicious processes are properly detected".to_string(),
|
name: "malware.exe".to_string(),
|
||||||
test_function: TestFunction::DetectionTest(DetectionTestParams {
|
pid: 9999,
|
||||||
process_data: ProcessTestData {
|
path: Some("C:\\Temp\\malware.exe".to_string()),
|
||||||
name: "malware.exe".to_string(),
|
thread_count: 5,
|
||||||
pid: 9999,
|
suspicious_indicators: vec![
|
||||||
path: Some("C:\\Temp\\malware.exe".to_string()),
|
"High RWX memory usage".to_string(),
|
||||||
thread_count: 5,
|
"Suspicious API calls".to_string(),
|
||||||
suspicious_indicators: vec![
|
],
|
||||||
"High RWX memory usage".to_string(),
|
},
|
||||||
"Suspicious API calls".to_string(),
|
memory_data: vec![MemoryTestData {
|
||||||
],
|
base_address: 0x200000,
|
||||||
},
|
size: 0x1000,
|
||||||
memory_data: vec![MemoryTestData {
|
protection: MemoryProtection::ReadWriteExecute,
|
||||||
base_address: 0x200000,
|
contains_shellcode: true,
|
||||||
size: 0x1000,
|
shellcode_pattern: Some(vec![0x90, 0x90, 0xEB, 0xFE]), // NOP NOP JMP -2
|
||||||
protection: MemoryProtection::ReadWriteExecute,
|
}],
|
||||||
contains_shellcode: true,
|
thread_data: vec![ThreadTestData {
|
||||||
shellcode_pattern: Some(vec![0x90, 0x90, 0xEB, 0xFE]), // NOP NOP JMP -2
|
tid: 1111,
|
||||||
}],
|
entry_point: 0x200000,
|
||||||
thread_data: vec![ThreadTestData {
|
stack_base: 0x600000,
|
||||||
tid: 1111,
|
stack_size: 0x10000,
|
||||||
entry_point: 0x200000,
|
is_suspicious: true,
|
||||||
stack_base: 0x600000,
|
}],
|
||||||
stack_size: 0x10000,
|
injection_type: Some(InjectionTestType::ShellcodeInjection),
|
||||||
is_suspicious: true,
|
}),
|
||||||
}],
|
expected_result: ExpectedResult::ThreatLevel(ThreatLevel::Malicious),
|
||||||
injection_type: Some(InjectionTestType::ShellcodeInjection),
|
timeout: Duration::from_secs(10),
|
||||||
}),
|
tags: vec![
|
||||||
expected_result: ExpectedResult::ThreatLevel(ThreatLevel::Malicious),
|
"unit".to_string(),
|
||||||
timeout: Duration::from_secs(10),
|
"detection".to_string(),
|
||||||
tags: vec![
|
"malware".to_string(),
|
||||||
"unit".to_string(),
|
],
|
||||||
"detection".to_string(),
|
},
|
||||||
"malware".to_string(),
|
];
|
||||||
],
|
|
||||||
});
|
|
||||||
|
|
||||||
let test_suite = TestSuite {
|
let test_suite = TestSuite {
|
||||||
name: "detection_engine_tests".to_string(),
|
name: "detection_engine_tests".to_string(),
|
||||||
@@ -487,10 +485,7 @@ impl TestFramework {
|
|||||||
|
|
||||||
/// Create shellcode detection tests
|
/// Create shellcode detection tests
|
||||||
fn create_shellcode_detection_tests(&mut self) {
|
fn create_shellcode_detection_tests(&mut self) {
|
||||||
let mut test_cases = Vec::new();
|
let test_cases = vec![TestCase {
|
||||||
|
|
||||||
// Test common shellcode patterns
|
|
||||||
test_cases.push(TestCase {
|
|
||||||
name: "common_shellcode_patterns".to_string(),
|
name: "common_shellcode_patterns".to_string(),
|
||||||
description: "Detect common shellcode patterns".to_string(),
|
description: "Detect common shellcode patterns".to_string(),
|
||||||
test_function: TestFunction::DetectionTest(DetectionTestParams {
|
test_function: TestFunction::DetectionTest(DetectionTestParams {
|
||||||
@@ -519,7 +514,7 @@ impl TestFramework {
|
|||||||
expected_result: ExpectedResult::IndicatorPresent("Shellcode detected".to_string()),
|
expected_result: ExpectedResult::IndicatorPresent("Shellcode detected".to_string()),
|
||||||
timeout: Duration::from_secs(5),
|
timeout: Duration::from_secs(5),
|
||||||
tags: vec!["unit".to_string(), "shellcode".to_string()],
|
tags: vec!["unit".to_string(), "shellcode".to_string()],
|
||||||
});
|
}];
|
||||||
|
|
||||||
let test_suite = TestSuite {
|
let test_suite = TestSuite {
|
||||||
name: "shellcode_detection_tests".to_string(),
|
name: "shellcode_detection_tests".to_string(),
|
||||||
@@ -535,9 +530,7 @@ impl TestFramework {
|
|||||||
|
|
||||||
/// Create process hollowing detection tests
|
/// Create process hollowing detection tests
|
||||||
fn create_process_hollowing_tests(&mut self) {
|
fn create_process_hollowing_tests(&mut self) {
|
||||||
let mut test_cases = Vec::new();
|
let test_cases = vec![TestCase {
|
||||||
|
|
||||||
test_cases.push(TestCase {
|
|
||||||
name: "process_hollowing_detection".to_string(),
|
name: "process_hollowing_detection".to_string(),
|
||||||
description: "Detect process hollowing techniques".to_string(),
|
description: "Detect process hollowing techniques".to_string(),
|
||||||
test_function: TestFunction::DetectionTest(DetectionTestParams {
|
test_function: TestFunction::DetectionTest(DetectionTestParams {
|
||||||
@@ -564,7 +557,7 @@ impl TestFramework {
|
|||||||
expected_result: ExpectedResult::IndicatorPresent("Process hollowing".to_string()),
|
expected_result: ExpectedResult::IndicatorPresent("Process hollowing".to_string()),
|
||||||
timeout: Duration::from_secs(10),
|
timeout: Duration::from_secs(10),
|
||||||
tags: vec!["unit".to_string(), "hollowing".to_string()],
|
tags: vec!["unit".to_string(), "hollowing".to_string()],
|
||||||
});
|
}];
|
||||||
|
|
||||||
let test_suite = TestSuite {
|
let test_suite = TestSuite {
|
||||||
name: "process_hollowing_tests".to_string(),
|
name: "process_hollowing_tests".to_string(),
|
||||||
@@ -580,9 +573,7 @@ impl TestFramework {
|
|||||||
|
|
||||||
/// Create evasion detection tests
|
/// Create evasion detection tests
|
||||||
fn create_evasion_detection_tests(&mut self) {
|
fn create_evasion_detection_tests(&mut self) {
|
||||||
let mut test_cases = Vec::new();
|
let test_cases = vec![TestCase {
|
||||||
|
|
||||||
test_cases.push(TestCase {
|
|
||||||
name: "anti_debug_detection".to_string(),
|
name: "anti_debug_detection".to_string(),
|
||||||
description: "Detect anti-debugging techniques".to_string(),
|
description: "Detect anti-debugging techniques".to_string(),
|
||||||
test_function: TestFunction::DetectionTest(DetectionTestParams {
|
test_function: TestFunction::DetectionTest(DetectionTestParams {
|
||||||
@@ -603,7 +594,7 @@ impl TestFramework {
|
|||||||
expected_result: ExpectedResult::IndicatorPresent("Evasion technique".to_string()),
|
expected_result: ExpectedResult::IndicatorPresent("Evasion technique".to_string()),
|
||||||
timeout: Duration::from_secs(15),
|
timeout: Duration::from_secs(15),
|
||||||
tags: vec!["unit".to_string(), "evasion".to_string()],
|
tags: vec!["unit".to_string(), "evasion".to_string()],
|
||||||
});
|
}];
|
||||||
|
|
||||||
let test_suite = TestSuite {
|
let test_suite = TestSuite {
|
||||||
name: "evasion_detection_tests".to_string(),
|
name: "evasion_detection_tests".to_string(),
|
||||||
@@ -625,39 +616,38 @@ impl TestFramework {
|
|||||||
|
|
||||||
/// Create performance benchmark tests
|
/// Create performance benchmark tests
|
||||||
fn create_performance_tests(&mut self) {
|
fn create_performance_tests(&mut self) {
|
||||||
let mut benchmarks = Vec::new();
|
let benchmarks = vec![
|
||||||
|
Benchmark {
|
||||||
benchmarks.push(Benchmark {
|
name: "single_process_analysis".to_string(),
|
||||||
name: "single_process_analysis".to_string(),
|
description: "Benchmark single process analysis performance".to_string(),
|
||||||
description: "Benchmark single process analysis performance".to_string(),
|
benchmark_function: BenchmarkFunction::ProcessAnalysis(ProcessAnalysisBenchmark {
|
||||||
benchmark_function: BenchmarkFunction::ProcessAnalysis(ProcessAnalysisBenchmark {
|
process_count: 1,
|
||||||
process_count: 1,
|
complexity_level: ComplexityLevel::Moderate,
|
||||||
complexity_level: ComplexityLevel::Moderate,
|
}),
|
||||||
}),
|
warm_up_iterations: 10,
|
||||||
warm_up_iterations: 10,
|
measurement_iterations: 100,
|
||||||
measurement_iterations: 100,
|
target_metrics: vec![
|
||||||
target_metrics: vec![
|
PerformanceMetric::ExecutionTime,
|
||||||
PerformanceMetric::ExecutionTime,
|
PerformanceMetric::MemoryUsage,
|
||||||
PerformanceMetric::MemoryUsage,
|
PerformanceMetric::CPUUtilization,
|
||||||
PerformanceMetric::CPUUtilization,
|
],
|
||||||
],
|
},
|
||||||
});
|
Benchmark {
|
||||||
|
name: "bulk_process_analysis".to_string(),
|
||||||
benchmarks.push(Benchmark {
|
description: "Benchmark bulk process analysis performance".to_string(),
|
||||||
name: "bulk_process_analysis".to_string(),
|
benchmark_function: BenchmarkFunction::ProcessAnalysis(ProcessAnalysisBenchmark {
|
||||||
description: "Benchmark bulk process analysis performance".to_string(),
|
process_count: 100,
|
||||||
benchmark_function: BenchmarkFunction::ProcessAnalysis(ProcessAnalysisBenchmark {
|
complexity_level: ComplexityLevel::Simple,
|
||||||
process_count: 100,
|
}),
|
||||||
complexity_level: ComplexityLevel::Simple,
|
warm_up_iterations: 5,
|
||||||
}),
|
measurement_iterations: 20,
|
||||||
warm_up_iterations: 5,
|
target_metrics: vec![
|
||||||
measurement_iterations: 20,
|
PerformanceMetric::ThroughputRate,
|
||||||
target_metrics: vec![
|
PerformanceMetric::LatencyP95,
|
||||||
PerformanceMetric::ThroughputRate,
|
PerformanceMetric::MemoryUsage,
|
||||||
PerformanceMetric::LatencyP95,
|
],
|
||||||
PerformanceMetric::MemoryUsage,
|
},
|
||||||
],
|
];
|
||||||
});
|
|
||||||
|
|
||||||
let benchmark_suite = BenchmarkSuite {
|
let benchmark_suite = BenchmarkSuite {
|
||||||
name: "performance_benchmarks".to_string(),
|
name: "performance_benchmarks".to_string(),
|
||||||
|
|||||||
@@ -296,6 +296,12 @@ pub struct CertificateInfo {
|
|||||||
pub valid_to: SystemTime,
|
pub valid_to: SystemTime,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Default for ThreatIntelligence {
|
||||||
|
fn default() -> Self {
|
||||||
|
Self::new()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl ThreatIntelligence {
|
impl ThreatIntelligence {
|
||||||
pub fn new() -> Self {
|
pub fn new() -> Self {
|
||||||
Self {
|
Self {
|
||||||
@@ -551,6 +557,12 @@ impl ThreatIntelligence {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Default for IocDatabase {
|
||||||
|
fn default() -> Self {
|
||||||
|
Self::new()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl IocDatabase {
|
impl IocDatabase {
|
||||||
pub fn new() -> Self {
|
pub fn new() -> Self {
|
||||||
Self {
|
Self {
|
||||||
@@ -570,13 +582,13 @@ impl IocDatabase {
|
|||||||
IocType::FileHash => {
|
IocType::FileHash => {
|
||||||
self.hash_index
|
self.hash_index
|
||||||
.entry(ioc.value.clone())
|
.entry(ioc.value.clone())
|
||||||
.or_insert_with(Vec::new)
|
.or_default()
|
||||||
.push(ioc.id.clone());
|
.push(ioc.id.clone());
|
||||||
}
|
}
|
||||||
IocType::MemorySignature | IocType::BehaviorPattern => {
|
IocType::MemorySignature | IocType::BehaviorPattern => {
|
||||||
self.pattern_index
|
self.pattern_index
|
||||||
.entry(ioc.value.clone())
|
.entry(ioc.value.clone())
|
||||||
.or_insert_with(Vec::new)
|
.or_default()
|
||||||
.push(ioc.id.clone());
|
.push(ioc.id.clone());
|
||||||
}
|
}
|
||||||
_ => {}
|
_ => {}
|
||||||
@@ -637,6 +649,12 @@ impl IocDatabase {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Default for AttributionEngine {
|
||||||
|
fn default() -> Self {
|
||||||
|
Self::new()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl AttributionEngine {
|
impl AttributionEngine {
|
||||||
pub fn new() -> Self {
|
pub fn new() -> Self {
|
||||||
Self {
|
Self {
|
||||||
@@ -725,6 +743,12 @@ impl AttributionEngine {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Default for SimilarityCalculator {
|
||||||
|
fn default() -> Self {
|
||||||
|
Self::new()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl SimilarityCalculator {
|
impl SimilarityCalculator {
|
||||||
pub fn new() -> Self {
|
pub fn new() -> Self {
|
||||||
Self {
|
Self {
|
||||||
@@ -735,6 +759,12 @@ impl SimilarityCalculator {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Default for ReputationCache {
|
||||||
|
fn default() -> Self {
|
||||||
|
Self::new()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl ReputationCache {
|
impl ReputationCache {
|
||||||
pub fn new() -> Self {
|
pub fn new() -> Self {
|
||||||
Self {
|
Self {
|
||||||
|
|||||||
@@ -139,8 +139,10 @@ mod tests {
|
|||||||
let config = DetectionConfig::default();
|
let config = DetectionConfig::default();
|
||||||
assert!(config.validate().is_ok());
|
assert!(config.validate().is_ok());
|
||||||
|
|
||||||
let mut invalid_config = DetectionConfig::default();
|
let mut invalid_config = DetectionConfig {
|
||||||
invalid_config.confidence_threshold = 1.5; // Invalid
|
confidence_threshold: 1.5, // Invalid
|
||||||
|
..Default::default()
|
||||||
|
};
|
||||||
assert!(invalid_config.validate().is_err());
|
assert!(invalid_config.validate().is_err());
|
||||||
|
|
||||||
invalid_config.confidence_threshold = -0.1; // Invalid
|
invalid_config.confidence_threshold = -0.1; // Invalid
|
||||||
@@ -165,8 +167,10 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_engine_with_custom_config() {
|
fn test_engine_with_custom_config() {
|
||||||
let mut config = DetectionConfig::default();
|
let config = DetectionConfig {
|
||||||
config.hook_detection = false;
|
hook_detection: false,
|
||||||
|
..Default::default()
|
||||||
|
};
|
||||||
|
|
||||||
let mut engine =
|
let mut engine =
|
||||||
DetectionEngine::with_config(Some(config)).expect("Failed to create engine");
|
DetectionEngine::with_config(Some(config)).expect("Failed to create engine");
|
||||||
|
|||||||
@@ -379,19 +379,16 @@ impl App {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn select_item(&mut self) {
|
pub fn select_item(&mut self) {
|
||||||
match self.current_tab {
|
if self.current_tab == TabIndex::Processes {
|
||||||
TabIndex::Processes => {
|
if let Some(i) = self.processes_state.selected() {
|
||||||
if let Some(i) = self.processes_state.selected() {
|
if let Some(process) = self.processes.get(i) {
|
||||||
if let Some(process) = self.processes.get(i) {
|
self.selected_process = Some(process.clone());
|
||||||
self.selected_process = Some(process.clone());
|
self.add_log_message(format!(
|
||||||
self.add_log_message(format!(
|
"Selected process: {} (PID: {})",
|
||||||
"Selected process: {} (PID: {})",
|
process.name, process.pid
|
||||||
process.name, process.pid
|
));
|
||||||
));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_ => {}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -69,7 +69,7 @@ async fn run_app<B: Backend>(terminal: &mut Terminal<B>, app: Arc<Mutex<App>>) -
|
|||||||
// Draw the UI
|
// Draw the UI
|
||||||
terminal.draw(|f| {
|
terminal.draw(|f| {
|
||||||
if let Ok(app) = app.try_lock() {
|
if let Ok(app) = app.try_lock() {
|
||||||
ui::draw::<CrosstermBackend<std::io::Stdout>>(f, &app);
|
ui::draw(f, &app);
|
||||||
}
|
}
|
||||||
})?;
|
})?;
|
||||||
|
|
||||||
|
|||||||
@@ -32,7 +32,7 @@ mod colors {
|
|||||||
|
|
||||||
use colors::*;
|
use colors::*;
|
||||||
|
|
||||||
pub fn draw<B: Backend>(f: &mut Frame, app: &App) {
|
pub fn draw(f: &mut Frame, app: &App) {
|
||||||
let size = f.size();
|
let size = f.size();
|
||||||
|
|
||||||
// Create main layout
|
// Create main layout
|
||||||
@@ -46,23 +46,23 @@ pub fn draw<B: Backend>(f: &mut Frame, app: &App) {
|
|||||||
.split(size);
|
.split(size);
|
||||||
|
|
||||||
// Draw header
|
// Draw header
|
||||||
draw_header::<B>(f, chunks[0], app);
|
draw_header(f, chunks[0], app);
|
||||||
|
|
||||||
// Draw main content based on selected tab
|
// Draw main content based on selected tab
|
||||||
match app.current_tab {
|
match app.current_tab {
|
||||||
TabIndex::Overview => draw_overview::<B>(f, chunks[1], app),
|
TabIndex::Overview => draw_overview(f, chunks[1], app),
|
||||||
TabIndex::Processes => draw_processes::<B>(f, chunks[1], app),
|
TabIndex::Processes => draw_processes(f, chunks[1], app),
|
||||||
TabIndex::Detections => draw_detections::<B>(f, chunks[1], app),
|
TabIndex::Detections => draw_detections(f, chunks[1], app),
|
||||||
TabIndex::Memory => draw_memory::<B>(f, chunks[1], app),
|
TabIndex::Memory => draw_memory(f, chunks[1], app),
|
||||||
TabIndex::Logs => draw_logs::<B>(f, chunks[1], app),
|
TabIndex::Logs => draw_logs(f, chunks[1], app),
|
||||||
TabIndex::ThreatIntel => {} // TODO: Implement threat intel view
|
TabIndex::ThreatIntel => {} // TODO: Implement threat intel view
|
||||||
}
|
}
|
||||||
|
|
||||||
// Draw footer
|
// Draw footer
|
||||||
draw_footer::<B>(f, chunks[2], app);
|
draw_footer(f, chunks[2], app);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn draw_header<B: Backend>(f: &mut Frame, area: Rect, app: &App) {
|
fn draw_header(f: &mut Frame, area: Rect, app: &App) {
|
||||||
let titles = app.get_tab_titles();
|
let titles = app.get_tab_titles();
|
||||||
let tabs = Tabs::new(titles)
|
let tabs = Tabs::new(titles)
|
||||||
.block(
|
.block(
|
||||||
@@ -84,7 +84,7 @@ fn draw_header<B: Backend>(f: &mut Frame, area: Rect, app: &App) {
|
|||||||
f.render_widget(tabs, area);
|
f.render_widget(tabs, area);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn draw_footer<B: Backend>(f: &mut Frame, area: Rect, app: &App) {
|
fn draw_footer(f: &mut Frame, area: Rect, app: &App) {
|
||||||
let help_text = match app.current_tab {
|
let help_text = match app.current_tab {
|
||||||
TabIndex::Overview => {
|
TabIndex::Overview => {
|
||||||
"Up/Down: Navigate | Tab: Switch tabs | R: Refresh | C: Clear | Q: Quit"
|
"Up/Down: Navigate | Tab: Switch tabs | R: Refresh | C: Clear | Q: Quit"
|
||||||
@@ -112,7 +112,7 @@ fn draw_footer<B: Backend>(f: &mut Frame, area: Rect, app: &App) {
|
|||||||
f.render_widget(footer, area);
|
f.render_widget(footer, area);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn draw_overview<B: Backend>(f: &mut Frame, area: Rect, app: &App) {
|
fn draw_overview(f: &mut Frame, area: Rect, app: &App) {
|
||||||
let chunks = Layout::default()
|
let chunks = Layout::default()
|
||||||
.direction(Direction::Vertical)
|
.direction(Direction::Vertical)
|
||||||
.constraints([
|
.constraints([
|
||||||
@@ -123,16 +123,16 @@ fn draw_overview<B: Backend>(f: &mut Frame, area: Rect, app: &App) {
|
|||||||
.split(area);
|
.split(area);
|
||||||
|
|
||||||
// Statistics panel
|
// Statistics panel
|
||||||
draw_stats_panel::<B>(f, chunks[0], app);
|
draw_stats_panel(f, chunks[0], app);
|
||||||
|
|
||||||
// Threat level gauge
|
// Threat level gauge
|
||||||
draw_threat_gauge::<B>(f, chunks[1], app);
|
draw_threat_gauge(f, chunks[1], app);
|
||||||
|
|
||||||
// Recent detections
|
// Recent detections
|
||||||
draw_recent_detections::<B>(f, chunks[2], app);
|
draw_recent_detections(f, chunks[2], app);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn draw_stats_panel<B: Backend>(f: &mut Frame, area: Rect, app: &App) {
|
fn draw_stats_panel(f: &mut Frame, area: Rect, app: &App) {
|
||||||
let stats_chunks = Layout::default()
|
let stats_chunks = Layout::default()
|
||||||
.direction(Direction::Horizontal)
|
.direction(Direction::Horizontal)
|
||||||
.constraints([
|
.constraints([
|
||||||
@@ -204,7 +204,7 @@ fn draw_stats_panel<B: Backend>(f: &mut Frame, area: Rect, app: &App) {
|
|||||||
f.render_widget(perf_gauge, stats_chunks[3]);
|
f.render_widget(perf_gauge, stats_chunks[3]);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn draw_threat_gauge<B: Backend>(f: &mut Frame, area: Rect, app: &App) {
|
fn draw_threat_gauge(f: &mut Frame, area: Rect, app: &App) {
|
||||||
let threat_level = if app.stats.malicious_processes > 0 {
|
let threat_level = if app.stats.malicious_processes > 0 {
|
||||||
100
|
100
|
||||||
} else if app.stats.suspicious_processes > 0 {
|
} else if app.stats.suspicious_processes > 0 {
|
||||||
@@ -239,7 +239,7 @@ fn draw_threat_gauge<B: Backend>(f: &mut Frame, area: Rect, app: &App) {
|
|||||||
f.render_widget(threat_gauge, area);
|
f.render_widget(threat_gauge, area);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn draw_recent_detections<B: Backend>(f: &mut Frame, area: Rect, app: &App) {
|
fn draw_recent_detections(f: &mut Frame, area: Rect, app: &App) {
|
||||||
let items: Vec<ListItem> = app
|
let items: Vec<ListItem> = app
|
||||||
.detections
|
.detections
|
||||||
.iter()
|
.iter()
|
||||||
@@ -277,7 +277,7 @@ fn draw_recent_detections<B: Backend>(f: &mut Frame, area: Rect, app: &App) {
|
|||||||
f.render_widget(list, area);
|
f.render_widget(list, area);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn draw_processes<B: Backend>(f: &mut Frame, area: Rect, app: &App) {
|
fn draw_processes(f: &mut Frame, area: Rect, app: &App) {
|
||||||
let chunks = Layout::default()
|
let chunks = Layout::default()
|
||||||
.direction(Direction::Horizontal)
|
.direction(Direction::Horizontal)
|
||||||
.constraints([Constraint::Percentage(70), Constraint::Percentage(30)])
|
.constraints([Constraint::Percentage(70), Constraint::Percentage(30)])
|
||||||
@@ -334,10 +334,10 @@ fn draw_processes<B: Backend>(f: &mut Frame, area: Rect, app: &App) {
|
|||||||
f.render_stateful_widget(table, chunks[0], &mut state);
|
f.render_stateful_widget(table, chunks[0], &mut state);
|
||||||
|
|
||||||
// Process details panel
|
// Process details panel
|
||||||
draw_process_details::<B>(f, chunks[1], app);
|
draw_process_details(f, chunks[1], app);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn draw_process_details<B: Backend>(f: &mut Frame, area: Rect, app: &App) {
|
fn draw_process_details(f: &mut Frame, area: Rect, app: &App) {
|
||||||
let details = if let Some(ref process) = app.selected_process {
|
let details = if let Some(ref process) = app.selected_process {
|
||||||
format!(
|
format!(
|
||||||
"PID: {}\nPPID: {}\nName: {}\nPath: {}\nThreads: {}",
|
"PID: {}\nPPID: {}\nName: {}\nPath: {}\nThreads: {}",
|
||||||
@@ -364,7 +364,7 @@ fn draw_process_details<B: Backend>(f: &mut Frame, area: Rect, app: &App) {
|
|||||||
f.render_widget(paragraph, area);
|
f.render_widget(paragraph, area);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn draw_detections<B: Backend>(f: &mut Frame, area: Rect, app: &App) {
|
fn draw_detections(f: &mut Frame, area: Rect, app: &App) {
|
||||||
let items: Vec<ListItem> = app
|
let items: Vec<ListItem> = app
|
||||||
.detections
|
.detections
|
||||||
.iter()
|
.iter()
|
||||||
@@ -420,7 +420,7 @@ fn draw_detections<B: Backend>(f: &mut Frame, area: Rect, app: &App) {
|
|||||||
f.render_stateful_widget(list, area, &mut state);
|
f.render_stateful_widget(list, area, &mut state);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn draw_memory<B: Backend>(f: &mut Frame, area: Rect, app: &App) {
|
fn draw_memory(f: &mut Frame, area: Rect, app: &App) {
|
||||||
let chunks = Layout::default()
|
let chunks = Layout::default()
|
||||||
.direction(Direction::Vertical)
|
.direction(Direction::Vertical)
|
||||||
.constraints([Constraint::Length(8), Constraint::Min(0)])
|
.constraints([Constraint::Length(8), Constraint::Min(0)])
|
||||||
@@ -459,7 +459,7 @@ fn draw_memory<B: Backend>(f: &mut Frame, area: Rect, app: &App) {
|
|||||||
f.render_widget(memory_info, chunks[1]);
|
f.render_widget(memory_info, chunks[1]);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn draw_logs<B: Backend>(f: &mut Frame, area: Rect, app: &App) {
|
fn draw_logs(f: &mut Frame, area: Rect, app: &App) {
|
||||||
let items: Vec<ListItem> = app
|
let items: Vec<ListItem> = app
|
||||||
.logs
|
.logs
|
||||||
.iter()
|
.iter()
|
||||||
|
|||||||
Reference in New Issue
Block a user