Compare commits
5 Commits
9031e1d04d
...
last_async
| Author | SHA1 | Date | |
|---|---|---|---|
| be72749b53 | |||
| dc2adfbca5 | |||
| a693338891 | |||
| bfa6865109 | |||
| 3155154083 |
1
.gitignore
vendored
1
.gitignore
vendored
@@ -1,3 +1,4 @@
|
||||
.venv
|
||||
OxApp.dist
|
||||
installer
|
||||
OxApp.bin
|
||||
2
.idea/misc.xml
generated
2
.idea/misc.xml
generated
@@ -3,7 +3,7 @@
|
||||
<component name="Black">
|
||||
<option name="sdkName" value="Python 3.13 (oxapp25)" />
|
||||
</component>
|
||||
<component name="ProjectRootManager" version="2" project-jdk-name="Python 3.13 virtualenv at D:\Dev\oxapp25\.venv" project-jdk-type="Python SDK" />
|
||||
<component name="ProjectRootManager" version="2" project-jdk-name="Python 3.13 (oxapp25)" project-jdk-type="Python SDK" />
|
||||
<component name="PythonCompatibilityInspectionAdvertiser">
|
||||
<option name="version" value="3" />
|
||||
</component>
|
||||
|
||||
2
.idea/oxapp25.iml
generated
2
.idea/oxapp25.iml
generated
@@ -4,7 +4,7 @@
|
||||
<content url="file://$MODULE_DIR$">
|
||||
<excludeFolder url="file://$MODULE_DIR$/.venv" />
|
||||
</content>
|
||||
<orderEntry type="jdk" jdkName="Python 3.13 virtualenv at D:\Dev\oxapp25\.venv" jdkType="Python SDK" />
|
||||
<orderEntry type="jdk" jdkName="Python 3.13 (oxapp25)" jdkType="Python SDK" />
|
||||
<orderEntry type="sourceFolder" forTests="false" />
|
||||
</component>
|
||||
</module>
|
||||
2
Makefile
2
Makefile
@@ -16,7 +16,7 @@ resources:
|
||||
|
||||
# Déploie l'application avec pyside6-deploy
|
||||
deploy:
|
||||
pyside6-deploy -c pysidedeploy.spec
|
||||
pyside6-deploy -c pysidedeploy_linux.spec
|
||||
|
||||
# Crée l'exécutable avec PyInstaller
|
||||
pyinstaller:
|
||||
|
||||
104
main.py
104
main.py
@@ -1,4 +1,4 @@
|
||||
from PySide6.QtCore import QStandardPaths, QDataStream, QByteArray, QIODevice, Signal, Qt, QTimer, QCryptographicHash
|
||||
from PySide6.QtCore import QDataStream, QIODevice, Signal, QTimer
|
||||
from PySide6.QtGui import QPalette, QColor
|
||||
from PySide6.QtNetwork import QLocalServer, QLocalSocket
|
||||
from PySide6.QtWidgets import QApplication
|
||||
@@ -7,14 +7,8 @@ import qasync
|
||||
import sys
|
||||
import asyncio
|
||||
import os
|
||||
import platform
|
||||
import argparse
|
||||
import hashlib
|
||||
import random
|
||||
import string
|
||||
import base64
|
||||
import logging
|
||||
from pathlib import Path
|
||||
|
||||
from src.logs import configure_logging
|
||||
from windows.main_window import MainWindow
|
||||
@@ -63,9 +57,6 @@ class SingleApplication(QApplication):
|
||||
self.app_id = app_id
|
||||
self.logger.debug(f"ID de l'application: {app_id}")
|
||||
|
||||
self.shared_key = hashlib.sha256(app_id.encode()).hexdigest()[:16]
|
||||
self.logger.debug(f"Clé partagée générée: {self.shared_key}")
|
||||
|
||||
self.server = None
|
||||
self.is_primary_instance = self.try_connect_to_primary()
|
||||
|
||||
@@ -77,7 +68,8 @@ class SingleApplication(QApplication):
|
||||
self.logger.debug("Signal newConnection connecté")
|
||||
|
||||
if not self.server.listen(self.app_id):
|
||||
self.logger.warning(f"Échec de l'écoute sur {self.app_id}, tentative de suppression du serveur existant")
|
||||
self.logger.warning(
|
||||
f"Échec de l'écoute sur {self.app_id}, tentative de suppression du serveur existant")
|
||||
# En cas d'erreur (serveur déjà existant mais zombie), on le supprime et on réessaie
|
||||
QLocalServer.removeServer(self.app_id)
|
||||
if self.server.listen(self.app_id):
|
||||
@@ -90,78 +82,6 @@ class SingleApplication(QApplication):
|
||||
self.logger.info("Instance secondaire détectée, fermeture de l'application")
|
||||
QTimer.singleShot(0, self.quit)
|
||||
|
||||
def encrypt_data(self, data_str):
|
||||
"""
|
||||
Méthode simple pour brouiller les données
|
||||
|
||||
Args:
|
||||
data_str (str): Données à chiffrer
|
||||
|
||||
Returns:
|
||||
str: Données chiffrées en base64
|
||||
"""
|
||||
self.logger.debug(f"Chiffrement des données (longueur: {len(data_str)})")
|
||||
|
||||
# Générer une "nonce" aléatoire pour éviter que les mêmes données produisent le même résultat
|
||||
nonce = ''.join(random.choice(string.ascii_letters + string.digits) for _ in range(8))
|
||||
self.logger.debug(f"Nonce générée: {nonce}")
|
||||
|
||||
# Combiner la nonce, la clé et les données
|
||||
combined = nonce + self.shared_key + data_str
|
||||
self.logger.debug("Données combinées avec nonce et clé partagée")
|
||||
|
||||
# Utiliser SHA-256 pour obtenir un hash
|
||||
hash_obj = QCryptographicHash(QCryptographicHash.Algorithm.Sha256)
|
||||
hash_obj.addData(combined.encode())
|
||||
signature = hash_obj.result().toHex().data().decode()[:16]
|
||||
self.logger.debug(f"Signature générée: {signature}")
|
||||
|
||||
# Encoder le tout en base64
|
||||
encoded = base64.b64encode((nonce + signature + data_str).encode()).decode()
|
||||
self.logger.debug(f"Données encodées en base64 (longueur: {len(encoded)})")
|
||||
return encoded
|
||||
|
||||
def decrypt_data(self, encoded_str):
|
||||
"""
|
||||
Déchiffre les données et vérifie leur intégrité
|
||||
|
||||
Args:
|
||||
encoded_str (str): Données chiffrées en base64
|
||||
|
||||
Returns:
|
||||
str ou None: Données déchiffrées ou None en cas d'erreur
|
||||
"""
|
||||
self.logger.debug(f"Déchiffrement des données (longueur: {len(encoded_str)})")
|
||||
|
||||
try:
|
||||
# Décoder de base64
|
||||
decoded = base64.b64decode(encoded_str.encode()).decode()
|
||||
self.logger.debug("Données décodées de base64")
|
||||
|
||||
# Extraire nonce, signature et données
|
||||
nonce = decoded[:8]
|
||||
signature = decoded[8:24]
|
||||
data_str = decoded[24:]
|
||||
self.logger.debug(f"Nonce extraite: {nonce}, signature: {signature}")
|
||||
|
||||
# Vérifier la signature
|
||||
combined = nonce + self.shared_key + data_str
|
||||
hash_obj = QCryptographicHash(QCryptographicHash.Algorithm.Sha256)
|
||||
hash_obj.addData(combined.encode())
|
||||
expected_signature = hash_obj.result().toHex().data().decode()[:16]
|
||||
self.logger.debug(f"Signature attendue: {expected_signature}")
|
||||
|
||||
if signature != expected_signature:
|
||||
self.logger.warning("Signature invalide, données potentiellement corrompues ou falsifiées")
|
||||
return None
|
||||
|
||||
self.logger.debug(f"Données déchiffrées avec succès (longueur: {len(data_str)})")
|
||||
return data_str
|
||||
|
||||
except Exception as e:
|
||||
self.logger.error(f"Erreur lors du déchiffrement: {e}", exc_info=True)
|
||||
return None
|
||||
|
||||
def try_connect_to_primary(self):
|
||||
"""
|
||||
Essaie de se connecter à l'instance primaire de l'application
|
||||
@@ -180,12 +100,13 @@ class SingleApplication(QApplication):
|
||||
args = sys.argv[1:] if len(sys.argv) > 1 else []
|
||||
self.logger.debug(f"Arguments à transmettre: {args}")
|
||||
|
||||
encrypt_args = self.encrypt_data(";".join(args))
|
||||
self.logger.debug("Arguments chiffrés pour transmission")
|
||||
# Envoi des arguments sans chiffrement
|
||||
args_str = ";".join(args)
|
||||
self.logger.debug("Arguments à envoyer: " + args_str)
|
||||
|
||||
# Envoyer les arguments à l'instance primaire
|
||||
stream = QDataStream(socket)
|
||||
stream.writeQString(encrypt_args)
|
||||
stream.writeQString(args_str)
|
||||
socket.flush()
|
||||
self.logger.debug("Données envoyées à l'instance primaire")
|
||||
|
||||
@@ -216,12 +137,9 @@ class SingleApplication(QApplication):
|
||||
self.logger.debug("Données disponibles pour lecture")
|
||||
stream = QDataStream(socket)
|
||||
|
||||
encrypted_args = stream.readQString()
|
||||
self.logger.debug(f"Arguments chiffrés reçus (longueur: {len(encrypted_args)})")
|
||||
|
||||
args_str = self.decrypt_data(encrypted_args)
|
||||
if args_str:
|
||||
self.logger.debug(f"Arguments déchiffrés: {args_str}")
|
||||
# Lecture des arguments sans déchiffrement
|
||||
args_str = stream.readQString()
|
||||
self.logger.debug(f"Arguments reçus: {args_str}")
|
||||
|
||||
# Émettre un signal pour informer l'application des fichiers à ouvrir
|
||||
args = args_str.split(";") if args_str else []
|
||||
@@ -230,8 +148,6 @@ class SingleApplication(QApplication):
|
||||
self.files_received.emit(args)
|
||||
else:
|
||||
self.logger.debug("Aucun argument à traiter")
|
||||
else:
|
||||
self.logger.warning("Échec du déchiffrement des arguments")
|
||||
else:
|
||||
self.logger.warning("Délai d'attente dépassé pour la lecture des données")
|
||||
|
||||
|
||||
@@ -43,7 +43,7 @@ qml_files =
|
||||
excluded_qml_plugins =
|
||||
|
||||
# qt modules used. comma separated
|
||||
modules = WebEngineCore,WebEngineWidgets,WebChannel,Core,Gui,Widgets,Network
|
||||
modules = Network,WebEngineCore,Widgets,Gui,WebEngineWidgets,Core,WebChannel
|
||||
|
||||
# qt plugins used by the application. only relevant for desktop deployment. for qt plugins used
|
||||
# in android application see [android][plugins]
|
||||
@@ -71,7 +71,7 @@ macos.permissions =
|
||||
mode = standalone
|
||||
|
||||
# (str) specify any extra nuitka arguments
|
||||
extra_args = --quiet --noinclude-qt-translations --windows-console-mode=disable --output-filename=oxapp
|
||||
extra_args = --quiet --noinclude-qt-translations --windows-console-mode=disable --output-filename=oxapp --company-name=Oxpanel --product-name=OxApp --file-description="Application légitime OxApp" --copyright="Oxpanel (c) 2023" --file-version=1.0.0 --product-version=1.0.0 --unstripped --no-deployment-flag=self-execution --disable-ccache --disable-console
|
||||
|
||||
[buildozer]
|
||||
|
||||
@@ -99,4 +99,3 @@ local_libs =
|
||||
# architecture of deployed platform
|
||||
# possible values = ["aarch64", "armv7a", "i686", "x86_64"]
|
||||
arch =
|
||||
|
||||
|
||||
99
pysidedeploy_linux.spec
Executable file
99
pysidedeploy_linux.spec
Executable file
@@ -0,0 +1,99 @@
|
||||
[app]
|
||||
|
||||
# title of your application
|
||||
title = OxApp
|
||||
|
||||
# project directory. the general assumption is that project_dir is the parent directory
|
||||
# of input_file
|
||||
project_dir = /home/nell/dev/oxapp25
|
||||
|
||||
# source file path
|
||||
input_file = /home/nell/dev/oxapp25/main.py
|
||||
|
||||
# directory where the executable output is generated
|
||||
exec_directory = .
|
||||
|
||||
# path to .pyproject project file
|
||||
project_file =
|
||||
|
||||
# application icon
|
||||
icon = /home/nell/dev/oxapp25/oxpanel.ico
|
||||
|
||||
[python]
|
||||
|
||||
# python path
|
||||
python_path = /home/nell/dev/oxapp25/.venv/bin/python
|
||||
|
||||
# python packages to install
|
||||
packages = Nuitka==2.5.1
|
||||
|
||||
# buildozer = for deploying Android application
|
||||
android_packages = buildozer==1.5.0,cython==0.29.33
|
||||
|
||||
[qt]
|
||||
|
||||
# comma separated path to qml files required
|
||||
# normally all the qml files required by the project are added automatically
|
||||
qml_files =
|
||||
|
||||
# excluded qml plugin binaries
|
||||
excluded_qml_plugins =
|
||||
|
||||
# qt modules used. comma separated
|
||||
modules = Positioning,WebChannel,Quick,QuickWidgets,QmlMeta,OpenGL,DBus,Core,QmlModels,QmlWorkerScript,Qml,Network,Widgets,Gui,WebEngineWidgets,PrintSupport,WebEngineCore
|
||||
|
||||
# qt plugins used by the application. only relevant for desktop deployment. for qt plugins used
|
||||
# in android application see [android][plugins]
|
||||
plugins = networkinformation,scenegraph,platforms/darwin,iconengines,tls,xcbglintegrations,qmltooling,position,platformthemes,imageformats,platforms,platforminputcontexts,accessiblebridge,generic,networkaccess,styles,printsupport,egldeviceintegrations
|
||||
|
||||
[android]
|
||||
|
||||
# path to pyside wheel
|
||||
wheel_pyside =
|
||||
|
||||
# path to shiboken wheel
|
||||
wheel_shiboken =
|
||||
|
||||
# plugins to be copied to libs folder of the packaged application. comma separated
|
||||
plugins =
|
||||
|
||||
[nuitka]
|
||||
|
||||
# usage description for permissions requested by the app as found in the info.plist file
|
||||
# of the app bundle
|
||||
# eg = extra_args = --show-modules --follow-stdlib
|
||||
macos.permissions =
|
||||
|
||||
# mode of using nuitka. accepts standalone or onefile. default is onefile.
|
||||
mode = onefile
|
||||
|
||||
# (str) specify any extra nuitka arguments
|
||||
extra_args = --quiet --noinclude-qt-translations --jobs=auto --lto=yes
|
||||
|
||||
[buildozer]
|
||||
|
||||
# build mode
|
||||
# possible options = [release, debug]
|
||||
# release creates an aab, while debug creates an apk
|
||||
mode = debug
|
||||
|
||||
# contrains path to pyside6 and shiboken6 recipe dir
|
||||
recipe_dir =
|
||||
|
||||
# path to extra qt android jars to be loaded by the application
|
||||
jars_dir =
|
||||
|
||||
# if empty uses default ndk path downloaded by buildozer
|
||||
ndk_path =
|
||||
|
||||
# if empty uses default sdk path downloaded by buildozer
|
||||
sdk_path =
|
||||
|
||||
# other libraries to be loaded. comma separated.
|
||||
# loaded at app startup
|
||||
local_libs =
|
||||
|
||||
# architecture of deployed platform
|
||||
# possible values = ["aarch64", "armv7a", "i686", "x86_64"]
|
||||
arch =
|
||||
|
||||
Reference in New Issue
Block a user