197 lines
9.1 KiB
Python
197 lines
9.1 KiB
Python
#!/usr/bin/env python3
|
|
import tkinter as tk
|
|
from tkinter import ttk, scrolledtext
|
|
import subprocess
|
|
import re
|
|
|
|
class ZorinDiskHealthV4:
|
|
def __init__(self, root):
|
|
self.root = root
|
|
self.root.title("Zorin Disk Health 4.1 - GOD MODE (Fixed)")
|
|
self.root.geometry("900x750")
|
|
self.root.minsize(850, 700)
|
|
|
|
# Couleurs Premium Dark Zorin
|
|
self.bg_dark = "#09090b"
|
|
self.bg_panel = "#18181b"
|
|
self.text_light = "#fafafa"
|
|
self.text_dim = "#a1a1aa"
|
|
self.accent = "#3b82f6"
|
|
self.success = "#10b981"
|
|
self.warn = "#f59e0b"
|
|
self.danger = "#ef4444"
|
|
|
|
self.root.configure(bg=self.bg_dark)
|
|
|
|
self.current_health = 0
|
|
self.target_health = 0
|
|
self.current_temp = 0
|
|
self.target_temp = 0
|
|
|
|
self.create_ui()
|
|
self.refresh_disks()
|
|
|
|
def create_ui(self):
|
|
header = tk.Frame(self.root, bg=self.bg_dark, pady=25)
|
|
header.pack(fill=tk.X, padx=40)
|
|
tk.Label(header, text="Zorin Disk Health", font=("Helvetica", 28, "bold"), fg=self.text_light, bg=self.bg_dark).pack(side=tk.LEFT)
|
|
tk.Label(header, text="v4.1 PRO", font=("Helvetica", 12, "bold"), fg=self.accent, bg=self.bg_dark).pack(side=tk.LEFT, padx=15, pady=12)
|
|
|
|
controls = tk.Frame(self.root, bg=self.bg_panel, padx=25, pady=20, highlightthickness=1, highlightbackground="#27272a")
|
|
controls.pack(fill=tk.X, padx=40, pady=10)
|
|
|
|
tk.Label(controls, text="Sélectionnez le disque :", bg=self.bg_panel, fg=self.text_light, font=("Helvetica", 11, "bold")).pack(side=tk.LEFT)
|
|
self.disk_var = tk.StringVar()
|
|
self.disk_combo = ttk.Combobox(controls, textvariable=self.disk_var, width=40, state="readonly", font=("Helvetica", 10))
|
|
self.disk_combo.pack(side=tk.LEFT, padx=15)
|
|
|
|
self.btn_analyze = tk.Button(controls, text="DÉMARRER L'ANALYSE", command=self.start_analysis, bg=self.accent, fg="white", font=("Helvetica", 11, "bold"), bd=0, padx=25, pady=10, cursor="hand2")
|
|
self.btn_analyze.pack(side=tk.RIGHT)
|
|
|
|
dash_frame = tk.Frame(self.root, bg=self.bg_dark)
|
|
dash_frame.pack(fill=tk.X, padx=40, pady=30)
|
|
|
|
self.c_health = tk.Canvas(dash_frame, width=250, height=250, bg=self.bg_dark, highlightthickness=0)
|
|
self.c_health.pack(side=tk.LEFT, expand=True)
|
|
self.draw_ring(self.c_health, 125, 125, 100, 18, 0, "#27272a", "0%", "SANTÉ")
|
|
|
|
self.c_temp = tk.Canvas(dash_frame, width=250, height=250, bg=self.bg_dark, highlightthickness=0)
|
|
self.c_temp.pack(side=tk.LEFT, expand=True)
|
|
self.draw_ring(self.c_temp, 125, 125, 100, 18, 0, "#27272a", "0°C", "TEMPÉRATURE")
|
|
|
|
self.log_area = scrolledtext.ScrolledText(self.root, wrap=tk.WORD, font=("Consolas", 10), bg="#0f0f11", fg="#34d399", bd=1, highlightthickness=1, highlightbackground="#27272a", padx=20, pady=20)
|
|
self.log_area.pack(fill=tk.BOTH, expand=True, padx=40, pady=(0, 40))
|
|
self.log_area.insert(tk.END, "✓ Zorin OS Mode activé.\n✓ Moteur graphique prêt.\n")
|
|
|
|
def draw_ring(self, canvas, x, y, radius, thickness, percentage, color, text_main, text_sub):
|
|
canvas.delete("all")
|
|
canvas.create_oval(x-radius, y-radius, x+radius, y+radius, outline="#27272a", width=thickness)
|
|
if percentage > 0:
|
|
extent = -(percentage / 100) * 360
|
|
canvas.create_arc(x-radius, y-radius, x+radius, y+radius, start=90, extent=extent, style=tk.ARC, outline=color, width=thickness)
|
|
canvas.create_text(x, y-15, text=text_main, fill=self.text_light, font=("Helvetica", 34, "bold"))
|
|
canvas.create_text(x, y+25, text=text_sub, fill=self.text_dim, font=("Helvetica", 12, "bold"))
|
|
|
|
def animate_health(self, color, text_sub):
|
|
if abs(self.target_health - self.current_health) < 0.5:
|
|
self.current_health = self.target_health
|
|
else:
|
|
self.current_health += (self.target_health - self.current_health) * 0.1
|
|
self.draw_ring(self.c_health, 125, 125, 100, 18, self.current_health, color, f"{int(self.current_health)}%", text_sub)
|
|
if self.current_health != self.target_health:
|
|
self.root.after(16, self.animate_health, color, text_sub)
|
|
|
|
def animate_temp(self, color, text_sub):
|
|
if abs(self.target_temp - self.current_temp) < 0.5:
|
|
self.current_temp = self.target_temp
|
|
else:
|
|
self.current_temp += (self.target_temp - self.current_temp) * 0.1
|
|
fill_pct = min((self.current_temp / 70) * 100, 100)
|
|
self.draw_ring(self.c_temp, 125, 125, 100, 18, fill_pct, color, f"{int(self.current_temp)}°C", text_sub)
|
|
if self.current_temp != self.target_temp:
|
|
self.root.after(16, self.animate_temp, color, text_sub)
|
|
|
|
def refresh_disks(self):
|
|
try:
|
|
result = subprocess.run(['lsblk', '-d', '-p', '-n', '-o', 'NAME,SIZE,MODEL'], capture_output=True, text=True)
|
|
disks = [line.strip() for line in result.stdout.split('\n') if line.strip()]
|
|
self.disk_combo['values'] = disks if disks else ["/dev/sda"]
|
|
self.disk_combo.current(0)
|
|
except Exception:
|
|
pass
|
|
|
|
def log(self, msg):
|
|
self.log_area.insert(tk.END, msg + "\n")
|
|
self.log_area.see(tk.END)
|
|
self.root.update()
|
|
|
|
def start_analysis(self):
|
|
disk = self.disk_var.get().split()[0]
|
|
self.btn_analyze.config(text="ANALYSE EN COURS...", state=tk.DISABLED)
|
|
|
|
self.current_health, self.target_health = 0, 0
|
|
self.current_temp, self.target_temp = 0, 0
|
|
self.draw_ring(self.c_health, 125, 125, 100, 18, 0, "#27272a", "0%", "SANTÉ")
|
|
self.draw_ring(self.c_temp, 125, 125, 100, 18, 0, "#27272a", "0°C", "TEMPÉRATURE")
|
|
|
|
self.log_area.delete(1.0, tk.END)
|
|
self.log(f"🔍 Démarrage sur {disk}...")
|
|
self.log("⚠️ Le système va vous demander votre mot de passe pour autoriser le test matériel.")
|
|
|
|
self.root.after(100, self.brute_force_samsung, disk)
|
|
|
|
def brute_force_samsung(self, disk):
|
|
# Le "Super-Script" qui teste les 8 protocoles en 1 seule demande administrateur
|
|
bash_script = f'''
|
|
for d in "" "sat" "nvme" "scsi" "samsung" "sntrealtek" "sntjmicron" "usbjmicron"; do
|
|
if [ -z "$d" ]; then
|
|
out=$(smartctl -A -H -T permissive {disk} 2>/dev/null)
|
|
else
|
|
out=$(smartctl -d "$d" -A -H -T permissive {disk} 2>/dev/null)
|
|
fi
|
|
if echo "$out" | grep -q -iE "Temperature|PASSED"; then
|
|
echo "BINGO:$d"
|
|
echo "$out"
|
|
exit 0
|
|
fi
|
|
done
|
|
echo "FAILED"
|
|
'''
|
|
|
|
cmd = ["pkexec", "bash", "-c", bash_script]
|
|
try:
|
|
self.log("⚡ Analyse des contrôleurs USB en arrière-plan...")
|
|
res = subprocess.run(cmd, capture_output=True, text=True)
|
|
out = res.stdout
|
|
|
|
if "BINGO:" in out:
|
|
driver = out.split("\n")[0].split(":")[1].strip()
|
|
drv_name = driver if driver else "Auto"
|
|
self.log(f"🎯 Succès ! Protection Samsung contournée (Pilote: {drv_name}).")
|
|
self.log("\n📊 Décodage des puces mémoire...\n")
|
|
self.parse_and_animate(out)
|
|
elif "pkexec" in res.stderr or res.returncode == 127:
|
|
self.log("❌ Action annulée : Mot de passe requis pour lire la santé physique du disque.")
|
|
self.btn_analyze.config(text="DÉMARRER L'ANALYSE", state=tk.NORMAL)
|
|
else:
|
|
self.log("❌ ÉCHEC. Le câble USB bloque absolument toutes les requêtes matérielles.")
|
|
self.btn_analyze.config(text="DÉMARRER L'ANALYSE", state=tk.NORMAL)
|
|
|
|
except Exception as e:
|
|
self.log(f"Erreur : {e}")
|
|
self.btn_analyze.config(text="DÉMARRER L'ANALYSE", state=tk.NORMAL)
|
|
|
|
def parse_and_animate(self, data):
|
|
health_val = 0
|
|
health_color = self.danger
|
|
h_text = "CRITIQUE"
|
|
|
|
if "PASSED" in data or "OK" in data:
|
|
health_val = 100
|
|
health_color = self.success
|
|
h_text = "EXCELLENTE"
|
|
p1 = re.search(r"Percentage Used:\s+(\d+)%", data)
|
|
if p1: health_val = 100 - int(p1.group(1))
|
|
|
|
self.target_health = health_val
|
|
self.animate_health(health_color, h_text)
|
|
|
|
temp_val = 0
|
|
t1 = re.search(r"Temperature:\s+(\d+)\s+Celsius", data)
|
|
t2 = re.search(r"194 Temperature_Celsius.*\s+(\d+)\s*$", data, re.MULTILINE)
|
|
if t1: temp_val = int(t1.group(1))
|
|
elif t2: temp_val = int(t2.group(1))
|
|
|
|
if temp_val > 0:
|
|
t_color = self.accent if temp_val < 45 else (self.warn if temp_val < 55 else self.danger)
|
|
t_text = "FRAIS" if temp_val < 45 else ("CHAUD" if temp_val < 55 else "SURCHAUFFE")
|
|
self.target_temp = temp_val
|
|
self.animate_temp(t_color, t_text)
|
|
|
|
self.btn_analyze.config(text="DÉMARRER L'ANALYSE", state=tk.NORMAL)
|
|
|
|
if __name__ == "__main__":
|
|
root = tk.Tk()
|
|
app = ZorinDiskHealthV4(root)
|
|
root.mainloop()
|