From b9f7b38f4357cc3f93650abbfe3b581c15899da5 Mon Sep 17 00:00:00 2001 From: Jules Date: Fri, 20 Mar 2026 11:01:39 +0100 Subject: [PATCH] Ajout protection mot de passe et installeur Windows complet - Mot de passe SHA-256 au lancement (3 tentatives, saisie masquee) - install.bat : installeur/desinstalleur/mise a jour tout-en-un - Telecharge et installe Git portable si absent - Telecharge et installe Python 3.12 embarque si absent - Installe pip et les dependances automatiquement - Clone le depot Gitea - Cree raccourcis Bureau et Menu Demarrer - Mise a jour en 1 clic (git pull + pip upgrade) - Desinstallation complete avec confirmation Co-Authored-By: Claude Opus 4.6 (1M context) --- install.bat | 361 ++++++++++++++++++++++++++++++++++++++++++++++++++++ main.py | 34 ++++- 2 files changed, 393 insertions(+), 2 deletions(-) create mode 100644 install.bat diff --git a/install.bat b/install.bat new file mode 100644 index 0000000..fb6cd50 --- /dev/null +++ b/install.bat @@ -0,0 +1,361 @@ +@echo off +chcp 65001 >nul 2>&1 +setlocal EnableDelayedExpansion +title Copydev Imposing Tool — Installation + +set "APP_NAME=Copydev Imposing Tool" +set "INSTALL_DIR=%LOCALAPPDATA%\CopydevImposingTool" +set "PYTHON_DIR=%INSTALL_DIR%\python" +set "APP_DIR=%INSTALL_DIR%\app" +set "SHORTCUT_NAME=Copydev Imposing Tool" +set "GITEA_REPO=https://git.copydev.fr/jules/copydev-imposing-tool.git" +set "PYTHON_VERSION=3.12.8" +set "PYTHON_URL=https://www.python.org/ftp/python/%PYTHON_VERSION%/python-%PYTHON_VERSION%-embed-amd64.zip" +set "GET_PIP_URL=https://bootstrap.pypa.io/get-pip.py" +set "GIT_URL=https://github.com/git-for-windows/git/releases/download/v2.47.1.windows.2/MinGit-2.47.1.2-64-bit.zip" + +:: ============================================================ +:: MENU PRINCIPAL +:: ============================================================ +:MENU +cls +echo ============================================================ +echo %APP_NAME% +echo ============================================================ +echo. +echo 1. Installer +echo 2. Mettre a jour +echo 3. Desinstaller +echo 4. Quitter +echo. +set /p "CHOIX=Votre choix [1-4] : " + +if "%CHOIX%"=="1" goto INSTALL +if "%CHOIX%"=="2" goto UPDATE +if "%CHOIX%"=="3" goto UNINSTALL +if "%CHOIX%"=="4" goto END +echo Choix invalide. +timeout /t 2 >nul +goto MENU + +:: ============================================================ +:: INSTALLATION +:: ============================================================ +:INSTALL +cls +echo ============================================================ +echo INSTALLATION de %APP_NAME% +echo ============================================================ +echo. + +:: Verifier si deja installe +if exist "%INSTALL_DIR%\app\main.py" ( + echo [!] L'application est deja installee dans : + echo %INSTALL_DIR% + echo. + set /p "REINSTALL=Voulez-vous reinstaller ? [O/N] : " + if /i "!REINSTALL!" neq "O" goto MENU + echo. + echo Suppression de l'ancienne installation... + rmdir /s /q "%APP_DIR%" 2>nul +) + +:: Creer le repertoire d'installation +echo [1/7] Creation du repertoire d'installation... +if not exist "%INSTALL_DIR%" mkdir "%INSTALL_DIR%" +if not exist "%INSTALL_DIR%\temp" mkdir "%INSTALL_DIR%\temp" + +:: ---- GIT ---- +:INSTALL_GIT +echo [2/7] Verification de Git... +where git >nul 2>&1 +if %ERRORLEVEL%==0 ( + echo Git est deja installe. + set "GIT_CMD=git" + goto INSTALL_PYTHON +) + +:: Git portable +if exist "%INSTALL_DIR%\git\cmd\git.exe" ( + echo Git portable detecte. + set "GIT_CMD=%INSTALL_DIR%\git\cmd\git.exe" + goto INSTALL_PYTHON +) + +echo Telechargement de Git portable... +if not exist "%INSTALL_DIR%\git" mkdir "%INSTALL_DIR%\git" +powershell -Command "& { [Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12; Invoke-WebRequest -Uri '%GIT_URL%' -OutFile '%INSTALL_DIR%\temp\git.zip' }" 2>nul +if not exist "%INSTALL_DIR%\temp\git.zip" ( + echo [ERREUR] Impossible de telecharger Git. + echo Verifiez votre connexion internet. + pause + goto MENU +) +echo Extraction de Git... +powershell -Command "Expand-Archive -Force '%INSTALL_DIR%\temp\git.zip' '%INSTALL_DIR%\git'" 2>nul +del "%INSTALL_DIR%\temp\git.zip" 2>nul +set "GIT_CMD=%INSTALL_DIR%\git\cmd\git.exe" +echo Git portable installe. + +:: ---- PYTHON ---- +:INSTALL_PYTHON +echo [3/7] Verification de Python... + +:: Verifier Python systeme +where python >nul 2>&1 +if %ERRORLEVEL%==0 ( + for /f "tokens=*" %%i in ('python --version 2^>^&1') do set "PY_VER=%%i" + echo !PY_VER! detecte. + set "PYTHON_CMD=python" + goto INSTALL_PIP +) + +:: Python embarque +if exist "%PYTHON_DIR%\python.exe" ( + echo Python embarque detecte. + set "PYTHON_CMD=%PYTHON_DIR%\python.exe" + goto INSTALL_PIP +) + +echo Telechargement de Python %PYTHON_VERSION% embarque... +if not exist "%PYTHON_DIR%" mkdir "%PYTHON_DIR%" +powershell -Command "& { [Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12; Invoke-WebRequest -Uri '%PYTHON_URL%' -OutFile '%INSTALL_DIR%\temp\python.zip' }" 2>nul +if not exist "%INSTALL_DIR%\temp\python.zip" ( + echo [ERREUR] Impossible de telecharger Python. + pause + goto MENU +) +echo Extraction de Python... +powershell -Command "Expand-Archive -Force '%INSTALL_DIR%\temp\python.zip' '%PYTHON_DIR%'" 2>nul +del "%INSTALL_DIR%\temp\python.zip" 2>nul + +:: Activer pip dans Python embarque (decommenter import site) +for %%f in ("%PYTHON_DIR%\python*._pth") do ( + powershell -Command "(Get-Content '%%f') -replace '#import site','import site' | Set-Content '%%f'" +) +set "PYTHON_CMD=%PYTHON_DIR%\python.exe" +echo Python %PYTHON_VERSION% embarque installe. + +:: ---- PIP ---- +:INSTALL_PIP +echo [4/7] Verification de pip... +"%PYTHON_CMD%" -m pip --version >nul 2>&1 +if %ERRORLEVEL%==0 ( + echo pip est deja installe. + goto INSTALL_DEPS +) + +echo Installation de pip... +powershell -Command "& { [Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12; Invoke-WebRequest -Uri '%GET_PIP_URL%' -OutFile '%INSTALL_DIR%\temp\get-pip.py' }" 2>nul +"%PYTHON_CMD%" "%INSTALL_DIR%\temp\get-pip.py" --no-warn-script-location >nul 2>&1 +del "%INSTALL_DIR%\temp\get-pip.py" 2>nul +echo pip installe. + +:: ---- DEPENDANCES ---- +:INSTALL_DEPS +echo [5/7] Installation des dependances Python... +"%PYTHON_CMD%" -m pip install --upgrade --no-warn-script-location PyQt6 pypdf reportlab pypdfium2 2>&1 | findstr /i "Successfully already" +echo Dependances installees. + +:: ---- CODE SOURCE ---- +:INSTALL_CODE +echo [6/7] Telechargement du code source... +if exist "%APP_DIR%\.git" ( + echo Mise a jour du code existant... + pushd "%APP_DIR%" + "%GIT_CMD%" pull origin master 2>&1 + popd +) else ( + if exist "%APP_DIR%" rmdir /s /q "%APP_DIR%" + "%GIT_CMD%" clone "%GITEA_REPO%" "%APP_DIR%" 2>&1 +) +if not exist "%APP_DIR%\main.py" ( + echo [ERREUR] Le telechargement du code a echoue. + echo Verifiez l'acces a %GITEA_REPO% + pause + goto MENU +) +echo Code source telecharge. + +:: ---- RACCOURCIS ---- +:INSTALL_SHORTCUTS +echo [7/7] Creation des raccourcis... + +:: Creer le lanceur .bat +( + echo @echo off + echo cd /d "%APP_DIR%" + echo "%PYTHON_CMD%" main.py +) > "%INSTALL_DIR%\lancer.bat" + +:: Creer le lanceur .vbs (sans fenetre console) +( + echo Set WshShell = CreateObject^("WScript.Shell"^) + echo WshShell.CurrentDirectory = "%APP_DIR%" + echo WshShell.Run """%PYTHON_CMD%"" ""%APP_DIR%\main.py""", 0, False +) > "%INSTALL_DIR%\lancer.vbs" + +:: Raccourci Bureau +powershell -Command "& { $WshShell = New-Object -ComObject WScript.Shell; $Shortcut = $WshShell.CreateShortcut([Environment]::GetFolderPath('Desktop') + '\%SHORTCUT_NAME%.lnk'); $Shortcut.TargetPath = '%INSTALL_DIR%\lancer.vbs'; $Shortcut.WorkingDirectory = '%APP_DIR%'; $Shortcut.Description = '%APP_NAME%'; $Shortcut.Save() }" 2>nul +echo Raccourci Bureau cree. + +:: Raccourci Menu Demarrer +set "START_MENU=%APPDATA%\Microsoft\Windows\Start Menu\Programs" +powershell -Command "& { $WshShell = New-Object -ComObject WScript.Shell; $Shortcut = $WshShell.CreateShortcut('%START_MENU%\%SHORTCUT_NAME%.lnk'); $Shortcut.TargetPath = '%INSTALL_DIR%\lancer.vbs'; $Shortcut.WorkingDirectory = '%APP_DIR%'; $Shortcut.Description = '%APP_NAME%'; $Shortcut.Save() }" 2>nul +echo Raccourci Menu Demarrer cree. + +:: Nettoyer temp +rmdir /s /q "%INSTALL_DIR%\temp" 2>nul + +:: ---- FIN INSTALLATION ---- +echo. +echo ============================================================ +echo INSTALLATION TERMINEE +echo ============================================================ +echo. +echo Dossier : %INSTALL_DIR% +echo Lanceur : Double-cliquez sur le raccourci Bureau +echo "%SHORTCUT_NAME%" +echo. +echo Mot de passe requis au lancement. +echo. +pause +goto MENU + +:: ============================================================ +:: MISE A JOUR +:: ============================================================ +:UPDATE +cls +echo ============================================================ +echo MISE A JOUR de %APP_NAME% +echo ============================================================ +echo. + +if not exist "%APP_DIR%\main.py" ( + echo [!] L'application n'est pas installee. + echo Lancez d'abord l'installation. + echo. + pause + goto MENU +) + +:: Determiner Git +where git >nul 2>&1 +if %ERRORLEVEL%==0 ( + set "GIT_CMD=git" +) else if exist "%INSTALL_DIR%\git\cmd\git.exe" ( + set "GIT_CMD=%INSTALL_DIR%\git\cmd\git.exe" +) else ( + echo [ERREUR] Git introuvable. Reinstallez l'application. + pause + goto MENU +) + +:: Determiner Python +where python >nul 2>&1 +if %ERRORLEVEL%==0 ( + set "PYTHON_CMD=python" +) else if exist "%PYTHON_DIR%\python.exe" ( + set "PYTHON_CMD=%PYTHON_DIR%\python.exe" +) else ( + echo [ERREUR] Python introuvable. Reinstallez l'application. + pause + goto MENU +) + +echo [1/3] Mise a jour du code source... +pushd "%APP_DIR%" +"%GIT_CMD%" fetch origin 2>&1 + +:: Afficher les changements +for /f %%i in ('"%GIT_CMD%" rev-list HEAD..origin/master --count 2^>nul') do set "COMMITS=%%i" +if "!COMMITS!"=="0" ( + echo Deja a jour ! + popd + echo. + pause + goto MENU +) +echo !COMMITS! nouveau(x) commit(s) disponible(s). +"%GIT_CMD%" log --oneline HEAD..origin/master 2>nul +echo. + +"%GIT_CMD%" pull origin master 2>&1 +popd +echo Code mis a jour. + +echo [2/3] Mise a jour des dependances... +"%PYTHON_CMD%" -m pip install --upgrade --no-warn-script-location PyQt6 pypdf reportlab pypdfium2 2>&1 | findstr /i "Successfully already" + +echo [3/3] Termine ! +echo. +echo ============================================================ +echo MISE A JOUR TERMINEE +echo ============================================================ +echo. +pause +goto MENU + +:: ============================================================ +:: DESINSTALLATION +:: ============================================================ +:UNINSTALL +cls +echo ============================================================ +echo DESINSTALLATION de %APP_NAME% +echo ============================================================ +echo. + +if not exist "%INSTALL_DIR%" ( + echo [!] L'application n'est pas installee. + echo. + pause + goto MENU +) + +echo Les elements suivants seront supprimes : +echo. +echo - Dossier : %INSTALL_DIR% +echo (code, Python embarque, Git portable) +echo - Raccourci Bureau +echo - Raccourci Menu Demarrer +echo. +set /p "CONFIRM=Confirmer la desinstallation ? [O/N] : " +if /i "%CONFIRM%" neq "O" goto MENU + +echo. +echo [1/3] Suppression des raccourcis... +del "%USERPROFILE%\Desktop\%SHORTCUT_NAME%.lnk" 2>nul +del "%APPDATA%\Microsoft\Windows\Start Menu\Programs\%SHORTCUT_NAME%.lnk" 2>nul +echo Raccourcis supprimes. + +echo [2/3] Suppression des fichiers... +:: Tuer les processus Python potentiellement en cours +taskkill /f /im python.exe 2>nul +taskkill /f /im pythonw.exe 2>nul +timeout /t 2 >nul + +rmdir /s /q "%INSTALL_DIR%" 2>nul +if exist "%INSTALL_DIR%" ( + echo [!] Certains fichiers n'ont pas pu etre supprimes. + echo Supprimez manuellement : %INSTALL_DIR% +) else ( + echo Fichiers supprimes. +) + +echo [3/3] Desinstallation terminee. +echo. +echo ============================================================ +echo DESINSTALLATION TERMINEE +echo ============================================================ +echo. +pause +goto MENU + +:: ============================================================ +:END +echo. +echo Au revoir ! +timeout /t 2 >nul +exit /b 0 diff --git a/main.py b/main.py index 37efa81..f5383d6 100644 --- a/main.py +++ b/main.py @@ -3,12 +3,38 @@ import sys import os +import hashlib # Ajouter le repertoire racine au path sys.path.insert(0, os.path.dirname(os.path.abspath(__file__))) -from PyQt6.QtWidgets import QApplication -from app.main_window import MainWindow +from PyQt6.QtWidgets import QApplication, QInputDialog, QMessageBox, QLineEdit + +# Hash SHA-256 du mot de passe — jamais en clair dans le code +_PASSWORD_HASH = "f3dd6962a99a2fe2e03cd8e5cfa7dafb12570bdcca1b6590e27d95dcccdf1f58" + +def _hash_password(pwd): + return hashlib.sha256(pwd.encode("utf-8")).hexdigest() + + +def _check_auth(): + """Demander le mot de passe au lancement.""" + max_attempts = 3 + for attempt in range(max_attempts): + pwd, ok = QInputDialog.getText( + None, + "Copydev Imposing Tool", + f"Mot de passe requis ({max_attempts - attempt} essai(s) restant(s)) :", + QLineEdit.EchoMode.Password, + ) + if not ok: + return False + if _hash_password(pwd) == _PASSWORD_HASH: + return True + if attempt < max_attempts - 1: + QMessageBox.warning(None, "Erreur", "Mot de passe incorrect.") + QMessageBox.critical(None, "Acces refuse", "Trop de tentatives. L'application va se fermer.") + return False def main(): @@ -16,6 +42,10 @@ def main(): app.setApplicationName("Copydev Imposing Tool") app.setOrganizationName("Copydev") + if not _check_auth(): + sys.exit(1) + + from app.main_window import MainWindow window = MainWindow() window.show() sys.exit(app.exec())