mirror of
https://github.com/GyulyVGC/sniffnet.git
synced 2026-06-05 21:06:52 +08:00
feat: improve IP blacklist import feedback
This commit is contained in:
parent
e4534b0e0f
commit
51e03967f4
@ -15,14 +15,18 @@
|
||||
use crate::gui::types::message::Message;
|
||||
use crate::gui::types::settings::Settings;
|
||||
use crate::mmdb::types::mmdb_reader::{MmdbReader, MmdbReaders};
|
||||
use crate::networking::types::ip_blacklist::IpBlacklist;
|
||||
use crate::networking::types::ip_blacklist::{IpBlacklist, IpBlacklistLoadStatus};
|
||||
use crate::translations::translations::language_translation;
|
||||
use crate::translations::translations_2::country_translation;
|
||||
use crate::translations::translations_3::{
|
||||
mmdb_files_translation, params_not_editable_translation, zoom_translation,
|
||||
};
|
||||
use crate::translations::translations_4::share_feedback_translation;
|
||||
use crate::translations::translations_5::ip_blacklist_translation;
|
||||
use crate::translations::translations_5::{
|
||||
ip_blacklist_file_read_error_translation, ip_blacklist_loaded_translation,
|
||||
ip_blacklist_loading_translation, ip_blacklist_no_valid_entries_translation,
|
||||
ip_blacklist_not_selected_translation, ip_blacklist_translation,
|
||||
};
|
||||
use crate::utils::formatted_strings::get_path_termination_string;
|
||||
use crate::utils::types::file_info::FileInfo;
|
||||
use crate::utils::types::icon::Icon;
|
||||
@ -331,6 +335,8 @@ fn blacklist_selection<'a>(
|
||||
};
|
||||
|
||||
let message = Message::LoadIpBlacklist;
|
||||
let status = blacklist_status_text(custom_path, ip_blacklist, language);
|
||||
let status_text_type = blacklist_status_text_type(ip_blacklist);
|
||||
|
||||
Column::new()
|
||||
.width(Length::Fill)
|
||||
@ -363,6 +369,44 @@ fn blacklist_selection<'a>(
|
||||
button_clear_mmdb(message, is_editable)
|
||||
}),
|
||||
)
|
||||
.push(Text::new(status).class(status_text_type).size(12))
|
||||
}
|
||||
|
||||
fn blacklist_status_text(
|
||||
custom_path: &str,
|
||||
ip_blacklist: &IpBlacklist,
|
||||
language: Language,
|
||||
) -> String {
|
||||
if custom_path.is_empty() {
|
||||
return ip_blacklist_not_selected_translation(language).to_string();
|
||||
}
|
||||
|
||||
match ip_blacklist.status() {
|
||||
IpBlacklistLoadStatus::NotSelected => {
|
||||
ip_blacklist_not_selected_translation(language).to_string()
|
||||
}
|
||||
IpBlacklistLoadStatus::Loading => ip_blacklist_loading_translation(language).to_string(),
|
||||
IpBlacklistLoadStatus::FileReadError => {
|
||||
ip_blacklist_file_read_error_translation(language).to_string()
|
||||
}
|
||||
IpBlacklistLoadStatus::NoValidEntries { .. } => {
|
||||
ip_blacklist_no_valid_entries_translation(language).to_string()
|
||||
}
|
||||
IpBlacklistLoadStatus::Loaded {
|
||||
ip_count,
|
||||
network_count,
|
||||
..
|
||||
} => ip_blacklist_loaded_translation(language, *ip_count, *network_count),
|
||||
}
|
||||
}
|
||||
|
||||
fn blacklist_status_text_type(ip_blacklist: &IpBlacklist) -> TextType {
|
||||
match ip_blacklist.status() {
|
||||
IpBlacklistLoadStatus::FileReadError | IpBlacklistLoadStatus::NoValidEntries { .. } => {
|
||||
TextType::Danger
|
||||
}
|
||||
_ => TextType::Standard,
|
||||
}
|
||||
}
|
||||
|
||||
fn button_clear_mmdb<'a>(
|
||||
|
||||
@ -5,20 +5,40 @@
|
||||
use ipnet::IpNet;
|
||||
use prefix_trie::joint::set::JointPrefixSet;
|
||||
|
||||
#[derive(Clone, Debug, Default, PartialEq, Eq)]
|
||||
pub enum IpBlacklistLoadStatus {
|
||||
#[default]
|
||||
NotSelected,
|
||||
Loading,
|
||||
Loaded {
|
||||
ip_count: usize,
|
||||
network_count: usize,
|
||||
ignored_lines: usize,
|
||||
},
|
||||
FileReadError,
|
||||
NoValidEntries {
|
||||
ignored_lines: usize,
|
||||
},
|
||||
}
|
||||
|
||||
#[derive(Clone, Default, Debug)]
|
||||
pub struct IpBlacklist {
|
||||
ips: Arc<HashSet<IpAddr>>,
|
||||
networks: Arc<JointPrefixSet<IpNet>>,
|
||||
is_loading: bool,
|
||||
status: IpBlacklistLoadStatus,
|
||||
}
|
||||
|
||||
impl IpBlacklist {
|
||||
pub async fn from_file(path: String) -> Self {
|
||||
let Ok(buf) = tokio::fs::read_to_string(&path).await else {
|
||||
return IpBlacklist::default();
|
||||
return IpBlacklist {
|
||||
status: IpBlacklistLoadStatus::FileReadError,
|
||||
..IpBlacklist::default()
|
||||
};
|
||||
};
|
||||
let mut ips = HashSet::new();
|
||||
let mut networks = JointPrefixSet::new();
|
||||
let mut ignored_lines = 0;
|
||||
for line in buf.lines() {
|
||||
let Some(first) = line.split_whitespace().next() else {
|
||||
continue;
|
||||
@ -28,12 +48,26 @@ pub async fn from_file(path: String) -> Self {
|
||||
ips.insert(ip);
|
||||
} else if let Ok(network) = first.parse::<IpNet>() {
|
||||
networks.insert(network);
|
||||
} else {
|
||||
ignored_lines += 1;
|
||||
}
|
||||
}
|
||||
let ip_count = ips.len();
|
||||
let network_count = networks.len();
|
||||
let status = if ip_count == 0 && network_count == 0 {
|
||||
IpBlacklistLoadStatus::NoValidEntries { ignored_lines }
|
||||
} else {
|
||||
IpBlacklistLoadStatus::Loaded {
|
||||
ip_count,
|
||||
network_count,
|
||||
ignored_lines,
|
||||
}
|
||||
};
|
||||
|
||||
IpBlacklist {
|
||||
ips: Arc::new(ips),
|
||||
networks: Arc::new(networks),
|
||||
is_loading: false,
|
||||
status,
|
||||
}
|
||||
}
|
||||
|
||||
@ -42,15 +76,22 @@ pub fn contains(&self, ip: &IpAddr) -> bool {
|
||||
}
|
||||
|
||||
pub fn is_invalid(&self) -> bool {
|
||||
self.ips.is_empty() && self.networks.is_empty() && !self.is_loading
|
||||
matches!(
|
||||
self.status,
|
||||
IpBlacklistLoadStatus::FileReadError | IpBlacklistLoadStatus::NoValidEntries { .. }
|
||||
)
|
||||
}
|
||||
|
||||
pub fn is_loading(&self) -> bool {
|
||||
self.is_loading
|
||||
matches!(self.status, IpBlacklistLoadStatus::Loading)
|
||||
}
|
||||
|
||||
pub fn status(&self) -> &IpBlacklistLoadStatus {
|
||||
&self.status
|
||||
}
|
||||
|
||||
pub fn start_loading(&mut self) {
|
||||
self.is_loading = true;
|
||||
self.status = IpBlacklistLoadStatus::Loading;
|
||||
}
|
||||
}
|
||||
|
||||
@ -68,6 +109,14 @@ async fn test_ip_blacklist_valid() {
|
||||
assert!(!blacklist.is_loading());
|
||||
assert_eq!(blacklist.ips.len(), 4);
|
||||
assert_eq!(blacklist.networks.len(), 0);
|
||||
assert_eq!(
|
||||
blacklist.status(),
|
||||
&IpBlacklistLoadStatus::Loaded {
|
||||
ip_count: 4,
|
||||
network_count: 0,
|
||||
ignored_lines: 4,
|
||||
}
|
||||
);
|
||||
|
||||
assert!(blacklist.contains(&IpAddr::V4(Ipv4Addr::new(8, 8, 8, 8))));
|
||||
assert!(blacklist.contains(&IpAddr::V4(Ipv4Addr::new(1, 2, 3, 255))));
|
||||
@ -89,6 +138,10 @@ async fn test_ip_blacklist_invalid() {
|
||||
assert!(!blacklist.is_loading());
|
||||
assert_eq!(blacklist.ips.len(), 0);
|
||||
assert_eq!(blacklist.networks.len(), 0);
|
||||
assert_eq!(
|
||||
blacklist.status(),
|
||||
&IpBlacklistLoadStatus::NoValidEntries { ignored_lines: 6 }
|
||||
);
|
||||
|
||||
assert!(!blacklist.contains(&IpAddr::V4(Ipv4Addr::new(8, 8, 8, 8))));
|
||||
assert!(!blacklist.contains(&IpAddr::V4(Ipv4Addr::new(0, 0, 0, 0))));
|
||||
@ -106,6 +159,14 @@ async fn test_ip_blacklist_valid_with_cidr() {
|
||||
assert!(!blacklist.is_loading());
|
||||
assert_eq!(blacklist.ips.len(), 2);
|
||||
assert_eq!(blacklist.networks.len(), 4);
|
||||
assert_eq!(
|
||||
blacklist.status(),
|
||||
&IpBlacklistLoadStatus::Loaded {
|
||||
ip_count: 2,
|
||||
network_count: 4,
|
||||
ignored_lines: 3,
|
||||
}
|
||||
);
|
||||
|
||||
assert!(blacklist.contains(&IpAddr::V4(Ipv4Addr::new(8, 8, 8, 8))));
|
||||
assert!(blacklist.contains(&"2001:db8::1".parse::<IpAddr>().unwrap()));
|
||||
@ -137,6 +198,14 @@ async fn test_ip_blacklist_valid_with_cidr_only() {
|
||||
assert!(!blacklist.is_loading());
|
||||
assert_eq!(blacklist.ips.len(), 0);
|
||||
assert_eq!(blacklist.networks.len(), 1);
|
||||
assert_eq!(
|
||||
blacklist.status(),
|
||||
&IpBlacklistLoadStatus::Loaded {
|
||||
ip_count: 0,
|
||||
network_count: 1,
|
||||
ignored_lines: 0,
|
||||
}
|
||||
);
|
||||
|
||||
assert!(blacklist.contains(&IpAddr::V4(Ipv4Addr::new(1, 2, 3, 1))));
|
||||
assert!(!blacklist.contains(&IpAddr::V4(Ipv4Addr::new(1, 2, 4, 1))));
|
||||
@ -170,4 +239,28 @@ async fn test_ip_blacklist_real_cidr_ranges() {
|
||||
assert!(!blacklist.contains(&IpAddr::V4(Ipv4Addr::new(209, 186, 237, 0))));
|
||||
assert!(!blacklist.contains(&IpAddr::V4(Ipv4Addr::new(209, 233, 160, 0))));
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_ip_blacklist_read_error() {
|
||||
let blacklist =
|
||||
IpBlacklist::from_file("resources/test/does_not_exist_blacklist.txt".to_string()).await;
|
||||
|
||||
assert!(blacklist.is_invalid());
|
||||
assert!(!blacklist.is_loading());
|
||||
assert_eq!(blacklist.ips.len(), 0);
|
||||
assert_eq!(blacklist.networks.len(), 0);
|
||||
assert_eq!(blacklist.status(), &IpBlacklistLoadStatus::FileReadError);
|
||||
assert!(!blacklist.contains(&IpAddr::V4(Ipv4Addr::new(8, 8, 8, 8))));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_ip_blacklist_loading_status() {
|
||||
let mut blacklist = IpBlacklist::default();
|
||||
|
||||
blacklist.start_loading();
|
||||
|
||||
assert!(blacklist.is_loading());
|
||||
assert!(!blacklist.is_invalid());
|
||||
assert_eq!(blacklist.status(), &IpBlacklistLoadStatus::Loading);
|
||||
}
|
||||
}
|
||||
|
||||
@ -86,6 +86,198 @@ pub fn ip_blacklist_translation(language: Language) -> &'static str {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn ip_blacklist_not_selected_translation(language: Language) -> &'static str {
|
||||
match language {
|
||||
Language::EN => "No blacklist file selected.",
|
||||
Language::CS => "Není vybrán žádný soubor blacklistu.",
|
||||
Language::DE => "Keine Blacklist-Datei ausgewählt.",
|
||||
Language::EL => "Δεν έχει επιλεγεί αρχείο λίστας αποκλεισμού.",
|
||||
Language::ES => "No se ha seleccionado ningún archivo de blacklist.",
|
||||
Language::FI => "Blacklist-tiedostoa ei ole valittu.",
|
||||
Language::FR => "Aucun fichier de blacklist sélectionné.",
|
||||
Language::ID => "Belum ada berkas daftar hitam yang dipilih.",
|
||||
Language::IT => "Nessun file blacklist selezionato.",
|
||||
Language::JA => "ブラックリストファイルが選択されていません。",
|
||||
Language::KO => "선택된 블랙리스트 파일이 없습니다.",
|
||||
Language::NL => "Geen blacklistbestand geselecteerd.",
|
||||
Language::PL => "Nie wybrano pliku blacklisty.",
|
||||
Language::PT => "Nenhum arquivo de blacklist selecionado.",
|
||||
Language::RO => "Nu a fost selectat niciun fișier blacklist.",
|
||||
Language::RU => "Файл черного списка не выбран.",
|
||||
Language::SV => "Ingen svartlistfil har valts.",
|
||||
Language::TR => "Kara liste dosyası seçilmedi.",
|
||||
Language::UK => "Файл чорного списку не вибрано.",
|
||||
Language::UZ => "Qora ro'yxat fayli tanlanmagan.",
|
||||
Language::VI => "Chưa chọn tệp danh sách đen.",
|
||||
Language::ZH => "未选择黑名单文件。",
|
||||
Language::ZH_TW => "未選擇黑名單檔案。",
|
||||
}
|
||||
}
|
||||
|
||||
pub fn ip_blacklist_loading_translation(language: Language) -> &'static str {
|
||||
match language {
|
||||
Language::EN => "Loading blacklist...",
|
||||
Language::CS => "Načítá se blacklist...",
|
||||
Language::DE => "Blacklist wird geladen...",
|
||||
Language::EL => "Φόρτωση λίστας αποκλεισμού...",
|
||||
Language::ES => "Cargando blacklist...",
|
||||
Language::FI => "Ladataan blacklistia...",
|
||||
Language::FR => "Chargement de la blacklist...",
|
||||
Language::ID => "Memuat daftar hitam...",
|
||||
Language::IT => "Caricamento blacklist...",
|
||||
Language::JA => "ブラックリストを読み込み中...",
|
||||
Language::KO => "블랙리스트를 불러오는 중...",
|
||||
Language::NL => "Blacklist laden...",
|
||||
Language::PL => "Wczytywanie blacklisty...",
|
||||
Language::PT => "Carregando blacklist...",
|
||||
Language::RO => "Se încarcă blacklistul...",
|
||||
Language::RU => "Загрузка черного списка...",
|
||||
Language::SV => "Läser in svartlistan...",
|
||||
Language::TR => "Kara liste yükleniyor...",
|
||||
Language::UK => "Завантаження чорного списку...",
|
||||
Language::UZ => "Qora ro'yxat yuklanmoqda...",
|
||||
Language::VI => "Đang tải danh sách đen...",
|
||||
Language::ZH => "正在加载黑名单...",
|
||||
Language::ZH_TW => "正在載入黑名單...",
|
||||
}
|
||||
}
|
||||
|
||||
pub fn ip_blacklist_file_read_error_translation(language: Language) -> &'static str {
|
||||
match language {
|
||||
Language::EN => "Could not read blacklist file.",
|
||||
Language::CS => "Soubor blacklistu nelze přečíst.",
|
||||
Language::DE => "Blacklist-Datei konnte nicht gelesen werden.",
|
||||
Language::EL => "Δεν ήταν δυνατή η ανάγνωση του αρχείου λίστας αποκλεισμού.",
|
||||
Language::ES => "No se pudo leer el archivo de blacklist.",
|
||||
Language::FI => "Blacklist-tiedostoa ei voitu lukea.",
|
||||
Language::FR => "Impossible de lire le fichier de blacklist.",
|
||||
Language::ID => "Berkas daftar hitam tidak dapat dibaca.",
|
||||
Language::IT => "Impossibile leggere il file blacklist.",
|
||||
Language::JA => "ブラックリストファイルを読み取れませんでした。",
|
||||
Language::KO => "블랙리스트 파일을 읽을 수 없습니다.",
|
||||
Language::NL => "Kan het blacklistbestand niet lezen.",
|
||||
Language::PL => "Nie można odczytać pliku blacklisty.",
|
||||
Language::PT => "Não foi possível ler o arquivo de blacklist.",
|
||||
Language::RO => "Nu s-a putut citi fișierul blacklist.",
|
||||
Language::RU => "Не удалось прочитать файл черного списка.",
|
||||
Language::SV => "Kunde inte läsa svartlistfilen.",
|
||||
Language::TR => "Kara liste dosyası okunamadı.",
|
||||
Language::UK => "Не вдалося прочитати файл чорного списку.",
|
||||
Language::UZ => "Qora ro'yxat faylini o'qib bo'lmadi.",
|
||||
Language::VI => "Không thể đọc tệp danh sách đen.",
|
||||
Language::ZH => "无法读取黑名单文件。",
|
||||
Language::ZH_TW => "無法讀取黑名單檔案。",
|
||||
}
|
||||
}
|
||||
|
||||
pub fn ip_blacklist_no_valid_entries_translation(language: Language) -> &'static str {
|
||||
match language {
|
||||
Language::EN => "No valid IP addresses or CIDR ranges found.",
|
||||
Language::CS => "Nebyly nalezeny žádné platné IP adresy ani rozsahy CIDR.",
|
||||
Language::DE => "Keine gültigen IP-Adressen oder CIDR-Bereiche gefunden.",
|
||||
Language::EL => "Δεν βρέθηκαν έγκυρες διευθύνσεις IP ή εύρη CIDR.",
|
||||
Language::ES => "No se encontraron direcciones IP ni rangos CIDR válidos.",
|
||||
Language::FI => "Kelvollisia IP-osoitteita tai CIDR-alueita ei löytynyt.",
|
||||
Language::FR => "Aucune adresse IP ni plage CIDR valide trouvée.",
|
||||
Language::ID => "Tidak ada alamat IP atau rentang CIDR yang valid ditemukan.",
|
||||
Language::IT => "Nessun indirizzo IP o intervallo CIDR valido trovato.",
|
||||
Language::JA => "有効な IP アドレスまたは CIDR 範囲が見つかりませんでした。",
|
||||
Language::KO => "유효한 IP 주소 또는 CIDR 범위를 찾을 수 없습니다.",
|
||||
Language::NL => "Geen geldige IP-adressen of CIDR-bereiken gevonden.",
|
||||
Language::PL => "Nie znaleziono prawidłowych adresów IP ani zakresów CIDR.",
|
||||
Language::PT => "Nenhum endereço IP ou intervalo CIDR válido encontrado.",
|
||||
Language::RO => "Nu au fost găsite adrese IP sau intervale CIDR valide.",
|
||||
Language::RU => "Действительные IP-адреса или диапазоны CIDR не найдены.",
|
||||
Language::SV => "Inga giltiga IP-adresser eller CIDR-intervall hittades.",
|
||||
Language::TR => "Geçerli IP adresi veya CIDR aralığı bulunamadı.",
|
||||
Language::UK => "Дійсні IP-адреси або діапазони CIDR не знайдено.",
|
||||
Language::UZ => "Yaroqli IP manzillar yoki CIDR oraliqlari topilmadi.",
|
||||
Language::VI => "Không tìm thấy địa chỉ IP hoặc dải CIDR hợp lệ.",
|
||||
Language::ZH => "未找到有效的 IP 地址或 CIDR 范围。",
|
||||
Language::ZH_TW => "找不到有效的 IP 位址或 CIDR 範圍。",
|
||||
}
|
||||
}
|
||||
|
||||
pub fn ip_blacklist_loaded_translation(
|
||||
language: Language,
|
||||
ip_count: usize,
|
||||
network_count: usize,
|
||||
) -> String {
|
||||
match language {
|
||||
Language::EN => {
|
||||
format!("Loaded {ip_count} IP addresses and {network_count} CIDR ranges.")
|
||||
}
|
||||
Language::CS => {
|
||||
format!("Načteno {ip_count} IP adres a {network_count} rozsahů CIDR.")
|
||||
}
|
||||
Language::DE => {
|
||||
format!("{ip_count} IP-Adressen und {network_count} CIDR-Bereiche geladen.")
|
||||
}
|
||||
Language::EL => {
|
||||
format!("Φορτώθηκαν {ip_count} διευθύνσεις IP και {network_count} εύρη CIDR.")
|
||||
}
|
||||
Language::ES => {
|
||||
format!("Cargadas {ip_count} direcciones IP y {network_count} rangos CIDR.")
|
||||
}
|
||||
Language::FI => {
|
||||
format!("Ladattu {ip_count} IP-osoitetta ja {network_count} CIDR-aluetta.")
|
||||
}
|
||||
Language::FR => {
|
||||
format!("{ip_count} adresses IP et {network_count} plages CIDR chargées.")
|
||||
}
|
||||
Language::ID => {
|
||||
format!("Dimuat {ip_count} alamat IP dan {network_count} rentang CIDR.")
|
||||
}
|
||||
Language::IT => {
|
||||
format!("Caricati {ip_count} indirizzi IP e {network_count} intervalli CIDR.")
|
||||
}
|
||||
Language::JA => {
|
||||
format!(
|
||||
"{ip_count} 件の IP アドレスと {network_count} 件の CIDR 範囲を読み込みました。"
|
||||
)
|
||||
}
|
||||
Language::KO => {
|
||||
format!("IP 주소 {ip_count}개와 CIDR 범위 {network_count}개를 불러왔습니다.")
|
||||
}
|
||||
Language::NL => {
|
||||
format!("{ip_count} IP-adressen en {network_count} CIDR-bereiken geladen.")
|
||||
}
|
||||
Language::PL => {
|
||||
format!("Wczytano adresów IP: {ip_count}, zakresów CIDR: {network_count}.")
|
||||
}
|
||||
Language::PT => {
|
||||
format!("Carregados {ip_count} endereços IP e {network_count} intervalos CIDR.")
|
||||
}
|
||||
Language::RO => {
|
||||
format!("Încărcate {ip_count} adrese IP și {network_count} intervale CIDR.")
|
||||
}
|
||||
Language::RU => {
|
||||
format!("Загружено IP-адресов: {ip_count}, диапазонов CIDR: {network_count}.")
|
||||
}
|
||||
Language::SV => {
|
||||
format!("{ip_count} IP-adresser och {network_count} CIDR-intervall har lästs in.")
|
||||
}
|
||||
Language::TR => {
|
||||
format!("{ip_count} IP adresi ve {network_count} CIDR aralığı yüklendi.")
|
||||
}
|
||||
Language::UK => {
|
||||
format!("Завантажено IP-адрес: {ip_count}, діапазонів CIDR: {network_count}.")
|
||||
}
|
||||
Language::UZ => {
|
||||
format!("{ip_count} ta IP manzil va {network_count} ta CIDR oralig'i yuklandi.")
|
||||
}
|
||||
Language::VI => {
|
||||
format!("Đã tải {ip_count} địa chỉ IP và {network_count} dải CIDR.")
|
||||
}
|
||||
Language::ZH => {
|
||||
format!("已加载 {ip_count} 个 IP 地址和 {network_count} 个 CIDR 范围。")
|
||||
}
|
||||
Language::ZH_TW => {
|
||||
format!("已載入 {ip_count} 個 IP 位址和 {network_count} 個 CIDR 範圍。")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn blacklisted_transmitted_translation(language: Language) -> &'static str {
|
||||
match language {
|
||||
Language::EN => "New data exchanged from a blacklisted IP",
|
||||
|
||||
Loading…
Reference in New Issue
Block a user