Actualiser 7lna.py
This commit is contained in:
243
7lna.py
243
7lna.py
@@ -3,43 +3,51 @@ from tkinter import filedialog, messagebox
|
|||||||
import os
|
import os
|
||||||
import threading
|
import threading
|
||||||
import subprocess
|
import subprocess
|
||||||
|
import urllib.request
|
||||||
|
import time
|
||||||
from watchdog.observers import Observer
|
from watchdog.observers import Observer
|
||||||
from watchdog.events import FileSystemEventHandler
|
from watchdog.events import FileSystemEventHandler
|
||||||
import time
|
|
||||||
|
|
||||||
# --- Configuration du Design ---
|
# ==========================================
|
||||||
|
# CONFIGURATION GLOBALE
|
||||||
|
# ==========================================
|
||||||
|
# Lien RAW officiel de ton dépôt Gitea
|
||||||
|
UPDATE_URL = "https://git.7ka1.com/7ka1/7LnA_Antivirus_Linux_Free_ClamAV_Based/raw/branch/main/7lna.py"
|
||||||
|
|
||||||
|
QUARANTINE_DIR = os.path.expanduser("~/.7lna_quarantine")
|
||||||
|
WATCH_FOLDER = os.path.expanduser("~/Téléchargements")
|
||||||
|
|
||||||
|
# Design global
|
||||||
ctk.set_appearance_mode("dark")
|
ctk.set_appearance_mode("dark")
|
||||||
ctk.set_default_color_theme("blue")
|
ctk.set_default_color_theme("blue")
|
||||||
|
|
||||||
|
# ==========================================
|
||||||
|
# GESTIONNAIRE DU BOUCLIER TEMPS RÉEL
|
||||||
|
# ==========================================
|
||||||
class RealTimeShieldHandler(FileSystemEventHandler):
|
class RealTimeShieldHandler(FileSystemEventHandler):
|
||||||
"""Gère les événements système : quand un fichier est créé."""
|
|
||||||
def __init__(self, app_instance):
|
def __init__(self, app_instance):
|
||||||
self.app = app_instance
|
self.app = app_instance
|
||||||
|
|
||||||
def on_created(self, event):
|
def on_created(self, event):
|
||||||
# On ignore les dossiers, on ne scanne que les fichiers
|
|
||||||
if not event.is_directory:
|
if not event.is_directory:
|
||||||
# Petit délai pour laisser le temps au téléchargement de se terminer
|
time.sleep(1.5) # Laisse le temps au téléchargement de se terminer
|
||||||
time.sleep(1)
|
|
||||||
self.app.trigger_realtime_scan(event.src_path)
|
self.app.trigger_realtime_scan(event.src_path)
|
||||||
|
|
||||||
|
# ==========================================
|
||||||
|
# APPLICATION PRINCIPALE
|
||||||
|
# ==========================================
|
||||||
class Antivirus7LnA(ctk.CTk):
|
class Antivirus7LnA(ctk.CTk):
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
super().__init__()
|
super().__init__()
|
||||||
self.title("7LnA Security Suite - Real-Time Edition")
|
self.title("7LnA Security Suite")
|
||||||
self.geometry("1000x650")
|
self.geometry("1050x650")
|
||||||
self.minsize(800, 500)
|
self.minsize(850, 550)
|
||||||
|
|
||||||
# --- Configuration Système ---
|
# Création du dossier de quarantaine
|
||||||
self.quarantine_dir = os.path.expanduser("~/.7lna_quarantine")
|
os.makedirs(QUARANTINE_DIR, exist_ok=True)
|
||||||
os.makedirs(self.quarantine_dir, exist_ok=True)
|
|
||||||
|
|
||||||
# Variables du Bouclier Temps Réel
|
|
||||||
self.shield_observer = None
|
self.shield_observer = None
|
||||||
self.shield_active = False
|
self.shield_active = False
|
||||||
self.watch_folder = os.path.expanduser("~/Téléchargements") # Par défaut sur Ubuntu FR
|
|
||||||
if not os.path.exists(self.watch_folder):
|
|
||||||
self.watch_folder = os.path.expanduser("~/Downloads") # Fallback en anglais
|
|
||||||
|
|
||||||
self.check_dependencies()
|
self.check_dependencies()
|
||||||
self.setup_ui()
|
self.setup_ui()
|
||||||
@@ -50,32 +58,28 @@ class Antivirus7LnA(ctk.CTk):
|
|||||||
self.clamav_installed = True
|
self.clamav_installed = True
|
||||||
except (subprocess.CalledProcessError, FileNotFoundError):
|
except (subprocess.CalledProcessError, FileNotFoundError):
|
||||||
self.clamav_installed = False
|
self.clamav_installed = False
|
||||||
messagebox.showwarning("Alerte Moteur", "ClamAV n'est pas détecté. Installez-le avec : sudo apt install clamav")
|
|
||||||
|
|
||||||
# ==========================================
|
|
||||||
# ARCHITECTURE DE L'INTERFACE
|
|
||||||
# ==========================================
|
|
||||||
def setup_ui(self):
|
def setup_ui(self):
|
||||||
self.grid_rowconfigure(0, weight=1)
|
self.grid_rowconfigure(0, weight=1)
|
||||||
self.grid_columnconfigure(1, weight=1)
|
self.grid_columnconfigure(1, weight=1)
|
||||||
|
|
||||||
# --- Menu Latéral ---
|
# --- BARRE LATÉRALE ---
|
||||||
self.sidebar = ctk.CTkFrame(self, width=220, corner_radius=0)
|
self.sidebar = ctk.CTkFrame(self, width=220, corner_radius=0)
|
||||||
self.sidebar.grid(row=0, column=0, sticky="nsew")
|
self.sidebar.grid(row=0, column=0, sticky="nsew")
|
||||||
self.sidebar.grid_rowconfigure(6, weight=1)
|
self.sidebar.grid_rowconfigure(6, weight=1)
|
||||||
|
|
||||||
self.logo = ctk.CTkLabel(self.sidebar, text="🛡️ 7LnA", font=ctk.CTkFont(size=28, weight="bold"))
|
ctk.CTkLabel(self.sidebar, text="🛡️ 7LnA", font=ctk.CTkFont(size=28, weight="bold")).grid(row=0, column=0, padx=20, pady=30)
|
||||||
self.logo.grid(row=0, column=0, padx=20, pady=(30, 30))
|
|
||||||
|
|
||||||
self.btn_dashboard = self.create_nav_button("📊 Tableau de Bord", 1, "dashboard")
|
self.btn_dash = self.create_nav_button("📊 Tableau de Bord", 1, "dashboard")
|
||||||
self.btn_scanner = self.create_nav_button("🔍 Scanner Manuel", 2, "scanner")
|
self.btn_scan = self.create_nav_button("🔍 Scanner Manuel", 2, "scanner")
|
||||||
self.btn_realtime = self.create_nav_button("⚡ Bouclier Temps Réel", 3, "realtime")
|
self.btn_shield = self.create_nav_button("⚡ Bouclier Actif", 3, "shield")
|
||||||
self.btn_audit = self.create_nav_button("⚙️ Audit Système", 4, "audit")
|
self.btn_audit = self.create_nav_button("⚙️ Audit Système", 4, "audit")
|
||||||
self.btn_update = self.create_nav_button("🔄 Mise à jour Base", 5, "update")
|
self.btn_update = self.create_nav_button("🔄 Mise à jour", 5, "update")
|
||||||
|
|
||||||
self.version_label = ctk.CTkLabel(self.sidebar, text="Version 5.0 - Active Shield", text_color="gray")
|
self.version_label = ctk.CTkLabel(self.sidebar, text="Version 5.0 - Ultimate", text_color="gray")
|
||||||
self.version_label.grid(row=6, column=0, pady=20, sticky="s")
|
self.version_label.grid(row=6, column=0, pady=20, sticky="s")
|
||||||
|
|
||||||
|
# --- CONTENEUR DES VUES ---
|
||||||
self.views = {}
|
self.views = {}
|
||||||
self.init_dashboard_view()
|
self.init_dashboard_view()
|
||||||
self.init_scanner_view()
|
self.init_scanner_view()
|
||||||
@@ -98,9 +102,7 @@ class Antivirus7LnA(ctk.CTk):
|
|||||||
if view_name in self.views:
|
if view_name in self.views:
|
||||||
self.views[view_name].grid(row=0, column=1, sticky="nsew", padx=20, pady=20)
|
self.views[view_name].grid(row=0, column=1, sticky="nsew", padx=20, pady=20)
|
||||||
|
|
||||||
# ==========================================
|
# --- VUE : TABLEAU DE BORD ---
|
||||||
# MODULE : TABLEAU DE BORD
|
|
||||||
# ==========================================
|
|
||||||
def init_dashboard_view(self):
|
def init_dashboard_view(self):
|
||||||
frame = ctk.CTkFrame(self, fg_color="transparent")
|
frame = ctk.CTkFrame(self, fg_color="transparent")
|
||||||
self.views["dashboard"] = frame
|
self.views["dashboard"] = frame
|
||||||
@@ -110,12 +112,12 @@ class Antivirus7LnA(ctk.CTk):
|
|||||||
status_card = ctk.CTkFrame(frame, fg_color="#1E8449" if self.clamav_installed else "#C0392B", corner_radius=15)
|
status_card = ctk.CTkFrame(frame, fg_color="#1E8449" if self.clamav_installed else "#C0392B", corner_radius=15)
|
||||||
status_card.pack(fill="x", pady=10, ipady=20)
|
status_card.pack(fill="x", pady=10, ipady=20)
|
||||||
|
|
||||||
status_text = "Moteur ClamAV Connecté" if self.clamav_installed else "Moteur Hors Ligne"
|
status_text = "Moteur ClamAV Opérationnel" if self.clamav_installed else "Moteur ClamAV Introuvable"
|
||||||
ctk.CTkLabel(status_card, text=f"{'✅' if self.clamav_installed else '❌'} {status_text}", font=ctk.CTkFont(size=18, weight="bold"), text_color="white").pack(expand=True)
|
ctk.CTkLabel(status_card, text=f"{'✅' if self.clamav_installed else '❌'} {status_text}", font=ctk.CTkFont(size=18, weight="bold"), text_color="white").pack(expand=True)
|
||||||
|
|
||||||
|
ctk.CTkLabel(frame, text=f"📂 Dossier de quarantaine : {QUARANTINE_DIR}").pack(anchor="w", pady=10)
|
||||||
|
|
||||||
# ==========================================
|
# --- VUE : SCANNER MANUEL ---
|
||||||
# MODULE : SCANNER MANUEL
|
|
||||||
# ==========================================
|
|
||||||
def init_scanner_view(self):
|
def init_scanner_view(self):
|
||||||
frame = ctk.CTkFrame(self, fg_color="transparent")
|
frame = ctk.CTkFrame(self, fg_color="transparent")
|
||||||
frame.grid_rowconfigure(2, weight=1)
|
frame.grid_rowconfigure(2, weight=1)
|
||||||
@@ -124,26 +126,70 @@ class Antivirus7LnA(ctk.CTk):
|
|||||||
|
|
||||||
ctk.CTkLabel(frame, text="Analyse Antivirus Manuelle", font=ctk.CTkFont(size=24, weight="bold")).grid(row=0, column=0, columnspan=2, sticky="w", pady=(0, 20))
|
ctk.CTkLabel(frame, text="Analyse Antivirus Manuelle", font=ctk.CTkFont(size=24, weight="bold")).grid(row=0, column=0, columnspan=2, sticky="w", pady=(0, 20))
|
||||||
|
|
||||||
self.btn_scan_f = ctk.CTkButton(frame, text="📄 Analyser un Fichier", command=lambda: self.start_scan(is_dir=False), height=40)
|
self.btn_scan_f = ctk.CTkButton(frame, text="📄 Analyser un Fichier", command=lambda: self.start_manual_scan(is_dir=False), height=40)
|
||||||
self.btn_scan_f.grid(row=1, column=0, padx=(0, 10), sticky="ew")
|
self.btn_scan_f.grid(row=1, column=0, padx=(0, 10), sticky="ew")
|
||||||
|
|
||||||
self.btn_scan_d = ctk.CTkButton(frame, text="📁 Analyser un Dossier", command=lambda: self.start_scan(is_dir=True), height=40, fg_color="#2E86C1")
|
self.btn_scan_d = ctk.CTkButton(frame, text="📁 Analyser un Dossier", command=lambda: self.start_manual_scan(is_dir=True), height=40, fg_color="#2E86C1")
|
||||||
self.btn_scan_d.grid(row=1, column=1, padx=(10, 0), sticky="ew")
|
self.btn_scan_d.grid(row=1, column=1, padx=(10, 0), sticky="ew")
|
||||||
|
|
||||||
self.scan_console = ctk.CTkTextbox(frame, font=ctk.CTkFont(family="Consolas", size=13))
|
self.scan_console = ctk.CTkTextbox(frame, font=ctk.CTkFont(family="Consolas", size=13))
|
||||||
self.scan_console.grid(row=2, column=0, columnspan=2, pady=20, sticky="nsew")
|
self.scan_console.grid(row=2, column=0, columnspan=2, pady=20, sticky="nsew")
|
||||||
self.scan_console.insert("end", "[*] Prêt pour une analyse manuelle.\n")
|
self.scan_console.insert("end", "[*] Prêt. Les menaces seront automatiquement isolées.\n")
|
||||||
|
|
||||||
def start_scan(self, is_dir):
|
def start_manual_scan(self, is_dir):
|
||||||
path = filedialog.askdirectory() if is_dir else filedialog.askopenfilename()
|
path = filedialog.askdirectory() if is_dir else filedialog.askopenfilename()
|
||||||
if path:
|
if path:
|
||||||
threading.Thread(target=self.run_clamav_engine, args=(path, is_dir, self.scan_console), daemon=True).start()
|
threading.Thread(target=self.run_clamav_scan, args=(path, is_dir, self.scan_console), daemon=True).start()
|
||||||
|
|
||||||
def run_clamav_engine(self, path, is_dir, console):
|
# --- VUE : BOUCLIER TEMPS RÉEL ---
|
||||||
console.insert("end", f"\n🚀 Lancement de l'analyse sur : {path}\n")
|
def init_realtime_view(self):
|
||||||
|
frame = ctk.CTkFrame(self, fg_color="transparent")
|
||||||
|
frame.grid_rowconfigure(2, weight=1)
|
||||||
|
frame.grid_columnconfigure(0, weight=1)
|
||||||
|
self.views["shield"] = frame
|
||||||
|
|
||||||
|
header = ctk.CTkFrame(frame, fg_color="transparent")
|
||||||
|
header.grid(row=0, column=0, sticky="ew", pady=(0, 20))
|
||||||
|
|
||||||
|
ctk.CTkLabel(header, text="⚡ Bouclier Actif", font=ctk.CTkFont(size=24, weight="bold")).pack(side="left")
|
||||||
|
self.btn_toggle_shield = ctk.CTkButton(header, text="Activer le Bouclier", fg_color="#27AE60", hover_color="#1E8449", command=self.toggle_shield)
|
||||||
|
self.btn_toggle_shield.pack(side="right")
|
||||||
|
|
||||||
|
ctk.CTkLabel(frame, text=f"Surveillance en direct de : {WATCH_FOLDER}\nLes nouveaux fichiers seront scannés instantanément.", justify="left").grid(row=1, column=0, sticky="w", pady=(0, 10))
|
||||||
|
|
||||||
|
self.rt_console = ctk.CTkTextbox(frame, font=ctk.CTkFont(family="Consolas", size=13))
|
||||||
|
self.rt_console.grid(row=2, column=0, sticky="nsew")
|
||||||
|
self.rt_console.insert("end", "[-] Bouclier désactivé. Cliquez sur le bouton pour démarrer.\n")
|
||||||
|
|
||||||
|
def toggle_shield(self):
|
||||||
|
if not self.shield_active:
|
||||||
|
self.shield_observer = Observer()
|
||||||
|
self.shield_observer.schedule(RealTimeShieldHandler(self), WATCH_FOLDER, recursive=False)
|
||||||
|
self.shield_observer.start()
|
||||||
|
self.shield_active = True
|
||||||
|
self.btn_toggle_shield.configure(text="Désactiver le Bouclier", fg_color="#C0392B", hover_color="#922B21")
|
||||||
|
self.rt_console.insert("end", f"\n[+] BOUCLIER ACTIVÉ sur {WATCH_FOLDER}\n[*] Analyse automatique prête...\n")
|
||||||
|
else:
|
||||||
|
self.shield_observer.stop()
|
||||||
|
self.shield_active = False
|
||||||
|
self.btn_toggle_shield.configure(text="Activer le Bouclier", fg_color="#27AE60", hover_color="#1E8449")
|
||||||
|
self.rt_console.insert("end", "\n[-] Bouclier DÉSACTIVÉ.\n")
|
||||||
|
self.rt_console.see("end")
|
||||||
|
|
||||||
|
def trigger_realtime_scan(self, filepath):
|
||||||
|
self.rt_console.insert("end", f"\n⚡ Détection auto : {os.path.basename(filepath)}\n")
|
||||||
|
threading.Thread(target=self.run_clamav_scan, args=(filepath, False, self.rt_console), daemon=True).start()
|
||||||
|
|
||||||
|
# --- MOTEUR CLAMAV (Commun au Manuel et au Temps Réel) ---
|
||||||
|
def run_clamav_scan(self, path, is_dir, console):
|
||||||
|
if not self.clamav_installed:
|
||||||
|
console.insert("end", "❌ Erreur : ClamAV n'est pas installé.\n")
|
||||||
|
return
|
||||||
|
|
||||||
|
console.insert("end", f"[*] Début de l'analyse : {path}\n")
|
||||||
console.see("end")
|
console.see("end")
|
||||||
try:
|
try:
|
||||||
cmd = ['clamscan', '-i', '--no-summary', f'--move={self.quarantine_dir}']
|
cmd = ['clamscan', '-i', '--no-summary', f'--move={QUARANTINE_DIR}']
|
||||||
if is_dir: cmd.append('-r')
|
if is_dir: cmd.append('-r')
|
||||||
cmd.append(path)
|
cmd.append(path)
|
||||||
|
|
||||||
@@ -152,7 +198,7 @@ class Antivirus7LnA(ctk.CTk):
|
|||||||
for line in process.stdout:
|
for line in process.stdout:
|
||||||
clean_line = line.strip()
|
clean_line = line.strip()
|
||||||
if "FOUND" in clean_line:
|
if "FOUND" in clean_line:
|
||||||
console.insert("end", f"☠️ DANGER : {clean_line}\n🛡️ Fichier isolé en quarantaine.\n")
|
console.insert("end", f"☠️ DANGER : {clean_line}\n🛡️ Isolé en quarantaine.\n")
|
||||||
infected += 1
|
infected += 1
|
||||||
else:
|
else:
|
||||||
console.insert("end", clean_line + "\n")
|
console.insert("end", clean_line + "\n")
|
||||||
@@ -160,82 +206,79 @@ class Antivirus7LnA(ctk.CTk):
|
|||||||
|
|
||||||
process.wait()
|
process.wait()
|
||||||
if infected == 0:
|
if infected == 0:
|
||||||
console.insert("end", "✅ Analyse terminée. Système propre.\n")
|
console.insert("end", "[+] Analyse terminée. Fichier(s) propre(s).\n")
|
||||||
else:
|
else:
|
||||||
console.insert("end", f"🚨 {infected} menace(s) neutralisée(s) !\n")
|
console.insert("end", f"🚨 {infected} menace(s) neutralisée(s) !\n")
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
console.insert("end", f"❌ Erreur : {e}\n")
|
console.insert("end", f"❌ Erreur système : {e}\n")
|
||||||
console.see("end")
|
console.see("end")
|
||||||
|
|
||||||
# ==========================================
|
# --- VUE : AUDIT SYSTÈME ---
|
||||||
# MODULE : BOUCLIER TEMPS RÉEL (NOUVEAU)
|
def init_audit_view(self):
|
||||||
# ==========================================
|
|
||||||
def init_realtime_view(self):
|
|
||||||
frame = ctk.CTkFrame(self, fg_color="transparent")
|
frame = ctk.CTkFrame(self, fg_color="transparent")
|
||||||
frame.grid_rowconfigure(2, weight=1)
|
frame.grid_rowconfigure(1, weight=1)
|
||||||
frame.grid_columnconfigure(0, weight=1)
|
frame.grid_columnconfigure(0, weight=1)
|
||||||
self.views["realtime"] = frame
|
self.views["audit"] = frame
|
||||||
|
|
||||||
header = ctk.CTkFrame(frame, fg_color="transparent")
|
header = ctk.CTkFrame(frame, fg_color="transparent")
|
||||||
header.grid(row=0, column=0, sticky="ew", pady=(0, 20))
|
header.grid(row=0, column=0, sticky="ew", pady=(0, 20))
|
||||||
|
|
||||||
ctk.CTkLabel(header, text="⚡ Bouclier Actif (Temps Réel)", font=ctk.CTkFont(size=24, weight="bold")).pack(side="left")
|
ctk.CTkLabel(header, text="Vérification des Vulnérabilités", font=ctk.CTkFont(size=24, weight="bold")).pack(side="left")
|
||||||
|
ctk.CTkButton(header, text="Lancer l'Audit", command=self.run_audit_thread).pack(side="right")
|
||||||
self.btn_toggle_shield = ctk.CTkButton(header, text="Activer le Bouclier", fg_color="#27AE60", hover_color="#1E8449", command=self.toggle_shield)
|
|
||||||
self.btn_toggle_shield.pack(side="right")
|
|
||||||
|
|
||||||
info_text = f"Dossier surveillé en permanence : {self.watch_folder}\nTout nouveau fichier sera scanné et neutralisé automatiquement."
|
self.audit_console = ctk.CTkTextbox(frame, font=ctk.CTkFont(family="Consolas", size=13))
|
||||||
ctk.CTkLabel(frame, text=info_text, justify="left").grid(row=1, column=0, sticky="w", pady=(0, 10))
|
self.audit_console.grid(row=1, column=0, sticky="nsew")
|
||||||
|
|
||||||
self.rt_console = ctk.CTkTextbox(frame, font=ctk.CTkFont(family="Consolas", size=13))
|
def run_audit_thread(self):
|
||||||
self.rt_console.grid(row=2, column=0, sticky="nsew")
|
self.audit_console.delete("0.0", "end")
|
||||||
self.rt_console.insert("end", "[-] Bouclier désactivé. Cliquez sur le bouton pour l'activer.\n")
|
threading.Thread(target=self.perform_audit, daemon=True).start()
|
||||||
|
|
||||||
def toggle_shield(self):
|
def perform_audit(self):
|
||||||
if not self.shield_active:
|
self.audit_console.insert("end", "[*] Ports réseaux ouverts (Recherche de Backdoors)...\n")
|
||||||
# Activer
|
try:
|
||||||
event_handler = RealTimeShieldHandler(self)
|
self.audit_console.insert("end", subprocess.check_output(['ss', '-tuln'], text=True))
|
||||||
self.shield_observer = Observer()
|
except Exception:
|
||||||
self.shield_observer.schedule(event_handler, self.watch_folder, recursive=False)
|
self.audit_console.insert("end", "[-] Impossible de lire le réseau.\n")
|
||||||
self.shield_observer.start()
|
|
||||||
|
|
||||||
self.shield_active = True
|
self.audit_console.insert("end", "\n[*] Top 10 des processus gourmands...\n")
|
||||||
self.btn_toggle_shield.configure(text="Désactiver le Bouclier", fg_color="#C0392B", hover_color="#922B21")
|
try:
|
||||||
self.rt_console.insert("end", f"\n[+] Bouclier ACTIVÉ sur {self.watch_folder}\n[*] En attente de nouveaux fichiers...\n")
|
res = subprocess.check_output(['ps', '-eo', 'pid,user,%cpu,%mem,cmd', '--sort=-%cpu'], text=True)
|
||||||
else:
|
self.audit_console.insert("end", "\n".join(res.split('\n')[:11]) + "\n")
|
||||||
# Désactiver
|
except Exception:
|
||||||
self.shield_observer.stop()
|
self.audit_console.insert("end", "[-] Impossible de lire les processus.\n")
|
||||||
self.shield_observer.join()
|
|
||||||
self.shield_active = False
|
|
||||||
self.btn_toggle_shield.configure(text="Activer le Bouclier", fg_color="#27AE60", hover_color="#1E8449")
|
|
||||||
self.rt_console.insert("end", "\n[-] Bouclier DÉSACTIVÉ.\n")
|
|
||||||
self.rt_console.see("end")
|
|
||||||
|
|
||||||
def trigger_realtime_scan(self, filepath):
|
|
||||||
"""Appelé automatiquement quand un nouveau fichier apparaît."""
|
|
||||||
self.rt_console.insert("end", f"\n⚡ Nouveau fichier détecté : {os.path.basename(filepath)}\n")
|
|
||||||
self.rt_console.insert("end", "[*] Analyse instantanée en cours...\n")
|
|
||||||
self.rt_console.see("end")
|
|
||||||
|
|
||||||
# On lance le scan dans un thread pour ne pas bloquer l'interface
|
|
||||||
threading.Thread(target=self.run_clamav_engine, args=(filepath, False, self.rt_console), daemon=True).start()
|
|
||||||
|
|
||||||
# ==========================================
|
|
||||||
# MODULES : AUDIT & UPDATE (Abregés pour l'exemple)
|
|
||||||
# ==========================================
|
|
||||||
def init_audit_view(self):
|
|
||||||
frame = ctk.CTkFrame(self, fg_color="transparent")
|
|
||||||
self.views["audit"] = frame
|
|
||||||
ctk.CTkLabel(frame, text="Audit Système", font=ctk.CTkFont(size=24, weight="bold")).pack(anchor="w")
|
|
||||||
ctk.CTkLabel(frame, text="Interface d'audit maintenue...").pack(pady=20)
|
|
||||||
|
|
||||||
|
# --- VUE : MISE À JOUR (OTA) ---
|
||||||
def init_update_view(self):
|
def init_update_view(self):
|
||||||
frame = ctk.CTkFrame(self, fg_color="transparent")
|
frame = ctk.CTkFrame(self, fg_color="transparent")
|
||||||
self.views["update"] = frame
|
self.views["update"] = frame
|
||||||
ctk.CTkLabel(frame, text="Mise à jour (FreshClam)", font=ctk.CTkFont(size=24, weight="bold")).pack(anchor="w")
|
|
||||||
ctk.CTkLabel(frame, text="Utilisez 'sudo freshclam' dans le terminal.").pack(pady=20)
|
ctk.CTkLabel(frame, text="Mises à jour de 7LnA", font=ctk.CTkFont(size=24, weight="bold")).pack(anchor="w", pady=(0, 20))
|
||||||
|
ctk.CTkLabel(frame, text="Vérifiez si une nouvelle version est disponible sur le dépôt officiel.\nL'application se mettra à jour automatiquement.", justify="left").pack(anchor="w", pady=10)
|
||||||
|
|
||||||
|
self.btn_update = ctk.CTkButton(frame, text="⬇️ Télécharger la dernière version", command=self.run_software_update, fg_color="#8E44AD", hover_color="#732D91")
|
||||||
|
self.btn_update.pack(anchor="w", pady=20)
|
||||||
|
|
||||||
|
self.update_console = ctk.CTkTextbox(frame, height=150, font=ctk.CTkFont(family="Consolas", size=13))
|
||||||
|
self.update_console.pack(fill="x", pady=10)
|
||||||
|
|
||||||
|
def run_software_update(self):
|
||||||
|
self.btn_update.configure(state="disabled")
|
||||||
|
self.update_console.insert("end", "[*] Connexion au serveur Git...\n")
|
||||||
|
|
||||||
|
try:
|
||||||
|
# os.path.abspath(__file__) trouve automatiquement le chemin exact du fichier en cours d'exécution
|
||||||
|
current_file_path = os.path.abspath(__file__)
|
||||||
|
urllib.request.urlretrieve(UPDATE_URL, current_file_path)
|
||||||
|
|
||||||
|
self.update_console.insert("end", "[+] Mise à jour téléchargée et appliquée !\n")
|
||||||
|
messagebox.showinfo("Mise à jour", "7LnA a été mis à jour avec succès. L'application va se fermer pour appliquer les changements.")
|
||||||
|
self.destroy()
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
self.update_console.insert("end", f"[-] Échec de la mise à jour : {e}\n")
|
||||||
|
self.btn_update.configure(state="normal")
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
app = Antivirus7LnA()
|
app = Antivirus7LnA()
|
||||||
app.mainloop()
|
app.mainloop()
|
||||||
Reference in New Issue
Block a user