mirror of
https://github.com/GyulyVGC/sniffnet.git
synced 2025-12-23 22:29:01 -05:00
Merge pull request #938 from GyulyVGC/configs
Improve configurations persistence across different runs of the app
This commit is contained in:
@@ -7,6 +7,7 @@ ## [UNRELEASED]
|
||||
- Added _bits_ data representation ([#936](https://github.com/GyulyVGC/sniffnet/pull/936) — fixes [#506](https://github.com/GyulyVGC/sniffnet/issues/506))
|
||||
- An AppImage of Sniffnet is now available ([#859](https://github.com/GyulyVGC/sniffnet/pull/859) — fixes [#900](https://github.com/GyulyVGC/sniffnet/issues/900))
|
||||
- Added Dutch translation 🇳🇱 ([#854](https://github.com/GyulyVGC/sniffnet/pull/854))
|
||||
- Improved configurations persistence across different runs of the app ([#938](https://github.com/GyulyVGC/sniffnet/pull/938) — fixes [#507](https://github.com/GyulyVGC/sniffnet/issues/507))
|
||||
- The Windows Installer is now signed with a code signing certificate provided by the [SignPath Foundation](https://signpath.org/) ([#897](https://github.com/GyulyVGC/sniffnet/pull/897) — fixes [#894](https://github.com/GyulyVGC/sniffnet/issues/894))
|
||||
- Updated some of the existing translations to v1.4:
|
||||
- German ([#833](https://github.com/GyulyVGC/sniffnet/pull/833))
|
||||
|
||||
@@ -1,12 +1,11 @@
|
||||
use crate::SNIFFNET_LOWERCASE;
|
||||
use crate::gui::types::conf::{CONF, Conf};
|
||||
use crate::gui::types::message::Message;
|
||||
use crate::networking::types::capture_context::CaptureSourcePicklist;
|
||||
use crate::utils::formatted_strings::APP_VERSION;
|
||||
use clap::Parser;
|
||||
use iced::{Task, window};
|
||||
|
||||
use crate::CONFIGS;
|
||||
use crate::Configs;
|
||||
use crate::SNIFFNET_LOWERCASE;
|
||||
use crate::gui::types::message::Message;
|
||||
use crate::utils::formatted_strings::APP_VERSION;
|
||||
|
||||
#[derive(Parser, Debug)]
|
||||
#[command(
|
||||
name = SNIFFNET_LOWERCASE,
|
||||
@@ -16,7 +15,7 @@
|
||||
)]
|
||||
struct Args {
|
||||
/// Start sniffing packets from the supplied network adapter
|
||||
#[arg(short, long, value_name = "NAME", default_missing_value = CONFIGS.device.device_name.as_str(), num_args = 0..=1)]
|
||||
#[arg(short, long, value_name = "NAME", default_missing_value = CONF.device.device_name.as_str(), num_args = 0..=1)]
|
||||
adapter: Option<String>,
|
||||
#[cfg(all(windows, not(debug_assertions)))]
|
||||
/// Show the logs (stdout and stderr) of the most recent application run
|
||||
@@ -50,7 +49,7 @@ pub fn handle_cli_args() -> Task<Message> {
|
||||
}
|
||||
|
||||
if args.restore_default {
|
||||
if Configs::default().store().is_ok() {
|
||||
if Conf::default().store().is_ok() {
|
||||
println!("Restored default settings");
|
||||
}
|
||||
std::process::exit(0);
|
||||
@@ -60,7 +59,12 @@ pub fn handle_cli_args() -> Task<Message> {
|
||||
.map(Message::StartApp)
|
||||
.chain(Task::done(Message::Periodic));
|
||||
if let Some(adapter) = args.adapter {
|
||||
// TODO: check if this works once #653 is fixed
|
||||
// currently the link type and device name aren't displayed properly when starting from CLI
|
||||
boot_task_chain = boot_task_chain
|
||||
.chain(Task::done(Message::SetCaptureSource(
|
||||
CaptureSourcePicklist::Device,
|
||||
)))
|
||||
.chain(Task::done(Message::DeviceSelection(adapter)))
|
||||
.chain(Task::done(Message::Start));
|
||||
}
|
||||
@@ -72,21 +76,28 @@ pub fn handle_cli_args() -> Task<Message> {
|
||||
mod tests {
|
||||
use serial_test::serial;
|
||||
|
||||
use crate::configs::types::config_window::{PositionTuple, SizeTuple};
|
||||
use crate::gui::pages::types::running_page::RunningPage;
|
||||
use crate::gui::pages::types::settings_page::SettingsPage;
|
||||
use crate::gui::styles::types::custom_palette::ExtraStyles;
|
||||
use crate::gui::styles::types::gradient_type::GradientType;
|
||||
use crate::gui::types::conf::Conf;
|
||||
use crate::gui::types::config_window::{PositionTuple, SizeTuple};
|
||||
use crate::gui::types::export_pcap::ExportPcap;
|
||||
use crate::gui::types::filters::Filters;
|
||||
use crate::gui::types::settings::Settings;
|
||||
use crate::networking::types::capture_context::CaptureSourcePicklist;
|
||||
use crate::networking::types::config_device::ConfigDevice;
|
||||
use crate::notifications::types::notifications::Notifications;
|
||||
use crate::{ConfigDevice, ConfigSettings, ConfigWindow, Language, Sniffer, StyleType};
|
||||
|
||||
use super::*;
|
||||
use crate::report::types::sort_type::SortType;
|
||||
use crate::{ConfigWindow, Language, Sniffer, StyleType};
|
||||
|
||||
#[test]
|
||||
#[serial]
|
||||
fn test_restore_default_configs() {
|
||||
// initial configs stored are the default ones
|
||||
assert_eq!(Configs::load(), Configs::default());
|
||||
let modified_configs = Configs {
|
||||
settings: ConfigSettings {
|
||||
assert_eq!(Conf::load(), Conf::default());
|
||||
let modified_conf = Conf {
|
||||
settings: Settings {
|
||||
color_gradient: GradientType::Wild,
|
||||
language: Language::ZH,
|
||||
scale_factor: 0.65,
|
||||
@@ -111,19 +122,35 @@ fn test_restore_default_configs() {
|
||||
size: SizeTuple(452.0, 870.0),
|
||||
thumbnail_position: PositionTuple(20.0, 20.0),
|
||||
},
|
||||
capture_source_picklist: CaptureSourcePicklist::File,
|
||||
report_sort_type: SortType::Ascending,
|
||||
host_sort_type: SortType::Descending,
|
||||
service_sort_type: SortType::Neutral,
|
||||
filters: Filters {
|
||||
bpf: "tcp".to_string(),
|
||||
expanded: true,
|
||||
},
|
||||
import_pcap_path: "whole_day.pcapng".to_string(),
|
||||
export_pcap: ExportPcap {
|
||||
enabled: true,
|
||||
file_name: "sniffnet.pcap".to_string(),
|
||||
directory: "home".to_string(),
|
||||
},
|
||||
last_opened_setting: SettingsPage::General,
|
||||
last_opened_page: RunningPage::Inspect,
|
||||
};
|
||||
// we want to be sure that modified config is different from defaults
|
||||
assert_ne!(Configs::default(), modified_configs);
|
||||
assert_ne!(Conf::default(), modified_conf);
|
||||
//store modified configs
|
||||
modified_configs.clone().store().unwrap();
|
||||
modified_conf.clone().store().unwrap();
|
||||
// assert they've been stored
|
||||
assert_eq!(Configs::load(), modified_configs);
|
||||
assert_eq!(Conf::load(), modified_conf);
|
||||
// restore defaults
|
||||
Configs::default().store().unwrap();
|
||||
Conf::default().store().unwrap();
|
||||
// assert that defaults are stored
|
||||
assert_eq!(Configs::load(), Configs::default());
|
||||
assert_eq!(Conf::load(), Conf::default());
|
||||
|
||||
// only needed because it will delete config files via its Drop implementation
|
||||
Sniffer::new(Configs::default());
|
||||
Sniffer::new(Conf::default());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
pub mod types;
|
||||
@@ -1,86 +0,0 @@
|
||||
//! Module defining the `ConfigDevice` struct, which allows to save and reload
|
||||
//! the application default configuration.
|
||||
|
||||
use crate::networking::types::my_device::MyDevice;
|
||||
#[cfg(not(test))]
|
||||
use crate::utils::error_logger::{ErrorLogger, Location};
|
||||
#[cfg(not(test))]
|
||||
use crate::{SNIFFNET_LOWERCASE, location};
|
||||
use pcap::{Device, DeviceFlags};
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
#[derive(Serialize, Deserialize, Clone, PartialEq, Debug)]
|
||||
pub struct ConfigDevice {
|
||||
pub device_name: String,
|
||||
}
|
||||
|
||||
impl Default for ConfigDevice {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
device_name: Device::lookup()
|
||||
.unwrap_or(None)
|
||||
.unwrap_or_else(|| Device {
|
||||
name: String::new(),
|
||||
desc: None,
|
||||
addresses: vec![],
|
||||
flags: DeviceFlags::empty(),
|
||||
})
|
||||
.name,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl ConfigDevice {
|
||||
const FILE_NAME: &'static str = "device";
|
||||
|
||||
#[cfg(not(test))]
|
||||
pub fn load() -> Self {
|
||||
if let Ok(device) = confy::load::<ConfigDevice>(SNIFFNET_LOWERCASE, Self::FILE_NAME) {
|
||||
device
|
||||
} else {
|
||||
let _ = confy::store(SNIFFNET_LOWERCASE, Self::FILE_NAME, ConfigDevice::default())
|
||||
.log_err(location!());
|
||||
ConfigDevice::default()
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(not(test))]
|
||||
pub fn store(self) -> Result<(), confy::ConfyError> {
|
||||
confy::store(SNIFFNET_LOWERCASE, Self::FILE_NAME, self).log_err(location!())
|
||||
}
|
||||
|
||||
pub fn to_my_device(&self) -> MyDevice {
|
||||
for device in Device::list().unwrap_or_default() {
|
||||
if device.name.eq(&self.device_name) {
|
||||
return MyDevice::from_pcap_device(device);
|
||||
}
|
||||
}
|
||||
let standard_device = Device::lookup().unwrap_or(None).unwrap_or_else(|| Device {
|
||||
name: String::new(),
|
||||
desc: None,
|
||||
addresses: vec![],
|
||||
flags: DeviceFlags::empty(),
|
||||
});
|
||||
MyDevice::from_pcap_device(standard_device)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use crate::ConfigDevice;
|
||||
|
||||
impl ConfigDevice {
|
||||
pub fn test_path() -> String {
|
||||
format!("{}/{}.toml", env!("CARGO_MANIFEST_DIR"), Self::FILE_NAME)
|
||||
}
|
||||
|
||||
pub fn load() -> Self {
|
||||
confy::load_path::<ConfigDevice>(ConfigDevice::test_path())
|
||||
.unwrap_or_else(|_| ConfigDevice::default())
|
||||
}
|
||||
|
||||
pub fn store(self) -> Result<(), confy::ConfyError> {
|
||||
confy::store_path(ConfigDevice::test_path(), self)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,84 +0,0 @@
|
||||
//! Module defining the `ConfigSettings` struct, which allows to save and reload
|
||||
//! the application default configuration.
|
||||
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use crate::gui::styles::types::gradient_type::GradientType;
|
||||
use crate::notifications::types::notifications::Notifications;
|
||||
#[cfg(not(test))]
|
||||
use crate::utils::error_logger::{ErrorLogger, Location};
|
||||
use crate::{Language, StyleType};
|
||||
#[cfg(not(test))]
|
||||
use crate::{SNIFFNET_LOWERCASE, location};
|
||||
|
||||
#[derive(Serialize, Deserialize, Clone, PartialEq, Debug)]
|
||||
pub struct ConfigSettings {
|
||||
pub color_gradient: GradientType,
|
||||
pub language: Language,
|
||||
pub scale_factor: f64,
|
||||
pub mmdb_country: String,
|
||||
pub mmdb_asn: String,
|
||||
pub style_path: String,
|
||||
pub notifications: Notifications,
|
||||
// StyleType should be last in order to deserialize as a table properly
|
||||
pub style: StyleType,
|
||||
}
|
||||
|
||||
impl ConfigSettings {
|
||||
const FILE_NAME: &'static str = "settings";
|
||||
|
||||
#[cfg(not(test))]
|
||||
pub fn load() -> Self {
|
||||
if let Ok(settings) = confy::load::<ConfigSettings>(SNIFFNET_LOWERCASE, Self::FILE_NAME) {
|
||||
settings
|
||||
} else {
|
||||
let _ = confy::store(
|
||||
SNIFFNET_LOWERCASE,
|
||||
Self::FILE_NAME,
|
||||
ConfigSettings::default(),
|
||||
)
|
||||
.log_err(location!());
|
||||
ConfigSettings::default()
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(not(test))]
|
||||
pub fn store(self) -> Result<(), confy::ConfyError> {
|
||||
confy::store(SNIFFNET_LOWERCASE, Self::FILE_NAME, self).log_err(location!())
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for ConfigSettings {
|
||||
fn default() -> Self {
|
||||
ConfigSettings {
|
||||
color_gradient: GradientType::default(),
|
||||
language: Language::default(),
|
||||
scale_factor: 1.0,
|
||||
mmdb_country: String::new(),
|
||||
mmdb_asn: String::new(),
|
||||
style_path: String::new(),
|
||||
notifications: Notifications::default(),
|
||||
style: StyleType::default(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use crate::ConfigSettings;
|
||||
|
||||
impl ConfigSettings {
|
||||
pub fn test_path() -> String {
|
||||
format!("{}/{}.toml", env!("CARGO_MANIFEST_DIR"), Self::FILE_NAME)
|
||||
}
|
||||
|
||||
pub fn load() -> Self {
|
||||
confy::load_path::<ConfigSettings>(ConfigSettings::test_path())
|
||||
.unwrap_or_else(|_| ConfigSettings::default())
|
||||
}
|
||||
|
||||
pub fn store(self) -> Result<(), confy::ConfyError> {
|
||||
confy::store_path(ConfigSettings::test_path(), self)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,30 +0,0 @@
|
||||
use crate::{ConfigDevice, ConfigSettings, ConfigWindow};
|
||||
use confy::ConfyError;
|
||||
|
||||
pub static CONFIGS: std::sync::LazyLock<Configs> = std::sync::LazyLock::new(Configs::load);
|
||||
|
||||
#[derive(Default, Clone, PartialEq, Debug)]
|
||||
pub struct Configs {
|
||||
pub settings: ConfigSettings,
|
||||
pub device: ConfigDevice,
|
||||
pub window: ConfigWindow,
|
||||
}
|
||||
|
||||
impl Configs {
|
||||
/// This should only be used directly to load fresh configs;
|
||||
/// use `CONFIGS` instead to access the initial instance
|
||||
pub fn load() -> Self {
|
||||
Configs {
|
||||
settings: ConfigSettings::load(),
|
||||
device: ConfigDevice::load(),
|
||||
window: ConfigWindow::load(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn store(self) -> Result<(), ConfyError> {
|
||||
self.settings.store()?;
|
||||
self.device.store()?;
|
||||
self.window.store()?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
@@ -1,4 +0,0 @@
|
||||
pub mod config_device;
|
||||
pub mod config_settings;
|
||||
pub mod config_window;
|
||||
pub mod configs;
|
||||
@@ -5,15 +5,14 @@
|
||||
use iced::widget::{Container, Row, Space, Text, Tooltip, button, horizontal_space};
|
||||
use iced::{Alignment, Font, Length};
|
||||
|
||||
use crate::configs::types::config_settings::ConfigSettings;
|
||||
use crate::gui::components::tab::notifications_badge;
|
||||
use crate::gui::pages::types::running_page::RunningPage;
|
||||
use crate::gui::pages::types::settings_page::SettingsPage;
|
||||
use crate::gui::sniffer::Sniffer;
|
||||
use crate::gui::styles::button::ButtonType;
|
||||
use crate::gui::styles::container::ContainerType;
|
||||
use crate::gui::styles::types::gradient_type::GradientType;
|
||||
use crate::gui::types::message::Message;
|
||||
use crate::gui::types::settings::Settings;
|
||||
use crate::translations::translations::{quit_analysis_translation, settings_translation};
|
||||
use crate::translations::translations_3::thumbnail_mode_translation;
|
||||
use crate::utils::types::icon::Icon;
|
||||
@@ -21,12 +20,12 @@
|
||||
|
||||
pub fn header(sniffer: &Sniffer) -> Container<'_, Message, StyleType> {
|
||||
let thumbnail = sniffer.thumbnail;
|
||||
let ConfigSettings {
|
||||
let Settings {
|
||||
style,
|
||||
language,
|
||||
color_gradient,
|
||||
..
|
||||
} = sniffer.configs.settings;
|
||||
} = sniffer.conf.settings;
|
||||
let font = style.get_extension().font;
|
||||
|
||||
if thumbnail {
|
||||
@@ -41,8 +40,8 @@ pub fn header(sniffer: &Sniffer) -> Container<'_, Message, StyleType> {
|
||||
);
|
||||
}
|
||||
|
||||
let last_opened_setting = sniffer.last_opened_setting;
|
||||
let is_running = sniffer.running_page.ne(&RunningPage::Init);
|
||||
let last_opened_setting = sniffer.conf.last_opened_setting;
|
||||
let is_running = sniffer.running_page.is_some();
|
||||
|
||||
let logo = Icon::Sniffnet
|
||||
.to_text()
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
use crate::gui::styles::text::TextType;
|
||||
use crate::gui::styles::types::gradient_type::GradientType;
|
||||
use crate::gui::types::message::Message;
|
||||
use crate::gui::types::settings::Settings;
|
||||
use crate::gui::types::timing_events::TimingEvents;
|
||||
use crate::networking::manage_packets::{
|
||||
get_address_to_lookup, get_traffic_type, is_local_connection, is_my_address,
|
||||
@@ -34,7 +35,7 @@
|
||||
};
|
||||
use crate::utils::formatted_strings::{get_formatted_timestamp, get_socket_address};
|
||||
use crate::utils::types::icon::Icon;
|
||||
use crate::{ConfigSettings, Language, Protocol, Sniffer, StyleType};
|
||||
use crate::{Language, Protocol, Sniffer, StyleType};
|
||||
use iced::alignment::Vertical;
|
||||
use iced::widget::scrollable::Direction;
|
||||
use iced::widget::tooltip::Position;
|
||||
@@ -50,12 +51,12 @@ pub fn connection_details_page(
|
||||
}
|
||||
|
||||
fn page_content<'a>(sniffer: &Sniffer, key: &AddressPortPair) -> Container<'a, Message, StyleType> {
|
||||
let ConfigSettings {
|
||||
let Settings {
|
||||
style,
|
||||
language,
|
||||
color_gradient,
|
||||
..
|
||||
} = sniffer.configs.settings;
|
||||
} = sniffer.conf.settings;
|
||||
let data_repr = sniffer.traffic_chart.data_repr;
|
||||
let font = style.get_extension().font;
|
||||
let font_headers = style.get_extension().font_headers;
|
||||
@@ -299,9 +300,9 @@ fn get_local_tooltip<'a>(
|
||||
address_to_lookup: &IpAddr,
|
||||
key: &AddressPortPair,
|
||||
) -> Tooltip<'a, Message, StyleType> {
|
||||
let ConfigSettings {
|
||||
let Settings {
|
||||
style, language, ..
|
||||
} = sniffer.configs.settings;
|
||||
} = sniffer.conf.settings;
|
||||
|
||||
let local_address = if address_to_lookup.eq(&key.address1) {
|
||||
&key.address2
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
use crate::gui::types::export_pcap::ExportPcap;
|
||||
use crate::gui::types::filters::Filters;
|
||||
use crate::gui::types::message::Message;
|
||||
use crate::gui::types::settings::Settings;
|
||||
use crate::networking::types::capture_context::{CaptureSource, CaptureSourcePicklist};
|
||||
use crate::translations::translations::{
|
||||
address_translation, addresses_translation, network_adapter_translation, start_translation,
|
||||
@@ -27,7 +28,7 @@
|
||||
use crate::utils::formatted_strings::get_path_termination_string;
|
||||
use crate::utils::types::file_info::FileInfo;
|
||||
use crate::utils::types::icon::Icon;
|
||||
use crate::{ConfigSettings, Language, StyleType};
|
||||
use crate::{Language, StyleType};
|
||||
use iced::Length::FillPortion;
|
||||
use iced::widget::scrollable::Direction;
|
||||
use iced::widget::{
|
||||
@@ -38,12 +39,12 @@
|
||||
|
||||
/// Computes the body of gui initial page
|
||||
pub fn initial_page(sniffer: &Sniffer) -> Container<'_, Message, StyleType> {
|
||||
let ConfigSettings {
|
||||
let Settings {
|
||||
style,
|
||||
language,
|
||||
color_gradient,
|
||||
..
|
||||
} = sniffer.configs.settings;
|
||||
} = sniffer.conf.settings;
|
||||
let font = style.get_extension().font;
|
||||
let font_headers = style.get_extension().font_headers;
|
||||
|
||||
@@ -51,10 +52,10 @@ pub fn initial_page(sniffer: &Sniffer) -> Container<'_, Message, StyleType> {
|
||||
|
||||
let col_checkboxes = Column::new()
|
||||
.spacing(10)
|
||||
.push(get_filters_group(&sniffer.filters, font, language))
|
||||
.push(get_filters_group(&sniffer.conf.filters, font, language))
|
||||
.push_maybe(get_export_pcap_group_maybe(
|
||||
sniffer.capture_source_picklist,
|
||||
&sniffer.export_pcap,
|
||||
sniffer.conf.capture_source_picklist,
|
||||
&sniffer.conf.export_pcap,
|
||||
language,
|
||||
font,
|
||||
));
|
||||
@@ -113,7 +114,7 @@ fn get_col_data_source(
|
||||
font: Font,
|
||||
language: Language,
|
||||
) -> Column<'_, Message, StyleType> {
|
||||
let current_option = if sniffer.capture_source_picklist == CaptureSourcePicklist::Device {
|
||||
let current_option = if sniffer.conf.capture_source_picklist == CaptureSourcePicklist::Device {
|
||||
network_adapter_translation(language)
|
||||
} else {
|
||||
capture_file_translation(language)
|
||||
@@ -153,7 +154,7 @@ fn get_col_data_source(
|
||||
.push(picklist),
|
||||
);
|
||||
|
||||
match &sniffer.capture_source_picklist {
|
||||
match &sniffer.conf.capture_source_picklist {
|
||||
CaptureSourcePicklist::Device => {
|
||||
col = col.push(get_col_adapter(sniffer, font, language));
|
||||
}
|
||||
@@ -162,7 +163,7 @@ fn get_col_data_source(
|
||||
language,
|
||||
font,
|
||||
&sniffer.capture_source,
|
||||
&sniffer.import_pcap_path,
|
||||
&sniffer.conf.import_pcap_path,
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,6 +21,7 @@
|
||||
use crate::gui::styles::text::TextType;
|
||||
use crate::gui::styles::text_input::TextInputType;
|
||||
use crate::gui::types::message::Message;
|
||||
use crate::gui::types::settings::Settings;
|
||||
use crate::networking::types::address_port_pair::AddressPortPair;
|
||||
use crate::networking::types::data_info::DataInfo;
|
||||
use crate::networking::types::data_representation::DataRepr;
|
||||
@@ -30,19 +31,20 @@
|
||||
use crate::report::get_report_entries::get_searched_entries;
|
||||
use crate::report::types::report_col::ReportCol;
|
||||
use crate::report::types::search_parameters::{FilterInputType, SearchParameters};
|
||||
use crate::report::types::sort_type::SortType;
|
||||
use crate::translations::translations_2::{
|
||||
administrative_entity_translation, country_translation, domain_name_translation,
|
||||
no_search_results_translation, only_show_favorites_translation, showing_results_translation,
|
||||
};
|
||||
use crate::translations::translations_3::filter_by_host_translation;
|
||||
use crate::utils::types::icon::Icon;
|
||||
use crate::{ConfigSettings, Language, ReportSortType, RunningPage, Sniffer, StyleType};
|
||||
use crate::{Language, RunningPage, Sniffer, StyleType};
|
||||
|
||||
/// Computes the body of gui inspect page
|
||||
pub fn inspect_page(sniffer: &Sniffer) -> Container<'_, Message, StyleType> {
|
||||
let ConfigSettings {
|
||||
let Settings {
|
||||
style, language, ..
|
||||
} = sniffer.configs.settings;
|
||||
} = sniffer.conf.settings;
|
||||
let font = style.get_extension().font;
|
||||
let font_headers = style.get_extension().font_headers;
|
||||
|
||||
@@ -74,7 +76,7 @@ pub fn inspect_page(sniffer: &Sniffer) -> Container<'_, Message, StyleType> {
|
||||
language,
|
||||
&sniffer.search,
|
||||
font,
|
||||
sniffer.report_sort_type,
|
||||
sniffer.conf.report_sort_type,
|
||||
sniffer.traffic_chart.data_repr,
|
||||
))
|
||||
.push(Space::with_height(4))
|
||||
@@ -105,9 +107,9 @@ pub fn inspect_page(sniffer: &Sniffer) -> Container<'_, Message, StyleType> {
|
||||
}
|
||||
|
||||
fn report<'a>(sniffer: &Sniffer) -> Column<'a, Message, StyleType> {
|
||||
let ConfigSettings {
|
||||
let Settings {
|
||||
style, language, ..
|
||||
} = sniffer.configs.settings;
|
||||
} = sniffer.conf.settings;
|
||||
let data_repr = sniffer.traffic_chart.data_repr;
|
||||
let font = style.get_extension().font;
|
||||
|
||||
@@ -183,7 +185,7 @@ fn report_header_row(
|
||||
language: Language,
|
||||
search_params: &SearchParameters,
|
||||
font: Font,
|
||||
sort_type: ReportSortType,
|
||||
sort_type: SortType,
|
||||
data_repr: DataRepr,
|
||||
) -> Row<'_, Message, StyleType> {
|
||||
let mut ret_val = Row::new().padding([0, 2]).align_y(Alignment::Center);
|
||||
@@ -269,7 +271,7 @@ fn title_report_col_display(
|
||||
}
|
||||
}
|
||||
|
||||
fn sort_arrows<'a>(active_sort_type: ReportSortType) -> Container<'a, Message, StyleType> {
|
||||
fn sort_arrows<'a>(active_sort_type: SortType) -> Container<'a, Message, StyleType> {
|
||||
Container::new(
|
||||
button(
|
||||
active_sort_type
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
use crate::gui::styles::style_constants::FONT_SIZE_FOOTER;
|
||||
use crate::gui::styles::text::TextType;
|
||||
use crate::gui::types::message::Message;
|
||||
use crate::gui::types::settings::Settings;
|
||||
use crate::networking::types::data_info::DataInfo;
|
||||
use crate::networking::types::data_info_host::DataInfoHost;
|
||||
use crate::networking::types::data_representation::DataRepr;
|
||||
@@ -26,7 +27,7 @@
|
||||
threshold_translation,
|
||||
};
|
||||
use crate::utils::types::icon::Icon;
|
||||
use crate::{ConfigSettings, Language, RunningPage, Sniffer, StyleType};
|
||||
use crate::{Language, RunningPage, Sniffer, StyleType};
|
||||
use iced::Length::FillPortion;
|
||||
use iced::widget::scrollable::Direction;
|
||||
use iced::widget::text::LineHeight;
|
||||
@@ -38,12 +39,12 @@
|
||||
|
||||
/// Computes the body of gui notifications page
|
||||
pub fn notifications_page(sniffer: &Sniffer) -> Container<'_, Message, StyleType> {
|
||||
let ConfigSettings {
|
||||
let Settings {
|
||||
style,
|
||||
language,
|
||||
notifications,
|
||||
..
|
||||
} = sniffer.configs.settings;
|
||||
} = sniffer.conf.settings;
|
||||
let font = style.get_extension().font;
|
||||
let font_headers = style.get_extension().font_headers;
|
||||
|
||||
@@ -282,9 +283,9 @@ fn get_button_clear_all<'a>(font: Font, language: Language) -> Tooltip<'a, Messa
|
||||
}
|
||||
|
||||
fn logged_notifications<'a>(sniffer: &Sniffer) -> Column<'a, Message, StyleType> {
|
||||
let ConfigSettings {
|
||||
let Settings {
|
||||
style, language, ..
|
||||
} = sniffer.configs.settings;
|
||||
} = sniffer.conf.settings;
|
||||
let data_repr = sniffer.traffic_chart.data_repr;
|
||||
let font = style.get_extension().font;
|
||||
let mut ret_val = Column::new()
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
use crate::gui::styles::types::palette_extension::PaletteExtension;
|
||||
use crate::gui::types::filters::Filters;
|
||||
use crate::gui::types::message::Message;
|
||||
use crate::gui::types::settings::Settings;
|
||||
use crate::networking::types::capture_context::CaptureSource;
|
||||
use crate::networking::types::data_info::DataInfo;
|
||||
use crate::networking::types::data_info_host::DataInfoHost;
|
||||
@@ -37,7 +38,7 @@
|
||||
use crate::translations::translations_3::{service_translation, unsupported_link_type_translation};
|
||||
use crate::translations::translations_4::reading_from_pcap_translation;
|
||||
use crate::utils::types::icon::Icon;
|
||||
use crate::{ConfigSettings, Language, RunningPage, StyleType};
|
||||
use crate::{Language, RunningPage, StyleType};
|
||||
use iced::Length::{Fill, FillPortion};
|
||||
use iced::alignment::{Horizontal, Vertical};
|
||||
use iced::widget::scrollable::Direction;
|
||||
@@ -52,66 +53,74 @@
|
||||
|
||||
/// Computes the body of gui overview page
|
||||
pub fn overview_page(sniffer: &Sniffer) -> Container<'_, Message, StyleType> {
|
||||
let ConfigSettings {
|
||||
let Settings {
|
||||
style, language, ..
|
||||
} = sniffer.configs.settings;
|
||||
} = sniffer.conf.settings;
|
||||
let font = style.get_extension().font;
|
||||
let font_headers = style.get_extension().font_headers;
|
||||
|
||||
let mut body = Column::new();
|
||||
let mut tab_and_body = Column::new().height(Length::Fill);
|
||||
|
||||
let dots = &sniffer.dots_pulse.0;
|
||||
// some packets are there!
|
||||
let tabs = get_pages_tabs(
|
||||
RunningPage::Overview,
|
||||
font,
|
||||
font_headers,
|
||||
language,
|
||||
sniffer.unread_notifications,
|
||||
);
|
||||
tab_and_body = tab_and_body.push(tabs);
|
||||
|
||||
if let Some(error) = sniffer.pcap_error.as_ref() {
|
||||
// pcap threw an ERROR!
|
||||
body = body_pcap_error(error, dots, language, font);
|
||||
} else {
|
||||
// NO pcap error detected
|
||||
let tot_packets = sniffer
|
||||
.info_traffic
|
||||
.tot_data_info
|
||||
.tot_data(DataRepr::Packets);
|
||||
let container_chart = container_chart(sniffer, font);
|
||||
|
||||
if tot_packets == 0 {
|
||||
// no packets observed at all
|
||||
body = body_no_packets(&sniffer.capture_source, font, language, dots);
|
||||
} else {
|
||||
// some packets are there!
|
||||
let tabs = get_pages_tabs(
|
||||
RunningPage::Overview,
|
||||
font,
|
||||
font_headers,
|
||||
language,
|
||||
sniffer.unread_notifications,
|
||||
);
|
||||
tab_and_body = tab_and_body.push(tabs);
|
||||
let container_info = col_info(sniffer);
|
||||
|
||||
let container_chart = container_chart(sniffer, font);
|
||||
let container_report = row_report(sniffer);
|
||||
|
||||
let container_info = col_info(sniffer);
|
||||
|
||||
let container_report = row_report(sniffer);
|
||||
|
||||
body = body
|
||||
.width(Length::Fill)
|
||||
.padding(10)
|
||||
body = body
|
||||
.width(Length::Fill)
|
||||
.padding(10)
|
||||
.spacing(10)
|
||||
.align_x(Alignment::Center)
|
||||
.push(
|
||||
Row::new()
|
||||
.height(280)
|
||||
.spacing(10)
|
||||
.align_x(Alignment::Center)
|
||||
.push(
|
||||
Row::new()
|
||||
.height(280)
|
||||
.spacing(10)
|
||||
.push(container_info)
|
||||
.push(container_chart),
|
||||
)
|
||||
.push(container_report);
|
||||
}
|
||||
}
|
||||
.push(container_info)
|
||||
.push(container_chart),
|
||||
)
|
||||
.push(container_report);
|
||||
|
||||
Container::new(Column::new().push(tab_and_body.push(body))).height(Length::Fill)
|
||||
}
|
||||
|
||||
pub fn waiting_page(sniffer: &Sniffer) -> Option<Container<'_, Message, StyleType>> {
|
||||
let Settings {
|
||||
style, language, ..
|
||||
} = sniffer.conf.settings;
|
||||
let font = style.get_extension().font;
|
||||
|
||||
let dots = &sniffer.dots_pulse.0;
|
||||
|
||||
let tot_packets = sniffer
|
||||
.info_traffic
|
||||
.tot_data_info
|
||||
.tot_data(DataRepr::Packets);
|
||||
|
||||
let body = if let Some(error) = sniffer.pcap_error.as_ref() {
|
||||
// pcap threw an ERROR!
|
||||
body_pcap_error(error, dots, language, font)
|
||||
} else if tot_packets == 0 {
|
||||
// no packets observed at all
|
||||
body_no_packets(&sniffer.capture_source, font, language, dots)
|
||||
} else {
|
||||
return None;
|
||||
};
|
||||
|
||||
Some(Container::new(Column::new().push(body)).height(Length::Fill))
|
||||
}
|
||||
|
||||
fn body_no_packets<'a>(
|
||||
cs: &CaptureSource,
|
||||
font: Font,
|
||||
@@ -210,16 +219,20 @@ fn row_report<'a>(sniffer: &Sniffer) -> Row<'a, Message, StyleType> {
|
||||
}
|
||||
|
||||
fn col_host<'a>(sniffer: &Sniffer) -> Column<'a, Message, StyleType> {
|
||||
let ConfigSettings {
|
||||
let Settings {
|
||||
style, language, ..
|
||||
} = sniffer.configs.settings;
|
||||
} = sniffer.conf.settings;
|
||||
let font = style.get_extension().font;
|
||||
let data_repr = sniffer.traffic_chart.data_repr;
|
||||
|
||||
let mut scroll_host = Column::new()
|
||||
.padding(Padding::ZERO.right(11.0))
|
||||
.align_x(Alignment::Center);
|
||||
let entries = get_host_entries(&sniffer.info_traffic, data_repr, sniffer.host_sort_type);
|
||||
let entries = get_host_entries(
|
||||
&sniffer.info_traffic,
|
||||
data_repr,
|
||||
sniffer.conf.host_sort_type,
|
||||
);
|
||||
let first_entry_data_info = entries
|
||||
.iter()
|
||||
.map(|(_, d)| d.data_info)
|
||||
@@ -273,7 +286,7 @@ fn col_host<'a>(sniffer: &Sniffer) -> Column<'a, Message, StyleType> {
|
||||
)
|
||||
.push(horizontal_space())
|
||||
.push(sort_arrows(
|
||||
sniffer.host_sort_type,
|
||||
sniffer.conf.host_sort_type,
|
||||
Message::HostSortSelection,
|
||||
)),
|
||||
)
|
||||
@@ -287,16 +300,20 @@ fn col_host<'a>(sniffer: &Sniffer) -> Column<'a, Message, StyleType> {
|
||||
}
|
||||
|
||||
fn col_service<'a>(sniffer: &Sniffer) -> Column<'a, Message, StyleType> {
|
||||
let ConfigSettings {
|
||||
let Settings {
|
||||
style, language, ..
|
||||
} = sniffer.configs.settings;
|
||||
} = sniffer.conf.settings;
|
||||
let font = style.get_extension().font;
|
||||
let data_repr = sniffer.traffic_chart.data_repr;
|
||||
|
||||
let mut scroll_service = Column::new()
|
||||
.padding(Padding::ZERO.right(11.0))
|
||||
.align_x(Alignment::Center);
|
||||
let entries = get_service_entries(&sniffer.info_traffic, data_repr, sniffer.service_sort_type);
|
||||
let entries = get_service_entries(
|
||||
&sniffer.info_traffic,
|
||||
data_repr,
|
||||
sniffer.conf.service_sort_type,
|
||||
);
|
||||
let first_entry_data_info = entries
|
||||
.iter()
|
||||
.map(|&(_, d)| d)
|
||||
@@ -337,7 +354,7 @@ fn col_service<'a>(sniffer: &Sniffer) -> Column<'a, Message, StyleType> {
|
||||
)
|
||||
.push(horizontal_space())
|
||||
.push(sort_arrows(
|
||||
sniffer.service_sort_type,
|
||||
sniffer.conf.service_sort_type,
|
||||
Message::ServiceSortSelection,
|
||||
)),
|
||||
)
|
||||
@@ -430,12 +447,17 @@ pub fn service_bar<'a>(
|
||||
}
|
||||
|
||||
fn col_info(sniffer: &Sniffer) -> Container<'_, Message, StyleType> {
|
||||
let ConfigSettings {
|
||||
let Settings {
|
||||
style, language, ..
|
||||
} = sniffer.configs.settings;
|
||||
} = sniffer.conf.settings;
|
||||
let PaletteExtension { font, .. } = style.get_extension();
|
||||
|
||||
let col_device = col_device(language, font, &sniffer.capture_source, &sniffer.filters);
|
||||
let col_device = col_device(
|
||||
language,
|
||||
font,
|
||||
&sniffer.capture_source,
|
||||
&sniffer.conf.filters,
|
||||
);
|
||||
|
||||
let col_data_representation =
|
||||
col_data_representation(language, font, sniffer.traffic_chart.data_repr);
|
||||
@@ -469,7 +491,7 @@ fn col_info(sniffer: &Sniffer) -> Container<'_, Message, StyleType> {
|
||||
}
|
||||
|
||||
fn container_chart(sniffer: &Sniffer, font: Font) -> Container<'_, Message, StyleType> {
|
||||
let ConfigSettings { language, .. } = sniffer.configs.settings;
|
||||
let Settings { language, .. } = sniffer.conf.settings;
|
||||
let traffic_chart = &sniffer.traffic_chart;
|
||||
|
||||
Container::new(
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
use crate::gui::styles::style_constants::FONT_SIZE_SUBTITLE;
|
||||
use crate::gui::styles::text::TextType;
|
||||
use crate::gui::types::message::Message;
|
||||
use crate::gui::types::settings::Settings;
|
||||
use crate::mmdb::types::mmdb_reader::{MmdbReader, MmdbReaders};
|
||||
use crate::translations::translations::language_translation;
|
||||
use crate::translations::translations_2::country_translation;
|
||||
@@ -25,15 +26,15 @@
|
||||
use crate::utils::types::file_info::FileInfo;
|
||||
use crate::utils::types::icon::Icon;
|
||||
use crate::utils::types::web_page::WebPage;
|
||||
use crate::{ConfigSettings, Language, RunningPage, Sniffer, StyleType};
|
||||
use crate::{Language, Sniffer, StyleType};
|
||||
|
||||
pub fn settings_general_page(sniffer: &Sniffer) -> Container<'_, Message, StyleType> {
|
||||
let ConfigSettings {
|
||||
let Settings {
|
||||
style,
|
||||
language,
|
||||
color_gradient,
|
||||
..
|
||||
} = sniffer.configs.settings;
|
||||
} = sniffer.conf.settings;
|
||||
let font = style.get_extension().font;
|
||||
let font_headers = style.get_extension().font_headers;
|
||||
|
||||
@@ -57,15 +58,15 @@ pub fn settings_general_page(sniffer: &Sniffer) -> Container<'_, Message, StyleT
|
||||
}
|
||||
|
||||
fn column_all_general_setting(sniffer: &Sniffer, font: Font) -> Column<'_, Message, StyleType> {
|
||||
let ConfigSettings {
|
||||
let Settings {
|
||||
language,
|
||||
scale_factor,
|
||||
mmdb_country,
|
||||
mmdb_asn,
|
||||
..
|
||||
} = sniffer.configs.settings.clone();
|
||||
} = sniffer.conf.settings.clone();
|
||||
|
||||
let is_editable = sniffer.running_page.eq(&RunningPage::Init);
|
||||
let is_editable = sniffer.running_page.is_none();
|
||||
|
||||
let mut column = Column::new()
|
||||
.align_x(Alignment::Center)
|
||||
|
||||
@@ -13,6 +13,7 @@
|
||||
use crate::gui::styles::text::TextType;
|
||||
use crate::gui::styles::types::gradient_type::GradientType;
|
||||
use crate::gui::types::message::Message;
|
||||
use crate::gui::types::settings::Settings;
|
||||
use crate::networking::types::data_representation::DataRepr;
|
||||
use crate::notifications::types::notifications::{
|
||||
DataNotification, FavoriteNotification, Notification,
|
||||
@@ -25,16 +26,16 @@
|
||||
use crate::translations::translations_2::data_representation_translation;
|
||||
use crate::translations::translations_4::data_exceeded_translation;
|
||||
use crate::utils::types::icon::Icon;
|
||||
use crate::{ConfigSettings, Language, Sniffer, StyleType};
|
||||
use crate::{Language, Sniffer, StyleType};
|
||||
|
||||
pub fn settings_notifications_page<'a>(sniffer: &Sniffer) -> Container<'a, Message, StyleType> {
|
||||
let ConfigSettings {
|
||||
let Settings {
|
||||
style,
|
||||
language,
|
||||
color_gradient,
|
||||
mut notifications,
|
||||
..
|
||||
} = sniffer.configs.settings;
|
||||
} = sniffer.conf.settings;
|
||||
let font = style.get_extension().font;
|
||||
let font_headers = style.get_extension().font_headers;
|
||||
|
||||
|
||||
@@ -19,22 +19,23 @@
|
||||
use crate::gui::styles::types::palette::Palette;
|
||||
use crate::gui::styles::types::palette_extension::PaletteExtension;
|
||||
use crate::gui::types::message::Message;
|
||||
use crate::gui::types::settings::Settings;
|
||||
use crate::translations::translations::appearance_title_translation;
|
||||
use crate::translations::translations_2::color_gradients_translation;
|
||||
use crate::translations::translations_3::custom_style_translation;
|
||||
use crate::utils::formatted_strings::get_path_termination_string;
|
||||
use crate::utils::types::file_info::FileInfo;
|
||||
use crate::utils::types::icon::Icon;
|
||||
use crate::{ConfigSettings, Language, Sniffer, StyleType};
|
||||
use crate::{Language, Sniffer, StyleType};
|
||||
|
||||
pub fn settings_style_page(sniffer: &Sniffer) -> Container<'_, Message, StyleType> {
|
||||
let ConfigSettings {
|
||||
let Settings {
|
||||
style,
|
||||
language,
|
||||
color_gradient,
|
||||
style_path,
|
||||
..
|
||||
} = sniffer.configs.settings.clone();
|
||||
} = sniffer.conf.settings.clone();
|
||||
let PaletteExtension {
|
||||
font, font_headers, ..
|
||||
} = style.get_extension();
|
||||
|
||||
@@ -5,12 +5,12 @@
|
||||
use iced::{Alignment, Font, Length};
|
||||
|
||||
use crate::chart::types::donut_chart::donut_chart;
|
||||
use crate::configs::types::config_settings::ConfigSettings;
|
||||
use crate::countries::country_utils::get_flag_tooltip;
|
||||
use crate::gui::sniffer::Sniffer;
|
||||
use crate::gui::styles::style_constants::FONT_SIZE_FOOTER;
|
||||
use crate::gui::styles::types::style_type::StyleType;
|
||||
use crate::gui::types::message::Message;
|
||||
use crate::gui::types::settings::Settings;
|
||||
use crate::networking::types::data_representation::DataRepr;
|
||||
use crate::networking::types::host::{Host, ThumbnailHost};
|
||||
use crate::networking::types::info_traffic::InfoTraffic;
|
||||
@@ -24,7 +24,7 @@
|
||||
|
||||
/// Computes the body of the thumbnail view
|
||||
pub fn thumbnail_page(sniffer: &Sniffer) -> Container<'_, Message, StyleType> {
|
||||
let ConfigSettings { style, .. } = sniffer.configs.settings;
|
||||
let Settings { style, .. } = sniffer.conf.settings;
|
||||
let font = style.get_extension().font;
|
||||
|
||||
let tot_packets = sniffer
|
||||
@@ -75,14 +75,14 @@ pub fn thumbnail_page(sniffer: &Sniffer) -> Container<'_, Message, StyleType> {
|
||||
info_traffic,
|
||||
data_repr,
|
||||
font,
|
||||
sniffer.host_sort_type,
|
||||
sniffer.conf.host_sort_type,
|
||||
))
|
||||
.push(Rule::vertical(10))
|
||||
.push(service_col(
|
||||
info_traffic,
|
||||
data_repr,
|
||||
font,
|
||||
sniffer.service_sort_type,
|
||||
sniffer.conf.service_sort_type,
|
||||
));
|
||||
|
||||
let content = Column::new()
|
||||
|
||||
@@ -3,13 +3,13 @@
|
||||
use crate::translations::translations_2::inspect_translation;
|
||||
use crate::utils::types::icon::Icon;
|
||||
use crate::{Language, StyleType};
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
/// This enum defines the current GUI page.
|
||||
#[derive(PartialEq, Eq, Clone, Copy, Debug)]
|
||||
/// This enum defines the current running page.
|
||||
#[derive(PartialEq, Eq, Clone, Copy, Debug, Serialize, Deserialize, Default)]
|
||||
pub enum RunningPage {
|
||||
/// Initial page.
|
||||
Init,
|
||||
/// Overview page.
|
||||
#[default]
|
||||
Overview,
|
||||
/// Inspect page.
|
||||
Inspect,
|
||||
@@ -29,7 +29,6 @@ pub fn get_tab_label(&self, language: Language) -> &str {
|
||||
RunningPage::Overview => overview_translation(language),
|
||||
RunningPage::Inspect => inspect_translation(language),
|
||||
RunningPage::Notifications => notifications_translation(language),
|
||||
RunningPage::Init => "",
|
||||
}
|
||||
}
|
||||
|
||||
@@ -38,7 +37,6 @@ pub fn next(self) -> Self {
|
||||
RunningPage::Overview => RunningPage::Inspect,
|
||||
RunningPage::Inspect => RunningPage::Notifications,
|
||||
RunningPage::Notifications => RunningPage::Overview,
|
||||
RunningPage::Init => RunningPage::Init,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -47,7 +45,6 @@ pub fn previous(self) -> Self {
|
||||
RunningPage::Overview => RunningPage::Notifications,
|
||||
RunningPage::Inspect => RunningPage::Overview,
|
||||
RunningPage::Notifications => RunningPage::Inspect,
|
||||
RunningPage::Init => RunningPage::Init,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -56,7 +53,6 @@ pub fn icon<'a>(self) -> iced::widget::Text<'a, StyleType> {
|
||||
RunningPage::Overview => Icon::Overview,
|
||||
RunningPage::Inspect => Icon::Inspect,
|
||||
RunningPage::Notifications => Icon::Notification,
|
||||
RunningPage::Init => Icon::Sniffnet,
|
||||
}
|
||||
.to_text()
|
||||
}
|
||||
|
||||
@@ -3,11 +3,13 @@
|
||||
use crate::translations::translations_3::general_translation;
|
||||
use crate::utils::types::icon::Icon;
|
||||
use crate::{Language, StyleType};
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
/// This enum defines the current settings page.
|
||||
#[derive(PartialEq, Eq, Clone, Copy, Debug)]
|
||||
#[derive(PartialEq, Eq, Clone, Copy, Debug, Serialize, Deserialize, Default)]
|
||||
pub enum SettingsPage {
|
||||
/// Settings Notifications page.
|
||||
#[default]
|
||||
Notifications,
|
||||
/// Settings Appearance page.
|
||||
Appearance,
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
87
src/gui/types/conf.rs
Normal file
87
src/gui/types/conf.rs
Normal file
@@ -0,0 +1,87 @@
|
||||
use crate::gui::pages::types::running_page::RunningPage;
|
||||
use crate::gui::pages::types::settings_page::SettingsPage;
|
||||
use crate::gui::types::config_window::ConfigWindow;
|
||||
use crate::gui::types::export_pcap::ExportPcap;
|
||||
use crate::gui::types::filters::Filters;
|
||||
use crate::gui::types::settings::Settings;
|
||||
use crate::networking::types::capture_context::CaptureSourcePicklist;
|
||||
use crate::networking::types::config_device::ConfigDevice;
|
||||
use crate::report::types::sort_type::SortType;
|
||||
#[cfg(not(test))]
|
||||
use crate::utils::error_logger::{ErrorLogger, Location};
|
||||
#[cfg(not(test))]
|
||||
use crate::{SNIFFNET_LOWERCASE, location};
|
||||
#[cfg(not(test))]
|
||||
use confy::ConfyError;
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
pub static CONF: std::sync::LazyLock<Conf> = std::sync::LazyLock::new(Conf::load);
|
||||
|
||||
#[derive(Serialize, Deserialize, Default, Clone, PartialEq, Debug)]
|
||||
#[serde(default)]
|
||||
pub struct Conf {
|
||||
/// Parameters from settings pages
|
||||
pub settings: Settings,
|
||||
/// Last selected network device name
|
||||
pub device: ConfigDevice,
|
||||
/// Window configuration, such as size and position
|
||||
pub window: ConfigWindow,
|
||||
/// Capture source picklist, to select the source of the capture
|
||||
pub capture_source_picklist: CaptureSourcePicklist,
|
||||
/// BPF filter program to be applied to the capture
|
||||
pub filters: Filters,
|
||||
/// Report sort type (inspect page)
|
||||
pub report_sort_type: SortType,
|
||||
/// Host sort type (overview page)
|
||||
pub host_sort_type: SortType,
|
||||
/// Service sort type (overview page)
|
||||
pub service_sort_type: SortType,
|
||||
/// Remembers the last opened setting page
|
||||
pub last_opened_setting: SettingsPage,
|
||||
/// Remembers the last opened running page
|
||||
pub last_opened_page: RunningPage,
|
||||
/// Information about PCAP file export
|
||||
pub export_pcap: ExportPcap,
|
||||
/// Import path for PCAP file
|
||||
pub import_pcap_path: String,
|
||||
}
|
||||
|
||||
impl Conf {
|
||||
const FILE_NAME: &'static str = "conf";
|
||||
|
||||
/// This should only be used directly to load fresh configurations;
|
||||
/// use `CONF` instead to access the initial instance
|
||||
#[cfg(not(test))]
|
||||
pub fn load() -> Self {
|
||||
if let Ok(conf) = confy::load::<Conf>(SNIFFNET_LOWERCASE, Self::FILE_NAME) {
|
||||
conf
|
||||
} else {
|
||||
let _ = Conf::default().store();
|
||||
Conf::default()
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(not(test))]
|
||||
pub fn store(self) -> Result<(), ConfyError> {
|
||||
confy::store(SNIFFNET_LOWERCASE, Self::FILE_NAME, self).log_err(location!())
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use crate::gui::types::conf::Conf;
|
||||
|
||||
impl Conf {
|
||||
pub fn test_path() -> String {
|
||||
format!("{}/{}.toml", env!("CARGO_MANIFEST_DIR"), Self::FILE_NAME)
|
||||
}
|
||||
|
||||
pub fn load() -> Self {
|
||||
confy::load_path::<Conf>(Conf::test_path()).unwrap_or_else(|_| Conf::default())
|
||||
}
|
||||
|
||||
pub fn store(self) -> Result<(), confy::ConfyError> {
|
||||
confy::store_path(Conf::test_path(), self)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,7 +1,3 @@
|
||||
#[cfg(not(test))]
|
||||
use crate::utils::error_logger::{ErrorLogger, Location};
|
||||
#[cfg(not(test))]
|
||||
use crate::{SNIFFNET_LOWERCASE, location};
|
||||
use iced::window::Position;
|
||||
use iced::{Point, Size};
|
||||
use serde::{Deserialize, Serialize};
|
||||
@@ -12,6 +8,7 @@
|
||||
pub struct SizeTuple(pub f32, pub f32);
|
||||
|
||||
#[derive(Serialize, Deserialize, Copy, Clone, PartialEq, Debug)]
|
||||
#[serde(default)]
|
||||
pub struct ConfigWindow {
|
||||
pub position: PositionTuple,
|
||||
pub size: SizeTuple,
|
||||
@@ -30,23 +27,6 @@ impl ConfigWindow {
|
||||
const MIN_SIZE_X: f32 = 100.0;
|
||||
const MIN_SIZE_Y: f32 = 100.0;
|
||||
|
||||
const FILE_NAME: &'static str = "window";
|
||||
#[cfg(not(test))]
|
||||
pub fn load() -> Self {
|
||||
if let Ok(window) = confy::load::<ConfigWindow>(SNIFFNET_LOWERCASE, Self::FILE_NAME) {
|
||||
window
|
||||
} else {
|
||||
let _ = confy::store(SNIFFNET_LOWERCASE, Self::FILE_NAME, ConfigWindow::default())
|
||||
.log_err(location!());
|
||||
ConfigWindow::default()
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(not(test))]
|
||||
pub fn store(self) -> Result<(), confy::ConfyError> {
|
||||
confy::store(SNIFFNET_LOWERCASE, Self::FILE_NAME, self).log_err(location!())
|
||||
}
|
||||
|
||||
pub fn thumbnail_size(factor: f64) -> SizeTuple {
|
||||
Self::THUMBNAIL_SIZE.scale_and_check(factor)
|
||||
}
|
||||
@@ -142,23 +122,3 @@ fn scale_and_check(self, factor: f64) -> PositionTuple {
|
||||
PositionTuple(x, y)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use crate::ConfigWindow;
|
||||
|
||||
impl ConfigWindow {
|
||||
pub fn test_path() -> String {
|
||||
format!("{}/{}.toml", env!("CARGO_MANIFEST_DIR"), Self::FILE_NAME)
|
||||
}
|
||||
|
||||
pub fn load() -> Self {
|
||||
confy::load_path::<ConfigWindow>(ConfigWindow::test_path())
|
||||
.unwrap_or_else(|_| ConfigWindow::default())
|
||||
}
|
||||
|
||||
pub fn store(self) -> Result<(), confy::ConfyError> {
|
||||
confy::store_path(ConfigWindow::test_path(), self)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,9 +1,12 @@
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::path::PathBuf;
|
||||
|
||||
#[derive(Serialize, Deserialize, Clone, PartialEq, Debug)]
|
||||
#[serde(default)]
|
||||
pub struct ExportPcap {
|
||||
enabled: bool,
|
||||
file_name: String,
|
||||
directory: String,
|
||||
pub(crate) enabled: bool,
|
||||
pub(crate) file_name: String,
|
||||
pub(crate) directory: String,
|
||||
}
|
||||
|
||||
impl ExportPcap {
|
||||
|
||||
@@ -1,7 +1,10 @@
|
||||
#[derive(Default)]
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
#[derive(Serialize, Deserialize, Clone, PartialEq, Debug, Default)]
|
||||
#[serde(default)]
|
||||
pub struct Filters {
|
||||
expanded: bool,
|
||||
bpf: String,
|
||||
pub(crate) expanded: bool,
|
||||
pub(crate) bpf: String,
|
||||
}
|
||||
|
||||
impl Filters {
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
use crate::report::types::sort_type::SortType;
|
||||
use crate::utils::types::file_info::FileInfo;
|
||||
use crate::utils::types::web_page::WebPage;
|
||||
use crate::{Language, ReportSortType, StyleType};
|
||||
use crate::{Language, StyleType};
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
/// Messages types that permit reacting to application interactions/subscriptions
|
||||
@@ -34,7 +34,7 @@ pub enum Message {
|
||||
/// Select data representation to use
|
||||
DataReprSelection(DataRepr),
|
||||
/// Select report sort type to be displayed (inspect page)
|
||||
ReportSortSelection(ReportSortType),
|
||||
ReportSortSelection(SortType),
|
||||
/// Select host sort type to be displayed (overview page)
|
||||
HostSortSelection(SortType),
|
||||
/// Select service sort type to be displayed (overview page)
|
||||
|
||||
@@ -1,4 +1,7 @@
|
||||
pub mod conf;
|
||||
pub mod config_window;
|
||||
pub mod export_pcap;
|
||||
pub mod filters;
|
||||
pub mod message;
|
||||
pub mod settings;
|
||||
pub mod timing_events;
|
||||
|
||||
34
src/gui/types/settings.rs
Normal file
34
src/gui/types/settings.rs
Normal file
@@ -0,0 +1,34 @@
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use crate::gui::styles::types::gradient_type::GradientType;
|
||||
use crate::notifications::types::notifications::Notifications;
|
||||
use crate::{Language, StyleType};
|
||||
|
||||
#[derive(Serialize, Deserialize, Clone, PartialEq, Debug)]
|
||||
#[serde(default)]
|
||||
pub struct Settings {
|
||||
pub color_gradient: GradientType,
|
||||
pub language: Language,
|
||||
pub scale_factor: f64,
|
||||
pub mmdb_country: String,
|
||||
pub mmdb_asn: String,
|
||||
pub style_path: String,
|
||||
pub notifications: Notifications,
|
||||
// StyleType should be last in order to deserialize as a table properly
|
||||
pub style: StyleType,
|
||||
}
|
||||
|
||||
impl Default for Settings {
|
||||
fn default() -> Self {
|
||||
Settings {
|
||||
color_gradient: GradientType::default(),
|
||||
language: Language::default(),
|
||||
scale_factor: 1.0,
|
||||
mmdb_country: String::new(),
|
||||
mmdb_asn: String::new(),
|
||||
style_path: String::new(),
|
||||
notifications: Notifications::default(),
|
||||
style: StyleType::default(),
|
||||
}
|
||||
}
|
||||
}
|
||||
18
src/main.rs
18
src/main.rs
@@ -7,12 +7,10 @@
|
||||
use iced::advanced::graphics::image::image_rs::ImageFormat;
|
||||
#[cfg(target_os = "linux")]
|
||||
use iced::window::settings::PlatformSpecific;
|
||||
use iced::{Font, Pixels, Settings, application, window};
|
||||
use iced::{Font, Pixels, application, window};
|
||||
|
||||
use chart::types::traffic_chart::TrafficChart;
|
||||
use cli::handle_cli_args;
|
||||
use configs::types::config_device::ConfigDevice;
|
||||
use configs::types::config_settings::ConfigSettings;
|
||||
use gui::pages::types::running_page::RunningPage;
|
||||
use gui::sniffer::Sniffer;
|
||||
use gui::styles::style_constants::FONT_SIZE_BODY;
|
||||
@@ -22,18 +20,16 @@
|
||||
use networking::types::ip_version::IpVersion;
|
||||
use networking::types::protocol::Protocol;
|
||||
use networking::types::service::Service;
|
||||
use report::types::report_sort_type::ReportSortType;
|
||||
use translations::types::language::Language;
|
||||
use utils::formatted_strings::print_cli_welcome_message;
|
||||
|
||||
use crate::configs::types::config_window::{ConfigWindow, ToPosition, ToSize};
|
||||
use crate::configs::types::configs::{CONFIGS, Configs};
|
||||
use crate::gui::sniffer::FONT_FAMILY_NAME;
|
||||
use crate::gui::styles::style_constants::{ICONS_BYTES, SARASA_MONO_BOLD_BYTES, SARASA_MONO_BYTES};
|
||||
use crate::gui::types::conf::CONF;
|
||||
use crate::gui::types::config_window::{ConfigWindow, ToPosition, ToSize};
|
||||
|
||||
mod chart;
|
||||
mod cli;
|
||||
mod configs;
|
||||
mod countries;
|
||||
mod gui;
|
||||
mod mmdb;
|
||||
@@ -62,7 +58,7 @@ pub fn main() -> iced::Result {
|
||||
_gag2 = gag2;
|
||||
}
|
||||
|
||||
let configs = CONFIGS.clone();
|
||||
let conf = CONF.clone();
|
||||
let boot_task_chain = handle_cli_args();
|
||||
|
||||
#[cfg(debug_assertions)]
|
||||
@@ -78,10 +74,10 @@ pub fn main() -> iced::Result {
|
||||
|
||||
print_cli_welcome_message();
|
||||
|
||||
let ConfigWindow { size, position, .. } = configs.window;
|
||||
let ConfigWindow { size, position, .. } = conf.window;
|
||||
|
||||
application(SNIFFNET_TITLECASE, Sniffer::update, Sniffer::view)
|
||||
.settings(Settings {
|
||||
.settings(iced::Settings {
|
||||
// id needed for Linux Wayland; should match StartupWMClass in .desktop file; see issue #292
|
||||
id: Some(String::from(SNIFFNET_LOWERCASE)),
|
||||
fonts: vec![
|
||||
@@ -114,5 +110,5 @@ pub fn main() -> iced::Result {
|
||||
.subscription(Sniffer::subscription)
|
||||
.theme(Sniffer::theme)
|
||||
.scale_factor(Sniffer::scale_factor)
|
||||
.run_with(move || (Sniffer::new(configs), boot_task_chain))
|
||||
.run_with(move || (Sniffer::new(conf), boot_task_chain))
|
||||
}
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
use crate::gui::types::conf::Conf;
|
||||
use crate::gui::types::filters::Filters;
|
||||
use crate::networking::types::my_device::MyDevice;
|
||||
use crate::networking::types::my_link_type::MyLinkType;
|
||||
@@ -5,6 +6,7 @@
|
||||
use crate::translations::translations_4::capture_file_translation;
|
||||
use crate::translations::types::language::Language;
|
||||
use pcap::{Active, Address, Capture, Error, Packet, Savefile, Stat};
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
pub enum CaptureContext {
|
||||
Live(Live),
|
||||
@@ -155,6 +157,19 @@ pub enum CaptureSource {
|
||||
}
|
||||
|
||||
impl CaptureSource {
|
||||
pub fn from_conf(conf: &Conf) -> Self {
|
||||
match conf.capture_source_picklist {
|
||||
CaptureSourcePicklist::Device => {
|
||||
let device = conf.device.to_my_device();
|
||||
Self::Device(device)
|
||||
}
|
||||
CaptureSourcePicklist::File => {
|
||||
let path = conf.import_pcap_path.clone();
|
||||
Self::File(MyPcapImport::new(path))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn title(&self, language: Language) -> &str {
|
||||
match self {
|
||||
Self::Device(_) => network_adapter_translation(language),
|
||||
@@ -222,7 +237,7 @@ pub fn new(path: String) -> Self {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Eq, PartialEq, Debug, Copy, Default)]
|
||||
#[derive(Clone, Eq, PartialEq, Debug, Copy, Default, Serialize, Deserialize)]
|
||||
pub enum CaptureSourcePicklist {
|
||||
#[default]
|
||||
Device,
|
||||
|
||||
42
src/networking/types/config_device.rs
Normal file
42
src/networking/types/config_device.rs
Normal file
@@ -0,0 +1,42 @@
|
||||
use crate::networking::types::my_device::MyDevice;
|
||||
use pcap::{Device, DeviceFlags};
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
#[derive(Serialize, Deserialize, Clone, PartialEq, Debug)]
|
||||
#[serde(default)]
|
||||
pub struct ConfigDevice {
|
||||
pub device_name: String,
|
||||
}
|
||||
|
||||
impl Default for ConfigDevice {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
device_name: Device::lookup()
|
||||
.unwrap_or(None)
|
||||
.unwrap_or_else(|| Device {
|
||||
name: String::new(),
|
||||
desc: None,
|
||||
addresses: vec![],
|
||||
flags: DeviceFlags::empty(),
|
||||
})
|
||||
.name,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl ConfigDevice {
|
||||
pub fn to_my_device(&self) -> MyDevice {
|
||||
for device in Device::list().unwrap_or_default() {
|
||||
if device.name.eq(&self.device_name) {
|
||||
return MyDevice::from_pcap_device(device);
|
||||
}
|
||||
}
|
||||
let standard_device = Device::lookup().unwrap_or(None).unwrap_or_else(|| Device {
|
||||
name: String::new(),
|
||||
desc: None,
|
||||
addresses: vec![],
|
||||
flags: DeviceFlags::empty(),
|
||||
});
|
||||
MyDevice::from_pcap_device(standard_device)
|
||||
}
|
||||
}
|
||||
@@ -3,6 +3,7 @@
|
||||
pub mod asn;
|
||||
pub mod bogon;
|
||||
pub mod capture_context;
|
||||
pub mod config_device;
|
||||
pub mod data_info;
|
||||
pub mod data_info_host;
|
||||
pub mod data_representation;
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
|
||||
/// Used to contain the notifications configuration set by the user
|
||||
#[derive(Clone, Serialize, Deserialize, Copy, PartialEq, Debug)]
|
||||
#[serde(default)]
|
||||
pub struct Notifications {
|
||||
pub volume: u8,
|
||||
pub data_notification: DataNotification,
|
||||
@@ -32,6 +33,7 @@ pub enum Notification {
|
||||
}
|
||||
|
||||
#[derive(Clone, Eq, PartialEq, Serialize, Deserialize, Debug, Copy)]
|
||||
#[serde(default)]
|
||||
pub struct DataNotification {
|
||||
/// Data representation
|
||||
pub data_repr: DataRepr,
|
||||
@@ -101,6 +103,7 @@ pub fn from(value: &str, existing: Option<Self>) -> Self {
|
||||
}
|
||||
|
||||
#[derive(Clone, Eq, PartialEq, Serialize, Deserialize, Debug, Copy)]
|
||||
#[serde(default)]
|
||||
pub struct FavoriteNotification {
|
||||
/// Flag to determine if this notification is enabled
|
||||
pub notify_on_favorite: bool,
|
||||
|
||||
@@ -50,7 +50,7 @@ pub fn get_searched_entries(
|
||||
all_results.sort_by(|&(_, a), &(_, b)| {
|
||||
a.compare(
|
||||
b,
|
||||
sniffer.report_sort_type.data_sort,
|
||||
sniffer.conf.report_sort_type,
|
||||
sniffer.traffic_chart.data_repr,
|
||||
)
|
||||
});
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
pub mod report_col;
|
||||
pub mod report_sort_type;
|
||||
pub mod search_parameters;
|
||||
pub mod sort_type;
|
||||
|
||||
@@ -1,78 +0,0 @@
|
||||
use std::fmt::Debug;
|
||||
|
||||
use iced::widget::Text;
|
||||
|
||||
use crate::gui::styles::button::ButtonType;
|
||||
use crate::gui::styles::types::style_type::StyleType;
|
||||
use crate::report::types::sort_type::SortType;
|
||||
|
||||
/// Struct representing the possible kinds of sort for displayed relevant connections.
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Default)]
|
||||
pub struct ReportSortType {
|
||||
pub data_sort: SortType,
|
||||
}
|
||||
|
||||
impl ReportSortType {
|
||||
pub fn next_sort(self) -> Self {
|
||||
Self {
|
||||
data_sort: self.data_sort.next_sort(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn icon<'a>(self) -> Text<'a, StyleType> {
|
||||
self.data_sort.icon()
|
||||
}
|
||||
|
||||
pub fn button_type(self) -> ButtonType {
|
||||
self.data_sort.button_type()
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use crate::report::types::report_sort_type::ReportSortType;
|
||||
use crate::report::types::sort_type::SortType;
|
||||
|
||||
#[test]
|
||||
fn test_next_report_sort() {
|
||||
let mut sort = ReportSortType::default();
|
||||
assert_eq!(
|
||||
sort,
|
||||
ReportSortType {
|
||||
data_sort: SortType::Neutral,
|
||||
}
|
||||
);
|
||||
|
||||
sort = sort.next_sort();
|
||||
assert_eq!(
|
||||
sort,
|
||||
ReportSortType {
|
||||
data_sort: SortType::Descending,
|
||||
}
|
||||
);
|
||||
|
||||
sort = sort.next_sort();
|
||||
assert_eq!(
|
||||
sort,
|
||||
ReportSortType {
|
||||
data_sort: SortType::Ascending,
|
||||
}
|
||||
);
|
||||
|
||||
sort = sort.next_sort();
|
||||
assert_eq!(
|
||||
sort,
|
||||
ReportSortType {
|
||||
data_sort: SortType::Neutral,
|
||||
}
|
||||
);
|
||||
|
||||
sort = sort.next_sort();
|
||||
assert_eq!(
|
||||
sort,
|
||||
ReportSortType {
|
||||
data_sort: SortType::Descending,
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -1,10 +1,10 @@
|
||||
use iced::widget::Text;
|
||||
|
||||
use crate::gui::styles::button::ButtonType;
|
||||
use crate::gui::styles::types::style_type::StyleType;
|
||||
use crate::utils::types::icon::Icon;
|
||||
use iced::widget::Text;
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Default)]
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Default, Serialize, Deserialize)]
|
||||
pub enum SortType {
|
||||
Ascending,
|
||||
Descending,
|
||||
|
||||
Reference in New Issue
Block a user