diff --git a/cpu_monitor.py b/cpu_monitor.py index 2b84c6b..5b5180f 100644 --- a/cpu_monitor.py +++ b/cpu_monitor.py @@ -7,10 +7,15 @@ import time import psutil -def format_line() -> str: - now = datetime.now().strftime("%H:%M:%S") +def get_cpu_ram() -> tuple[float, float]: cpu = psutil.cpu_percent(interval=None) ram = psutil.virtual_memory().percent + return cpu, ram + + +def format_line() -> str: + now = datetime.now().strftime("%H:%M:%S") + cpu, ram = get_cpu_ram() return f"{now} | CPU: {cpu:5.1f}% | RAM: {ram:5.1f}%" diff --git a/cpu_monitor_gui.py b/cpu_monitor_gui.py new file mode 100644 index 0000000..3b74824 --- /dev/null +++ b/cpu_monitor_gui.py @@ -0,0 +1,170 @@ +#!/usr/bin/env python3 +# Lancement: python cpu_monitor_gui.py + +import tkinter as tk +from tkinter import ttk +from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg, NavigationToolbar2Tk +from matplotlib.figure import Figure +from collections import deque +import time + +import psutil + +MAX_POINTS = 60 +UPDATE_INTERVAL = 1000 # ms + + +class CPUTracker: + def __init__(self): + self.cpu_data = deque(maxlen=MAX_POINTS) + self.ram_data = deque(maxlen=MAX_POINTS) + self.time_data = deque(maxlen=MAX_POINTS) + self._last_cpu = None + now = time.time() + self.time_data.append(now) + + def update(self): + cpu = psutil.cpu_percent(interval=None) + ram = psutil.virtual_memory().percent + self._last_cpu = cpu + t = time.time() + + self.cpu_data.append(cpu) + self.ram_data.append(ram) + self.time_data.append(t) + + def get_latest(self): + if self._last_cpu is None: + self.update() + return self._last_cpu, self.ram_data[-1] + + +class App: + def __init__(self, root): + self.root = root + self.root.title("CPU / RAM Monitor") + + self.tracker = CPUTracker() + + # --- Header card --- + card_bg = "#23272f" + card_fg = "#ffffff" + accent = "#4fc3f7" + + header_frame = ttk.Frame(root) + header_frame.pack(fill=tk.X, padx=10, pady=(10, 0)) + + self.cpu_label = ttk.Label( + header_frame, + text=f"CPU: --%", + font=("Segoe UI", 20, "bold"), + foreground=accent, + ) + self.cpu_label.pack(side=tk.LEFT, padx=20) + + self.ram_label = ttk.Label( + header_frame, + text=f"RAM: --%", + font=("Segoe UI", 20, "bold"), + foreground="#81c784", + ) + self.ram_label.pack(side=tk.LEFT, padx=20) + + # --- Plot --- + fig = Figure(figsize=(8, 3), facecolor=card_bg) + ax_cpu = fig.add_subplot(1, 2, 1, facecolor=card_bg) + ax_ram = fig.add_subplot(1, 2, 2, facecolor=card_bg) + + ax_cpu.set_title("CPU %", color=card_fg, fontsize=11) + ax_ram.set_title("RAM %", color=card_fg, fontsize=11) + ax_cpu.set_ylim(0, 100) + ax_ram.set_ylim(0, 100) + ax_cpu.set_ylabel("%") + ax_ram.set_ylabel("%") + ax_cpu.tick_params(colors="#aaa") + ax_ram.tick_params(colors="#aaa") + for label in ax_cpu.get_yticklabels(): + label.set_color("#aaa") + for line in ax_cpu.spines.values(): + line.set_color("#3a3f4a") + for line in ax_ram.spines.values(): + line.set_color("#3a3f4a") + + self.cpu_line, = ax_cpu.plot( + [], [], color="#ef5350", linewidth=1.5, marker="", markerfacecolor="#ef5350" + ) + self.ram_line, = ax_ram.plot( + [], [], color="#66bb6a", linewidth=1.5, marker="", markerfacecolor="#66bb6a" + ) + + ax_cpu.axhline(y=80, color="#ef5350", linestyle="--", alpha=0.4) + ax_ram.axhline(y=80, color="#66bb6a", linestyle="--", alpha=0.4) + ax_cpu.text(0.02, 0.02, "80%", fontsize=8, color="#ef5350", alpha=0.6, transform=ax_cpu.transAxes) + + self.fig = fig + self.ax_cpu = ax_cpu + self.ax_ram = ax_ram + + canvas = FigureCanvasTkAgg(fig, master=root) + canvas.draw() + canvas.get_tk_widget().pack(fill=tk.BOTH, expand=True, padx=10, pady=10) + + toolbar = NavigationToolbar2Tk(canvas, root) + toolbar.update() + + # --- Footer status --- + status_frame = ttk.Frame(root) + status_frame.pack(fill=tk.X, padx=10, pady=(0, 10)) + + self.status_label = ttk.Label( + status_frame, + text="Monitoring...", + font=("Segoe UI", 9), + foreground="#888", + ) + self.status_label.pack(side=tk.LEFT) + + stop_btn = ttk.Button( + status_frame, + text="Stop", + command=self._stop, + width=10, + ) + stop_btn.pack(side=tk.RIGHT, padx=(10, 0)) + + self._running = True + self._refresh() + + def _refresh(self): + if not self._running: + return + self.tracker.update() + cpu, ram = self.tracker.get_latest() + self.cpu_label.config(text=f"CPU: {cpu:5.1f}%") + self.ram_label.config(text=f"RAM: {ram:5.1f}%") + + ax = self.ax_cpu + cpu_arr = list(self.tracker.cpu_data) + ram_arr = list(self.tracker.ram_data) + self.cpu_line.set_data(range(len(cpu_arr)), cpu_arr) + self.ram_line.set_data(range(len(ram_arr)), ram_arr) + + ax.set_xlim(0, MAX_POINTS) + self.ax_ram.set_xlim(0, MAX_POINTS) + + self.fig.canvas.draw_idle() + self.root.after(UPDATE_INTERVAL, self._refresh) + + def _stop(self): + self._running = False + self.status_label.config(text="Stopped.") + + +def main(): + root = tk.Tk() + app = App(root) + root.mainloop() + + +if __name__ == "__main__": + main() diff --git a/requirements.txt b/requirements.txt index a4d92cc..8549cfa 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1 +1,2 @@ psutil +matplotlib diff --git a/toto.py b/toto.py new file mode 100644 index 0000000..8dbe344 --- /dev/null +++ b/toto.py @@ -0,0 +1,47 @@ +import re +from flask import Flask, request, make_response +from markupsafe import escape + +app = Flask(__name__) + +# Limiter la taille maximale des requêtes pour éviter le DoS +app.config['MAX_CONTENT_LENGTH'] = 1 * 1024 * 1024 # 1 Mo + + +def add_security_headers(response): + response.headers['X-Content-Type-Options'] = 'nosniff' + response.headers['X-Frame-Options'] = 'DENY' + response.headers['Content-Type'] = 'text/html; charset=utf-8' + return response + + +@app.after_request +def after_request(response): + return add_security_headers(response) + + +@app.route('/hello', methods=['GET']) +def hello(): + name = request.args.get('name', '') + + if not name: + resp = make_response("Hello Guest", 200) + return resp + + # 1. Longueur max pour éviter les attaques par déni de service + if len(name) > 100: + return "Erreur : Le nom est trop long", 400 + + # 2. Validation stricte : uniquement alphanumérique + if not re.match(r'^[a-zA-Z0-9]+$', name): + return "Erreur : Le nom contient des caractères interdits", 400 + + # 3. Échappement XSS + safe_name = escape(name) + + resp = make_response(f"Hello {safe_name}", 200) + return resp + + +if __name__ == '__main__': + app.run(debug=False)