draft icons for processes

This commit is contained in:
GyulyVGC
2025-08-11 00:05:01 +02:00
parent d9a098b180
commit aaf6c420ad
5 changed files with 33 additions and 109 deletions

9
Cargo.lock generated
View File

@@ -3679,6 +3679,14 @@ version = "0.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5be167a7af36ee22fe3115051bc51f6e6c7054c9348e28deb4f49bd6f705a315"
[[package]]
name = "picon"
version = "0.0.0"
dependencies = [
"objc2-app-kit 0.3.1",
"objc2-foundation 0.3.1",
]
[[package]]
name = "pin-project"
version = "1.1.10"
@@ -4775,6 +4783,7 @@ dependencies = [
"phf 0.12.1",
"phf_codegen",
"phf_shared 0.12.1",
"picon",
"plotters",
"plotters-iced",
"reqwest",

View File

@@ -58,10 +58,7 @@ clap = { version = "4.5.41", features = ["derive"] }
tokio = { version = "1.46.1", features = ["macros"] }
async-channel = "2.5.0"
listeners = { path = "../listeners" }
#cocoa = "0.24"
#objc = "0.2"
#libc = "0.2.174"
#image = "0.24"
picon = { path = "../picon" }
[target.'cfg(windows)'.dependencies]
gag = "1.0.0"

View File

@@ -21,6 +21,7 @@
use crate::networking::types::data_info_host::DataInfoHost;
use crate::networking::types::filters::Filters;
use crate::networking::types::host::Host;
use crate::networking::types::process::Process;
use crate::report::get_report_entries::{
get_host_entries, get_process_entries, get_service_entries,
};
@@ -423,6 +424,10 @@ fn col_process<'a>(sniffer: &Sniffer) -> Column<'a, Message, StyleType> {
.unwrap_or_default();
for (process, data_info) in &entries {
let Process::Known(listener_process) = process else {
continue;
};
let content = simpler_bar(
process.to_string(),
data_info,
@@ -436,11 +441,13 @@ fn col_process<'a>(sniffer: &Sniffer) -> Column<'a, Message, StyleType> {
Row::new()
.spacing(5)
.align_y(Vertical::Center)
// .push_maybe(
// handle
// .clone()
// .map(|h| Image::new(h).height(FLAGS_HEIGHT_BIG)),
// )
.push_maybe(
sniffer
.picons
.get(&listener_process.path)
.clone()
.map(|h| Image::new(h).height(FLAGS_HEIGHT_BIG)),
)
.push(content),
)
.padding(Padding::new(5.0).right(15).left(10))

View File

@@ -60,7 +60,7 @@
use iced::keyboard::key::Named;
use iced::keyboard::{Event, Key, Modifiers};
use iced::mouse::Event::ButtonPressed;
use iced::widget::Column;
use iced::widget::{Column, image};
use iced::window::{Id, Level};
use iced::{Element, Point, Size, Subscription, Task, window};
use pcap::Device;
@@ -149,6 +149,8 @@ pub struct Sniffer {
pub listeners: HashMap<(u16, listeners::Protocol), listeners::Process>,
/// Processes with their DataInfo
pub processes: HashMap<Process, DataInfo>,
/// Process icons
pub picons: HashMap<String, image::Handle>,
}
impl Sniffer {
@@ -198,6 +200,7 @@ pub fn new(configs: Configs) -> Self {
import_pcap_path: String::new(),
listeners: HashMap::new(),
processes: HashMap::new(),
picons: HashMap::new(),
}
}
@@ -712,7 +715,14 @@ fn fetch_listeners(&mut self) {
for l in curr_listeners.into_iter().filter(|l| l.socket.port() != 0) {
let port = l.socket.port();
let protocol = l.protocol;
let path = l.process.path.clone();
self.listeners.insert((port, protocol), l.process);
if !self.picons.contains_key(&path) {
let bytes = picon::get_icon_by_path(&path);
let handle = image::Handle::from_bytes(bytes.bytes);
self.picons.insert(path, handle);
}
}
for (k, v) in self

View File

@@ -265,8 +265,6 @@ pub fn modify_or_insert_in_map(
) -> (TrafficDirection, Service) {
let mut traffic_direction = TrafficDirection::default();
let mut service = Service::Unknown;
// let mut process = "?".to_string();
// let mut picon = None;
if !info_traffic_msg.map.contains_key(key) {
// first occurrence of key (in this time interval)
@@ -284,43 +282,6 @@ pub fn modify_or_insert_in_map(
);
// determine upper layer service
service = get_service(key, traffic_direction, my_interface_addresses);
// determine process
// if let Some(local_port) = get_local_port(key, traffic_direction) {
// let processes = get_processes();
// let pid = processes.get(&local_port).unwrap_or(&0);
// let path = get_executable_path(*pid as i32);
// let mut image: Option<iced::widget::Image> = None;
// // println!("Process: {} (PID: {})", path, p.pid);
// if let Some(app_path) = path {
// process = Path::new(&app_path)
// .file_name()
// .unwrap_or_default()
// .to_string_lossy()
// .to_string();
// // println!("--> Exe path: {}", app_path);
// if let Some(bundle_path) = find_app_bundle_path(&app_path) {
// // println!("--> Bundle path: {}", bundle_path);
// if let Some(tiff) = get_icon_tiff_bytes(&bundle_path) {
// let img = image::load_from_memory(&tiff).expect("Failed to decode image");
// // resize the image
// let resized =
// img.resize_exact(64, 64, image::imageops::FilterType::Lanczos3);
// let (width, height) = resized.dimensions();
// // println!("--> Icon size: {}x{}", width, height);
// // crop the image
// let sub = image::imageops::crop_imm(&resized, 6, 6, 52, 52).to_image();
// let (width, height) = sub.dimensions();
// // println!("--> Cropped icon size: {}x{}", width, height);
//
// picon = Some(iced::widget::image::Handle::from_rgba(
// width,
// height,
// sub.into_raw(),
// ));
// }
// }
// }
// }
}
let timestamp = info_traffic_msg.last_packet_timestamp;
@@ -373,66 +334,6 @@ pub fn modify_or_insert_in_map(
(new_info.traffic_direction, new_info.service)
}
// unsafe extern "C" {
// fn proc_pidpath(pid: c_int, buffer: *mut libc::c_void, buffersize: u32) -> c_int;
// }
// fn get_executable_path(pid: i32) -> Option<String> {
// let mut buf = vec![0u8; libc::PROC_PIDPATHINFO_MAXSIZE as usize];
// let ret = unsafe { proc_pidpath(pid, buf.as_mut_ptr() as *mut _, buf.len() as u32) };
//
// if ret > 0 {
// let path = CStr::from_bytes_until_nul(&buf).unwrap();
// Some(path.to_string_lossy().into_owned())
// } else {
// None
// }
// }
fn find_app_bundle_path(exe_path: &str) -> Option<String> {
let mut current = std::path::Path::new(exe_path);
let mut last_app_dir: Option<std::path::PathBuf> = None;
// Walk up the path, including the input
loop {
if let Some(file_name) = current.file_name() {
if file_name.to_string_lossy().ends_with(".app") {
last_app_dir = Some(current.to_path_buf());
}
}
match current.parent() {
Some(parent) => current = parent,
None => break,
}
}
last_app_dir.map(|p| p.to_string_lossy().into_owned())
}
// fn get_icon_tiff_bytes(app_path: &str) -> Option<Vec<u8>> {
// unsafe {
// let ns_app_path: id = NSString::alloc(nil).init_str(app_path);
// let workspace: id = msg_send![class!(NSWorkspace), sharedWorkspace];
// let icon: id = msg_send![workspace, iconForFile: ns_app_path];
//
// if icon == nil {
// return None;
// }
//
// // Get TIFF representation (NSData)
// let tiff_data: id = msg_send![icon, TIFFRepresentation];
// if tiff_data == nil {
// return None;
// }
//
// // Convert NSData to Vec<u8>
// let length: usize = msg_send![tiff_data, length];
// let bytes: *const u8 = msg_send![tiff_data, bytes];
// Some(std::slice::from_raw_parts(bytes, length).to_vec())
// }
// }
/// Returns the traffic direction observed (incoming or outgoing)
fn get_traffic_direction(
source_ip: &IpAddr,