fix: changelog embarqué manquant, badge hors-ligne trompeur, installeur WireGuard
- CHANGELOG.md n'était pas empaqueté par PyInstaller (datas=[]) et son chemin, calculé depuis __file__, ne survivait pas à l'extraction onefile : la page « À propos » restait vide une fois compilée. Le fichier est désormais embarqué (--add-data) et son chemin bascule sur sys._MEIPASS en mode frozen. - Le badge de latence se basait uniquement sur un ping ICMP vers l'endpoint : de nombreux serveurs/pare-feux le bloquent alors que le tunnel WireGuard fonctionne, d'où « hors ligne » permanent. Repli sur l'âge du dernier handshake réel quand l'ICMP échoue. - wgsecure.iss installe désormais WireGuard for Windows en silencieux (prérequis manquant jusqu'ici), au même titre que le VC++ Redistributable ; make installer-deps télécharge les deux binaires.
This commit is contained in:
@@ -27,7 +27,7 @@ PI_OPTS := \
|
|||||||
--hidden-import cryptography.hazmat.primitives.asymmetric.x25519 \
|
--hidden-import cryptography.hazmat.primitives.asymmetric.x25519 \
|
||||||
--collect-submodules PyQt6
|
--collect-submodules PyQt6
|
||||||
|
|
||||||
.PHONY: all linux windows release version changelog install install-gnome uninstall-gnome run run-admin icon reset-password setup-sudoers check-privileges clean clean-all help venv
|
.PHONY: all linux windows installer-deps release version changelog install install-gnome uninstall-gnome run run-admin icon reset-password setup-sudoers check-privileges clean clean-all help venv
|
||||||
|
|
||||||
# ── Cible par défaut ────────────────────────────────────────────────────────
|
# ── Cible par défaut ────────────────────────────────────────────────────────
|
||||||
all: linux
|
all: linux
|
||||||
@@ -69,6 +69,7 @@ linux: install icon
|
|||||||
$(PYTHON) -m PyInstaller $(PI_OPTS) \
|
$(PYTHON) -m PyInstaller $(PI_OPTS) \
|
||||||
--onefile \
|
--onefile \
|
||||||
--icon=$(ICON) \
|
--icon=$(ICON) \
|
||||||
|
--add-data "CHANGELOG.md:." \
|
||||||
$(SRC)
|
$(SRC)
|
||||||
@echo ""
|
@echo ""
|
||||||
@echo " ✅ Binaire Linux → $(DIST)/$(APP)"
|
@echo " ✅ Binaire Linux → $(DIST)/$(APP)"
|
||||||
@@ -97,6 +98,7 @@ windows: icon
|
|||||||
--icon=$(ICON) \
|
--icon=$(ICON) \
|
||||||
--add-data "$(WINE_QT_PLUGINS)/platforms;PyQt6/Qt6/plugins/platforms" \
|
--add-data "$(WINE_QT_PLUGINS)/platforms;PyQt6/Qt6/plugins/platforms" \
|
||||||
--add-data "$(WINE_QT_PLUGINS)/styles;PyQt6/Qt6/plugins/styles" \
|
--add-data "$(WINE_QT_PLUGINS)/styles;PyQt6/Qt6/plugins/styles" \
|
||||||
|
--add-data "CHANGELOG.md;." \
|
||||||
$(SRC) \
|
$(SRC) \
|
||||||
|| (echo ""; \
|
|| (echo ""; \
|
||||||
echo " ❌ Échec : Python Windows introuvable dans Wine."; \
|
echo " ❌ Échec : Python Windows introuvable dans Wine."; \
|
||||||
@@ -106,6 +108,25 @@ windows: icon
|
|||||||
@echo " ✅ Binaire Windows → $(DIST)/$(APP).exe"
|
@echo " ✅ Binaire Windows → $(DIST)/$(APP).exe"
|
||||||
@echo ""
|
@echo ""
|
||||||
|
|
||||||
|
# ── Prérequis de l'installeur Windows (wgsecure.iss) ─────────────────────────
|
||||||
|
# WireGuard n'est pas empaqueté avec WGSecure (c'est wg.exe et le pilote
|
||||||
|
# tunnel qui manquent, pas une simple DLL) : wgsecure.iss l'installe donc en
|
||||||
|
# silencieux à partir de ce binaire, téléchargé ici une bonne fois pour
|
||||||
|
# toutes plutôt que d'imposer une étape manuelle avant chaque compilation.
|
||||||
|
WIREGUARD_URL := https://download.wireguard.com/windows-client/wireguard-installer.exe
|
||||||
|
VCREDIST_URL := https://aka.ms/vs/17/release/vc_redist.x64.exe
|
||||||
|
|
||||||
|
installer/wireguard-installer.exe:
|
||||||
|
@echo " ⬇️ Téléchargement de l'installeur WireGuard…"
|
||||||
|
@curl -L --fail -o $@ $(WIREGUARD_URL)
|
||||||
|
|
||||||
|
installer/VC_redist.x64.exe:
|
||||||
|
@echo " ⬇️ Téléchargement du Visual C++ Redistributable…"
|
||||||
|
@curl -L --fail -o $@ $(VCREDIST_URL)
|
||||||
|
|
||||||
|
installer-deps: installer/wireguard-installer.exe installer/VC_redist.x64.exe
|
||||||
|
@echo " ✅ Prérequis de l'installeur prêts dans installer/"
|
||||||
|
|
||||||
# ── Installation de Python dans Wine ─────────────────────────────────────────
|
# ── Installation de Python dans Wine ─────────────────────────────────────────
|
||||||
WINE_PY_VER := 3.11.9
|
WINE_PY_VER := 3.11.9
|
||||||
WINE_PY_URL := https://www.python.org/ftp/python/$(WINE_PY_VER)/python-$(WINE_PY_VER)-amd64.exe
|
WINE_PY_URL := https://www.python.org/ftp/python/$(WINE_PY_VER)/python-$(WINE_PY_VER)-amd64.exe
|
||||||
@@ -272,6 +293,7 @@ help:
|
|||||||
@echo " ║ make install Installe les dépendances ║"
|
@echo " ║ make install Installe les dépendances ║"
|
||||||
@echo " ║ make linux Binaire Linux (onefile) ║"
|
@echo " ║ make linux Binaire Linux (onefile) ║"
|
||||||
@echo " ║ make windows Binaire Windows (Wine) ║"
|
@echo " ║ make windows Binaire Windows (Wine) ║"
|
||||||
|
@echo " ║ make installer-deps Prérequis wgsecure.iss ║"
|
||||||
@echo " ║ make release Linux + nommage release ║"
|
@echo " ║ make release Linux + nommage release ║"
|
||||||
@echo " ║ make version Affiche la version ║"
|
@echo " ║ make version Affiche la version ║"
|
||||||
@echo " ║ make changelog Dernière entrée changelog║"
|
@echo " ║ make changelog Dernière entrée changelog║"
|
||||||
|
|||||||
@@ -7,9 +7,18 @@ seul endroit où elle est bumpée à chaque release — jamais recopiée en dur
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
import os
|
import os
|
||||||
|
import sys
|
||||||
|
|
||||||
from app import __version__
|
from app import __version__
|
||||||
|
|
||||||
|
# En développement, CHANGELOG.md vit à la racine du dépôt, deux niveaux
|
||||||
|
# au-dessus de ce fichier. Une fois empaqueté par PyInstaller (--onefile),
|
||||||
|
# `__file__` pointe vers l'intérieur de l'exécutable et ce chemin n'existe
|
||||||
|
# plus : le fichier doit alors être cherché dans `sys._MEIPASS`, le dossier
|
||||||
|
# temporaire où l'exe extrait les données embarquées via `--add-data`.
|
||||||
|
if getattr(sys, "frozen", False):
|
||||||
|
_CHANGELOG_PATH = os.path.join(getattr(sys, "_MEIPASS", ""), "CHANGELOG.md")
|
||||||
|
else:
|
||||||
_CHANGELOG_PATH = os.path.join(
|
_CHANGELOG_PATH = os.path.join(
|
||||||
os.path.dirname(os.path.dirname(os.path.abspath(__file__))), "CHANGELOG.md"
|
os.path.dirname(os.path.dirname(os.path.abspath(__file__))), "CHANGELOG.md"
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -994,6 +994,34 @@ def ping_server(host: str, timeout: int = 2) -> int | None:
|
|||||||
return 0
|
return 0
|
||||||
|
|
||||||
|
|
||||||
|
#: Au-delà de cet âge (s), un handshake est considéré trop ancien pour
|
||||||
|
#: garantir que le tunnel répond encore (keepalive par défaut : 25 s).
|
||||||
|
_HANDSHAKE_STALE_S = 150
|
||||||
|
|
||||||
|
|
||||||
|
def ping_or_handshake(cfg: Config, timeout: int = 2) -> tuple[int | None, str]:
|
||||||
|
"""Latence ICMP vers l'endpoint, avec repli sur l'âge du handshake.
|
||||||
|
|
||||||
|
De nombreux serveurs (ou un pare-feu en chemin) bloquent l'ICMP echo
|
||||||
|
tout en laissant le tunnel WireGuard fonctionner parfaitement : sans ce
|
||||||
|
repli, le badge de statut affichait « hors ligne » en continu sur ces
|
||||||
|
configurations, alors que le handshake était récent et le trafic RX/TX
|
||||||
|
bien réel. Retourne (valeur, source) où `source` vaut "ping" (latence
|
||||||
|
ICMP), "handshake" (âge du dernier handshake, tunnel sain), "stale"
|
||||||
|
(handshake trop ancien) ou "down" (aucune des deux sondes n'aboutit).
|
||||||
|
"""
|
||||||
|
host = cfg.wg.get("server_endpoint", "")
|
||||||
|
ms = ping_server(host, timeout) if host else None
|
||||||
|
if ms is not None:
|
||||||
|
return ms, "ping"
|
||||||
|
age = last_handshake_age(cfg.wg.get("interface_name", "wgs0"))
|
||||||
|
if age is not None and 0 <= age <= _HANDSHAKE_STALE_S:
|
||||||
|
return age, "handshake"
|
||||||
|
if age is not None and age > _HANDSHAKE_STALE_S:
|
||||||
|
return age, "stale"
|
||||||
|
return None, "down"
|
||||||
|
|
||||||
|
|
||||||
# ── Test DNS leak ─────────────────────────────────────────────────────────
|
# ── Test DNS leak ─────────────────────────────────────────────────────────
|
||||||
|
|
||||||
def dns_leak_test(cfg: Config) -> dict:
|
def dns_leak_test(cfg: Config) -> dict:
|
||||||
|
|||||||
+11
-3
@@ -414,7 +414,7 @@ class MainWindow(QMainWindow):
|
|||||||
return
|
return
|
||||||
# `ping` bloque jusqu'à 4 s : exécuté dans le thread Qt, il faisait
|
# `ping` bloque jusqu'à 4 s : exécuté dans le thread Qt, il faisait
|
||||||
# saccader toute l'interface toutes les 10 secondes.
|
# saccader toute l'interface toutes les 10 secondes.
|
||||||
self._ping_worker = ValueWorker(wg_core.ping_server, host, 2, parent=self)
|
self._ping_worker = ValueWorker(wg_core.ping_or_handshake, self._cfg, 2, parent=self)
|
||||||
self._ping_worker.done.connect(self._on_ping_done)
|
self._ping_worker.done.connect(self._on_ping_done)
|
||||||
# Détruire le QThread depuis `finished` et non depuis `done` : `done`
|
# Détruire le QThread depuis `finished` et non depuis `done` : `done`
|
||||||
# est émis avant la sortie de run(), un deleteLater() à ce moment
|
# est émis avant la sortie de run(), un deleteLater() à ce moment
|
||||||
@@ -422,12 +422,20 @@ class MainWindow(QMainWindow):
|
|||||||
self._ping_worker.finished.connect(self._ping_worker.deleteLater)
|
self._ping_worker.finished.connect(self._ping_worker.deleteLater)
|
||||||
self._ping_worker.start()
|
self._ping_worker.start()
|
||||||
|
|
||||||
def _on_ping_done(self, ms):
|
def _on_ping_done(self, result):
|
||||||
self._ping_worker = None
|
self._ping_worker = None
|
||||||
|
ms, source = result if result else (None, "down")
|
||||||
if not self._is_connected:
|
if not self._is_connected:
|
||||||
self._set_ping_badge(None, "— ms", "offline")
|
self._set_ping_badge(None, "— ms", "offline")
|
||||||
elif ms is None:
|
elif source == "down":
|
||||||
self._set_ping_badge(None, "hors ligne", "bad")
|
self._set_ping_badge(None, "hors ligne", "bad")
|
||||||
|
elif source == "stale":
|
||||||
|
self._set_ping_badge(None, "handshake ancien", "bad")
|
||||||
|
elif source == "handshake":
|
||||||
|
# ICMP bloqué par le serveur/pare-feu mais handshake WireGuard
|
||||||
|
# récent : le tunnel fonctionne, la latence réelle est juste
|
||||||
|
# invisible depuis ce test.
|
||||||
|
self._set_ping_badge(None, f"actif ({ms}s)", "medium")
|
||||||
elif ms < 50:
|
elif ms < 50:
|
||||||
self._set_ping_badge(ms, f"{ms} ms", "good")
|
self._set_ping_badge(ms, f"{ms} ms", "good")
|
||||||
elif ms < 200:
|
elif ms < 200:
|
||||||
|
|||||||
+25
-5
@@ -1,6 +1,7 @@
|
|||||||
; ──────────────────────────────────────────────
|
; ──────────────────────────────────────────────
|
||||||
; WGSecure (WGS) — Script Inno Setup
|
; WGSecure (WGS) — Script Inno Setup
|
||||||
; Installeur Windows (bundle VC++ Redistributable)
|
; Installeur Windows complet : WGSecure + WireGuard +
|
||||||
|
; Visual C++ Redistributable, chacun installé en silence si absent.
|
||||||
; ──────────────────────────────────────────────
|
; ──────────────────────────────────────────────
|
||||||
|
|
||||||
#define MyAppName "WGSecure"
|
#define MyAppName "WGSecure"
|
||||||
@@ -29,9 +30,15 @@ Name: "french"; MessagesFile: "compiler:Languages\French.isl"
|
|||||||
|
|
||||||
[Files]
|
[Files]
|
||||||
Source: "dist\{#MyAppExeName}"; DestDir: "{app}"; Flags: ignoreversion
|
Source: "dist\{#MyAppExeName}"; DestDir: "{app}"; Flags: ignoreversion
|
||||||
; VC++ Redistributable x64 — à télécharger avant compilation :
|
; VC++ Redistributable x64 — téléchargé automatiquement par `make installer-deps` :
|
||||||
; https://aka.ms/vs/17/release/vc_redist.x64.exe → installer\vc_redist.x64.exe
|
; https://aka.ms/vs/17/release/vc_redist.x64.exe → installer\VC_redist.x64.exe
|
||||||
Source: "installer\vc_redist.x64.exe"; DestDir: "{tmp}"; Flags: deleteafterinstall
|
Source: "installer\VC_redist.x64.exe"; DestDir: "{tmp}"; Flags: deleteafterinstall
|
||||||
|
; WireGuard pour Windows — prérequis à WGSecure (fournit wg.exe, le pilote
|
||||||
|
; tunnel et le service WireGuardTunnel$ que wireguard.py pilote). Téléchargé
|
||||||
|
; automatiquement par `make installer-deps` :
|
||||||
|
; https://download.wireguard.com/windows-client/wireguard-installer.exe
|
||||||
|
; → installer\wireguard-installer.exe
|
||||||
|
Source: "installer\wireguard-installer.exe"; DestDir: "{tmp}"; Flags: deleteafterinstall
|
||||||
|
|
||||||
[Icons]
|
[Icons]
|
||||||
Name: "{group}\{#MyAppName}"; Filename: "{app}\{#MyAppExeName}"
|
Name: "{group}\{#MyAppName}"; Filename: "{app}\{#MyAppExeName}"
|
||||||
@@ -39,7 +46,12 @@ Name: "{autodesktop}\{#MyAppName}"; Filename: "{app}\{#MyAppExeName}"
|
|||||||
|
|
||||||
[Run]
|
[Run]
|
||||||
; Installation silencieuse du VC++ Redistributable si absent (corrige "Failed to load Python DLL: python312.dll")
|
; Installation silencieuse du VC++ Redistributable si absent (corrige "Failed to load Python DLL: python312.dll")
|
||||||
Filename: "{tmp}\vc_redist.x64.exe"; Parameters: "/install /quiet /norestart"; StatusMsg: "Installation du composant Visual C++ Redistributable…"; Check: VCRedistNeedsInstall
|
Filename: "{tmp}\VC_redist.x64.exe"; Parameters: "/install /quiet /norestart"; StatusMsg: "Installation du composant Visual C++ Redistributable…"; Check: VCRedistNeedsInstall
|
||||||
|
; L'installeur officiel WireGuard s'exécute déjà sans assistant (juste une
|
||||||
|
; fenêtre de progression) : notre propre installeur tourne en admin
|
||||||
|
; (PrivilegesRequired=admin ci-dessus), donc pas d'UAC supplémentaire non plus.
|
||||||
|
; `waituntilterminated` : l'app ne doit pas démarrer avant que wg.exe existe.
|
||||||
|
Filename: "{tmp}\wireguard-installer.exe"; StatusMsg: "Installation de WireGuard…"; Check: WireGuardNeedsInstall; Flags: waituntilterminated
|
||||||
Filename: "{app}\{#MyAppExeName}"; Description: "Lancer {#MyAppName}"; Flags: nowait postinstall skipifsilent
|
Filename: "{app}\{#MyAppExeName}"; Description: "Lancer {#MyAppName}"; Flags: nowait postinstall skipifsilent
|
||||||
|
|
||||||
[Code]
|
[Code]
|
||||||
@@ -50,3 +62,11 @@ begin
|
|||||||
// Clé présente si VC++ 2015-2022 x64 (v14+) déjà installé
|
// Clé présente si VC++ 2015-2022 x64 (v14+) déjà installé
|
||||||
Result := not RegQueryStringValue(HKLM64, 'SOFTWARE\Microsoft\VisualStudio\14.0\VC\Runtimes\X64', 'Version', Version);
|
Result := not RegQueryStringValue(HKLM64, 'SOFTWARE\Microsoft\VisualStudio\14.0\VC\Runtimes\X64', 'Version', Version);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
function WireGuardNeedsInstall: Boolean;
|
||||||
|
begin
|
||||||
|
// WireGuard s'installe toujours dans le Program Files 64 bits, quelle que
|
||||||
|
// soit l'architecture de WGSecure : {pf} y pointe bien puisque
|
||||||
|
// ArchitecturesInstallIn64BitMode=x64compatible ci-dessus.
|
||||||
|
Result := not FileExists(ExpandConstant('{pf}\WireGuard\wireguard.exe'));
|
||||||
|
end;
|
||||||
|
|||||||
Reference in New Issue
Block a user