示例#1
0
def GetValeur(cle="", defaut="", theme=None):
    # lecture du thème
    if theme == None:
        theme = UTILS_Customize.GetValeur("interface", "theme", "Vert")

    # Lecture de la valeur
    if theme in DONNEES:
        if cle in DONNEES[theme]:
            return DONNEES[theme][cle]

    # Sinon renvoie la valeur par défaut
    return defaut
示例#2
0
    def Rechercher(self, event=None):
        # Récupération des champs saisis
        nom = self.ctrl_nom.GetValue()
        if nom == "":
            dlg = wx.MessageDialog(self, _(u"Vous devez renseigner le nom !"),
                                   _(u"Erreur de saisie"),
                                   wx.OK | wx.ICON_EXCLAMATION)
            dlg.ShowModal()
            dlg.Destroy()
            return

        prenom = self.ctrl_prenom.GetValue()
        if prenom == "":
            dlg = wx.MessageDialog(self,
                                   _(u"Vous devez renseigner le prénom !"),
                                   _(u"Erreur de saisie"),
                                   wx.OK | wx.ICON_EXCLAMATION)
            dlg.ShowModal()
            dlg.Destroy()
            return

        adresse = self.ctrl_adresse.GetValue()
        if adresse == "":
            dlg = wx.MessageDialog(self,
                                   _(u"Vous devez renseigner l'adresse !"),
                                   _(u"Erreur de saisie"),
                                   wx.OK | wx.ICON_EXCLAMATION)
            dlg.ShowModal()
            dlg.Destroy()
            return

        # Récupération de l'URL
        url = UTILS_Customize.GetValeur("referentiel",
                                        "url",
                                        None,
                                        ajouter_si_manquant=False)
        if url == None:
            dlg = wx.MessageDialog(
                self,
                _(u"Vous devez renseigner l'URL dans le fichier Customize !"),
                _(u"Erreur"), wx.OK | wx.ICON_EXCLAMATION)
            dlg.ShowModal()
            dlg.Destroy()
            return
        url = u"%s/%s* %s*" % (url, nom, prenom)

        # Requête
        try:
            reponse = requests.get(url)
        except Exception, error:
            self.ctrl_resultats.SetTexte(unicode(error))
            return
示例#3
0
    def OnBoutonOutils(self, event):
        # Création du menu contextuel
        menuPop = wx.Menu()

        # Item Mesurer
        item = wx.MenuItem(menuPop, 10, _(u"Mesurer une distance"))
        item.SetBitmap(wx.Bitmap(Chemins.GetStaticPath("Images/16x16/Transport.png"), wx.BITMAP_TYPE_PNG))
        menuPop.AppendItem(item)
        self.Bind(wx.EVT_MENU, self.Mesurer_distance, id=10)

        # Contrôle
        if UTILS_Customize.GetValeur("referentiel", "url", None, ajouter_si_manquant=False) != None:
            item = wx.MenuItem(menuPop, 20, _(u"Contrôle référentiel"))
            item.SetBitmap(wx.Bitmap(Chemins.GetStaticPath("Images/16x16/Personnes.png"), wx.BITMAP_TYPE_PNG))
            menuPop.AppendItem(item)
            self.Bind(wx.EVT_MENU, self.Controle_referentiel, id=20)

        self.PopupMenu(menuPop)
        menuPop.Destroy()
示例#4
0
def GetRepData(fichier=""):
    # Vérifie si un répertoire 'Portable' existe
    chemin = Chemins.GetMainPath("Portable")
    if os.path.isdir(chemin):
        chemin = os.path.join(chemin, "Data")
        if not os.path.isdir(chemin):
            os.mkdir(chemin)
        return os.path.join(chemin, fichier)

    # Recherche s'il existe un chemin personnalisé dans le Customize.ini
    chemin = UTILS_Customize.GetValeur("repertoire_donnees", "chemin", "")
    #chemin = chemin.decode("iso-8859-15")
    if chemin != "" and os.path.isdir(chemin):
        return os.path.join(chemin, fichier)

    # Recherche le chemin du répertoire des données
    if sys.platform == "win32" and platform.release() != "Vista":

        chemin = appdirs.site_data_dir(appname=None, appauthor=False)
        #chemin = chemin.decode("iso-8859-15")

        chemin = os.path.join(chemin, "teamworks")
        if not os.path.isdir(chemin):
            os.mkdir(chemin)

    else:

        chemin = appdirs.user_data_dir(appname=None, appauthor=False)
        #chemin = chemin.decode("iso-8859-15")

        chemin = os.path.join(chemin, "teamworks")
        if not os.path.isdir(chemin):
            os.mkdir(chemin)

        chemin = os.path.join(chemin, "Data")
        if not os.path.isdir(chemin):
            os.mkdir(chemin)

    # Ajoute le dirname si besoin
    return os.path.join(chemin, fichier)
import Chemins
from Utils.UTILS_Traduction import _
import wx
import os
import time
import datetime
from threading import Thread, Lock
import GestionDB
from Utils import UTILS_Parametres
from Utils import UTILS_Fichiers
from Utils import UTILS_Customize
from Utils import UTILS_Portail_synchro
from Dlg.DLG_Portail_config import LISTE_DELAIS_SYNCHRO

CUSTOMIZE = UTILS_Customize.Customize()

class Abort(Exception):
    pass

class Serveur(Thread):
    def __init__(self, parent):
        Thread.__init__(self)
        self.parent = parent
        self.start_synchro = False
        self.synchro_en_cours = False
        self.active = False

    def Start(self):
        if self.IsRunning() == False :
            self.keepGoing = self.active = True
    def Rechercher(self, event=None):
        # Récupération des champs saisis
        nom = self.ctrl_nom.GetValue()
        if nom == "" :
            dlg = wx.MessageDialog(self, _(u"Vous devez renseigner le nom !"), _(u"Erreur de saisie"), wx.OK | wx.ICON_EXCLAMATION)
            dlg.ShowModal()
            dlg.Destroy()
            return

        prenom = self.ctrl_prenom.GetValue()
        if prenom == "" :
            dlg = wx.MessageDialog(self, _(u"Vous devez renseigner le prénom !"), _(u"Erreur de saisie"), wx.OK | wx.ICON_EXCLAMATION)
            dlg.ShowModal()
            dlg.Destroy()
            return

        adresse = self.ctrl_adresse.GetValue()
        if adresse == "" :
            dlg = wx.MessageDialog(self, _(u"Vous devez renseigner l'adresse !"), _(u"Erreur de saisie"), wx.OK | wx.ICON_EXCLAMATION)
            dlg.ShowModal()
            dlg.Destroy()
            return

        # Récupération de l'URL
        url = UTILS_Customize.GetValeur("referentiel", "url", None, ajouter_si_manquant=False)
        if url == None :
            dlg = wx.MessageDialog(self, _(u"Vous devez renseigner l'URL dans le fichier Customize !"), _(u"Erreur"), wx.OK | wx.ICON_EXCLAMATION)
            dlg.ShowModal()
            dlg.Destroy()
            return
        url = u"%s/%s* %s*" % (url, nom, prenom)

        # Requête
        try :
            reponse = requests.get(url)
        except Exception as error :
            self.ctrl_resultats.SetTexte(unicode(error))
            return

        # Si erreur
        if reponse.status_code != 200:
            self.ctrl_resultats.SetTexte(_(u"Accès au référentiel impossible (Erreur %s)") % reponse.status_code)
            return

        # Conversion en XML
        root = ElementTree.fromstring(reponse.content)

        # Parcours le XML

        nbreResultats = 0
        listeResultats = []
        for child in root:
            ligne = {}
            for node in child.iter():
                if "}nomOfficiel" in node.tag:
                    ligne["nom"] = node.text
                if "}prenomUsuel" in node.tag:
                    ligne["prenom"] = node.text
                if "}voieNumero" in node.tag:
                    ligne["adresse"] = node.text

            nbreResultats += 1
            listeResultats.append(ligne)

        # Analyse des résultats
        listeResultatsTraites = []
        for dictTemp in listeResultats :
            texte1 = u"%s#%s#%s" % (dictTemp["nom"], dictTemp["prenom"], dictTemp["adresse"])
            texte2 = u"%s#%s#%s" % (nom, prenom, adresse)
            pourcent = GetRatioDiffTextes(texte1, texte2)
            listeResultatsTraites.append((pourcent, dictTemp))

        # Tri en fonction du nombre de similarités
        listeResultatsTraites.sort(reverse=True)

        # Affichage des résultats
        if nbreResultats > 0 :
            texte = _(u"<FONT SIZE=5><B>%d résultats :</B><BR></FONT><BR>") % nbreResultats
        else :
            texte = _(u"<FONT SIZE=5><B>Aucun résultat</B><BR></FONT><BR>")

        for pourcent, dictTemp in listeResultatsTraites :
            if pourcent == 100 :
                couleur = "GREEN"
            elif pourcent > 90 :
                couleur = "#FF8000"
            else :
                couleur = "RED"

            texte += _(u"""
            <FONT SIZE=2 COLOR='%s'>Pertinence : %s%%</FONT> <BR>
            Nom : <B>%s</B> <BR>
            Prénom : <B>%s</B> <BR>
            Adresse : <B>%s</B> <BR>
            <BR>
            """) % (couleur, pourcent, dictTemp["nom"], dictTemp["prenom"], dictTemp["adresse"])

        # Affichage des résultats
        self.ctrl_resultats.SetTexte(texte)
示例#7
0
def SetTheme(theme="Vert"):
    UTILS_Customize.SetValeur("interface", "theme", theme)
示例#8
0
def GetTheme():
    return UTILS_Customize.GetValeur("interface", "theme", "Vert")
示例#9
0
    def Run(self, afficherDlgAttente=False):
        dictParametres = self.GetParametres()

        # Ouverture dlg d'attente
        if afficherDlgAttente == True:
            dlgAttente = wx.BusyInfo(
                _(u"Génération du fichier de données..."), None)

        try:

            # Génération du nom de fichier
            self.nomFichier = UTILS_Fichiers.GetRepTemp(
                fichier=u"data_%s" % dictParametres["IDfichier"])

            # Vérifie si le fichier existe déj�
            nomFichierTemp = self.nomFichier + ".dat"
            if os.path.isfile(nomFichierTemp):
                os.remove(nomFichierTemp)

            # Création des tables
            dbdest = GestionDB.DB(suffixe=None,
                                  nomFichier=nomFichierTemp,
                                  modeCreation=True)
            dbdest.CreationTables(dicoDB=self.dictTables)

            # Enregistrement des paramètres
            listeParametres = [
                ("IDfichier", dictParametres["IDfichier"]),
                ("horodatage", dictParametres["horodatage"]),
                ("type", "donnees"),
            ]
            self.Enregistrer(dbdest,
                             nomTable="parametres",
                             listeChamps=["nom", "valeur"],
                             listeDonnees=listeParametres)

            # Données du dictIndividus
            from Utils import UTILS_Infos_individus
            infos = UTILS_Infos_individus.Informations()
            dictValeurs = infos.GetDictValeurs(mode="individu",
                                               formatChamp=False)
            listeDonnees = []
            for ID, dictTemp in dictValeurs.items():
                for champ, valeur in dictTemp.items():
                    if type(valeur) in (str, six.text_type) and valeur not in (
                            "", None):
                        listeDonnees.append((ID, champ, valeur))

            self.Enregistrer(dbdest,
                             nomTable="informations",
                             listeChamps=["IDindividu", "champ", "valeur"],
                             listeDonnees=listeDonnees)

            # Données individus
            db = GestionDB.DB(suffixe="PHOTOS")
            req = """SELECT IDindividu, photo FROM photos;"""
            db.ExecuterReq(req)
            listePhotos = db.ResultatReq()
            db.Close()
            dictPhotos = {}
            for IDindividu, photo in listePhotos:
                dictPhotos[IDindividu] = photo

            db = GestionDB.DB()
            req = """SELECT IDindividu, IDcivilite, nom, prenom FROM individus;"""
            db.ExecuterReq(req)
            listeIndividus = db.ResultatReq()
            db.Close()
            listeDonnees = []
            for IDindividu, IDcivilite, nom, prenom in listeIndividus:
                if IDindividu in dictPhotos:
                    photo = sqlite3.Binary(dictPhotos[IDindividu])
                else:
                    photo = None
                listeDonnees.append(
                    (IDindividu, IDcivilite, nom, prenom, photo))

            self.Enregistrer(dbdest,
                             nomTable="individus",
                             listeChamps=[
                                 "IDindividu", "IDcivilite", "nom", "prenom",
                                 "photo"
                             ],
                             listeDonnees=listeDonnees)

            # Données Titulaires de dossier
            dictTitulaires = UTILS_Titulaires.GetTitulaires()
            listeDonnees = []
            for IDfamille, dictTemp in dictTitulaires.items():
                nom = dictTitulaires[IDfamille]["titulairesSansCivilite"]
                listeDonnees.append((IDfamille, nom))

            self.Enregistrer(dbdest,
                             nomTable="titulaires",
                             listeChamps=["IDfamille", "nom"],
                             listeDonnees=listeDonnees)

            # Données organisateur
            db = GestionDB.DB()
            req = """SELECT IDorganisateur, nom, logo FROM organisateur;"""
            db.ExecuterReq(req)
            listeTemp = db.ResultatReq()
            db.Close()
            listeDonnees = []
            for IDorganisateur, nom, logo in listeTemp:
                if logo != None:
                    logo = sqlite3.Binary(logo)
                listeDonnees.append((IDorganisateur, nom, logo))

            self.Enregistrer(dbdest,
                             nomTable="organisateur",
                             listeChamps=["IDorganisateur", "nom", "logo"],
                             listeDonnees=listeDonnees)

            # Tables à copier en intégralité
            listeTables = [
                "vacances",
                "jours_feries",
                "activites",
                "groupes",
                "unites",
                "unites_groupes",
                "unites_incompat",
                "unites_remplissage",
                "unites_remplissage_unites",
                "ouvertures",
                "remplissage",
                "inscriptions",
                "consommations",
                "memo_journee",
                "comptes_payeurs",
                "familles",
                "utilisateurs",
                "nomade_archivage",
                "niveaux_scolaires",
                "ecoles",
                "classes",
                "scolarite",
            ]
            self.CopieTables(dbdest, listeTables)

            # Cloture de la base
            dbdest.connexion.commit()
            dbdest.Close()

            # Compression
            fichierZip = zipfile.ZipFile(self.nomFichier + EXTENSION_DECRYPTE,
                                         "w",
                                         compression=zipfile.ZIP_DEFLATED)
            fichierZip.write(self.nomFichier + ".dat", "database.dat")
            fichierZip.close()
            os.remove(self.nomFichier + ".dat")

            # Cryptage
            cryptage_actif = UTILS_Config.GetParametre(
                "synchro_cryptage_activer", defaut=False)
            cryptage_mdp = base64.b64decode(
                UTILS_Config.GetParametre("synchro_cryptage_mdp", defaut=""))
            if six.PY3:
                cryptage_mdp = cryptage_mdp.decode()
            if cryptage_actif == True and cryptage_mdp != "":
                ancienne_methode = UTILS_Customize.GetValeur(
                    "version_cryptage",
                    "nomadhys",
                    "1",
                    ajouter_si_manquant=False) in ("1", None)
                UTILS_Cryptage_fichier.CrypterFichier(
                    self.nomFichier + EXTENSION_DECRYPTE,
                    self.nomFichier + EXTENSION_CRYPTE,
                    cryptage_mdp,
                    ancienne_methode=ancienne_methode)
                os.remove(self.nomFichier + EXTENSION_DECRYPTE)
                nomFichierFinal = self.nomFichier + EXTENSION_CRYPTE
            else:
                nomFichierFinal = self.nomFichier + EXTENSION_DECRYPTE

        except Exception as err:
            print("Erreur dans UTILS_Export_nomade.Run :", err)
            traceback.print_exc(file=sys.stdout)
            if afficherDlgAttente == True:
                del dlgAttente
            dlg = wx.MessageDialog(
                None,
                _(u"Désolé, l'erreur suivante a été rencontrée : ") +
                str(err), "Erreur ", wx.OK | wx.ICON_ERROR)
            dlg.ShowModal()
            dlg.Destroy()
            return None

        if afficherDlgAttente == True:
            del dlgAttente
        return nomFichierFinal
示例#10
0
    def Envoyer_mail(self, commentaires="", joindre_journal=False):
        """ Envoi d'un mail avec pièce jointe """
        from Utils import UTILS_Envoi_email

        # Expéditeur
        dictExp = self.GetAdresseExpDefaut()
        if dictExp == None :
            dlg = wx.MessageDialog(self, _(u"Vous devez d'abord saisir une adresse d'expéditeur depuis le menu Paramétrage > Adresses d'expédition d'Emails. Sinon, postez votre rapport de bug dans le forum de Noethys."), _(u"Erreur"), wx.OK | wx.ICON_EXCLAMATION)
            dlg.ShowModal()
            dlg.Destroy()
            return False
        moteur = dictExp["moteur"]
        adresseExpediteur = dictExp["adresse"]
        serveur = dictExp["smtp"]
        port = dictExp["port"]
        auth = dictExp["auth"]
        startTLS = dictExp["startTLS"]
        motdepasse = dictExp["motdepasse"]
        utilisateur = dictExp["utilisateur"]
        parametres = dictExp["parametres"]

        if adresseExpediteur == None :
            dlg = wx.MessageDialog(self, _(u"L'adresse d'expédition ne semble pas valide. Veuillez la vérifier."), _(u"Envoi impossible"), wx.OK | wx.ICON_EXCLAMATION)
            dlg.ShowModal()
            dlg.Destroy()
            return False

        # Attacher le journal d'erreurs
        fichiers = []
        if joindre_journal == True :
            customize = UTILS_Customize.Customize()
            nom_journal = UTILS_Fichiers.GetRepUtilisateur(customize.GetValeur("journal", "nom", "journal.log"))
            fichiers.append(nom_journal)

        # Préparation du message
        IDrapport = datetime.datetime.now().strftime("%Y%m%d%H%M%S")
        texteRapport = self.ctrl_rapport.GetValue().replace("\n","<br/>")
        if len(commentaires) == 0 :
            commentaires = _(u"Aucun")
        texte_html = _(u"<u>Rapport de bug %s :</u><br/><br/>%s<br/><u>Commentaires :</u><br/><br/>%s") % (IDrapport, texteRapport, commentaires)

        sujet = _(u"Rapport de bug Noethys n°%s") % IDrapport
        message = UTILS_Envoi_email.Message(destinataires=["noe" + "thys" + "@" + "gm" + "ail" + ".com",], sujet=sujet, texte_html=texte_html, fichiers=fichiers)

        # Envoi du mail
        try :
            messagerie = UTILS_Envoi_email.Messagerie(backend=moteur, hote=serveur, port=port, utilisateur=utilisateur, motdepasse=motdepasse, email_exp=adresseExpediteur, use_tls=startTLS, parametres=parametres)
            messagerie.Connecter()
            messagerie.Envoyer(message)
            messagerie.Fermer()
        except Exception as err :
            dlg = wx.MessageDialog(self, _(u"Le message n'a pas pu être envoyé. Merci de poster votre rapport de bug sur le forum de Noethys.\n\nErreur : %s !") % err, _(u"Envoi impossible"), wx.OK | wx.ICON_EXCLAMATION)
            dlg.ShowModal()
            dlg.Destroy()
            return False

        # Message de confirmation
        dlg = wx.MessageDialog(self, _(u"Le rapport d'erreur a été envoyé avec succès."), _(u"Rapport envoyé"), wx.OK | wx.ICON_INFORMATION)
        dlg.ShowModal()
        dlg.Destroy()

        return True
示例#11
0
def Sauvegarde(listeFichiersLocaux=[], listeFichiersReseau=[], nom="", repertoire=None, motdepasse=None, listeEmails=None, dictConnexion=None):
    """ Processus de de création du ZIP """
    # Si aucun fichier à sauvegarder
    if len(listeFichiersLocaux) == 0 and len(listeFichiersReseau) == 0 : 
        return False
    
    # Initialisation de la barre de progression
    nbreEtapes = 3
    nbreEtapes += len(listeFichiersLocaux)
    nbreEtapes += len(listeFichiersReseau)
    if motdepasse != None : nbreEtapes += 1
    if repertoire != None : nbreEtapes += 1
    if listeEmails != None : nbreEtapes += 1
    
    # Création du nom du fichier de destination
    if motdepasse != None :
        extension = EXTENSIONS["crypte"]
    else:
        extension = EXTENSIONS["decrypte"]

    # Vérifie si fichier de destination existe déjà
    if repertoire != None :
        fichierDest = u"%s/%s.%s" % (repertoire, nom, extension)
        if os.path.isfile(fichierDest) == True :
            dlg = wx.MessageDialog(None, _(u"Un fichier de sauvegarde portant ce nom existe déjà. \n\nVoulez-vous le remplacer ?"), "Attention !", wx.YES_NO | wx.NO_DEFAULT | wx.ICON_EXCLAMATION)
            reponse = dlg.ShowModal()
            dlg.Destroy()
            if reponse != wx.ID_YES :
                return False

    # Récupération des paramètres de l'adresse d'expéditeur par défaut
    if listeEmails != None :
        dictAdresse = UTILS_Envoi_email.GetAdresseExpDefaut()
        if dictAdresse == None :
            dlgErreur = wx.MessageDialog(None, _(u"Envoi par Email impossible :\n\nAucune adresse d'expéditeur n'a été définie. Veuillez la saisir dans le menu Paramétrage du logiciel..."), _(u"Erreur"), wx.OK | wx.ICON_ERROR)
            dlgErreur.ShowModal() 
            dlgErreur.Destroy()
            return False

    # Fenêtre de progression
    dlgprogress = wx.ProgressDialog(_(u"Sauvegarde"), _(u"Lancement de la sauvegarde..."), maximum=nbreEtapes, parent=None, style= wx.PD_SMOOTH | wx.PD_AUTO_HIDE | wx.PD_APP_MODAL)
    
    # Création du fichier ZIP temporaire
    nomFichierTemp = u"%s.%s" % (nom, EXTENSIONS["decrypte"])
    fichierZip = zipfile.ZipFile(UTILS_Fichiers.GetRepTemp(fichier=nomFichierTemp), "w", compression=zipfile.ZIP_DEFLATED)
    numEtape = 1
    dlgprogress.Update(numEtape, _(u"Création du fichier de compression..."));numEtape += 1
    
    # Intégration des fichiers locaux
    for nomFichier in listeFichiersLocaux :
        dlgprogress.Update(numEtape, _(u"Compression du fichier %s...") % nomFichier);numEtape += 1
        fichier = UTILS_Fichiers.GetRepData(nomFichier)
        if os.path.isfile(fichier) == True :
            fichierZip.write(fichier, nomFichier)
        else :
            dlgprogress.Destroy()
            dlgErreur = wx.MessageDialog(None, _(u"Le fichier '%s' n'existe plus sur cet ordinateur. \n\nVeuillez ôter ce fichier de la procédure de sauvegarde automatique (Menu Fichier > Sauvegardes automatiques)") % nomFichier, _(u"Erreur"), wx.OK | wx.ICON_ERROR)
            dlgErreur.ShowModal() 
            dlgErreur.Destroy()
            return False
        
    # Intégration des fichiers réseau
    if len(listeFichiersReseau) > 0 and dictConnexion != None :
        
        # Création du répertoire temporaire
        repTemp = UTILS_Fichiers.GetRepTemp(fichier="savetemp")
        if os.path.isdir(repTemp) == True :
            shutil.rmtree(repTemp)
        os.mkdir(repTemp)
        
        # Recherche du répertoire d'installation de MySQL
        repMySQL = GetRepertoireMySQL(dictConnexion) 
        if repMySQL == None :
            dlgprogress.Destroy()
            dlgErreur = wx.MessageDialog(None, _(u"Noethys n'a pas réussi à localiser MySQL sur votre ordinateur.\n\nNotez bien que MySQL doit être installé obligatoirement pour créer une sauvegarde réseau."), _(u"Erreur"), wx.OK | wx.ICON_ERROR)
            dlgErreur.ShowModal() 
            dlgErreur.Destroy()
            return False
        
        # Création du fichier de login
        nomFichierLoginTemp = repTemp + "/logintemp.cnf" #os.path.abspath(os.curdir) + "/" + repTemp + "/logintemp.cnf"
        CreationFichierLoginTemp(host=dictConnexion["host"], port=dictConnexion["port"], user=dictConnexion["user"], password=dictConnexion["password"], nomFichier=nomFichierLoginTemp)
        
        # Création du backup pour chaque fichier MySQL
        for nomFichier in listeFichiersReseau :
            dlgprogress.Update(numEtape, _(u"Compression du fichier %s...") % nomFichier);numEtape += 1
            fichierSave = u"%s/%s.sql" % (repTemp, nomFichier)

            args = u""""%sbin/mysqldump" --defaults-extra-file="%s" --single-transaction --opt --databases %s > "%s" """ % (repMySQL, nomFichierLoginTemp, nomFichier, fichierSave)
            print(("Chemin mysqldump =", args))
            if six.PY2:
                args = args.encode('utf8')
            proc = subprocess.Popen(args, shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, stdin=subprocess.PIPE)
            out, temp = proc.communicate()

            if out not in ("", b""):
                print((out,))
                try :
                    if six.PY2:
                        out = str(out).decode("iso-8859-15")
                except :
                    pass
                dlgprogress.Destroy()
                dlgErreur = wx.MessageDialog(None, _(u"Une erreur a été détectée dans la procédure de sauvegarde !\n\nErreur : %s") % out, _(u"Erreur"), wx.OK | wx.ICON_ERROR)
                dlgErreur.ShowModal() 
                dlgErreur.Destroy()
                return False

            # Insère le fichier Sql dans le ZIP
            try :
                fichierZip.write(fichierSave.encode('utf8'), u"%s.sql" % nomFichier)
            except Exception as err :
                dlgprogress.Destroy()
                print(("insertion sql dans zip : ", err,))
                try :
                    if six.PY2:
                        err = str(err).decode("iso-8859-15")
                except :
                    pass
                dlgErreur = wx.MessageDialog(None, _(u"Une erreur est survenue dans la sauvegarde !\n\nErreur : %s") % err, _(u"Erreur"), wx.OK | wx.ICON_ERROR)
                dlgErreur.ShowModal() 
                dlgErreur.Destroy()
                return False

        # Supprime le répertoire temp
        shutil.rmtree(repTemp)

    # Finalise le fichier ZIP
    fichierZip.close()
    
    # Cryptage du fichier
    if motdepasse != None :
        dlgprogress.Update(numEtape, _(u"Cryptage du fichier..."));numEtape += 1
        fichierCrypte = u"%s.%s" % (nom, EXTENSIONS["crypte"])
        motdepasse = base64.b64decode(motdepasse)
        if six.PY3:
            motdepasse = motdepasse.decode('utf8')
        ancienne_methode = UTILS_Customize.GetValeur("version_cryptage", "sauvegarde", "1", ajouter_si_manquant=False) in ("1", None)
        UTILS_Cryptage_fichier.CrypterFichier(UTILS_Fichiers.GetRepTemp(fichier=nomFichierTemp), UTILS_Fichiers.GetRepTemp(fichier=fichierCrypte), motdepasse, ancienne_methode=ancienne_methode)
        nomFichierTemp = fichierCrypte
        extension = EXTENSIONS["crypte"]
    else:
        extension = EXTENSIONS["decrypte"]
    
    # Copie le fichier obtenu dans le répertoire donné
    if repertoire != None :
        dlgprogress.Update(numEtape, _(u"Création du fichier dans le répertoire cible..."));numEtape += 1
        try :
            shutil.copy2(UTILS_Fichiers.GetRepTemp(fichier=nomFichierTemp), fichierDest)
        except :
            print("Le repertoire de destination de sauvegarde n'existe pas.")

    # Préparation du message
    message = UTILS_Envoi_email.Message(destinataires=listeEmails, sujet=_(u"Sauvegarde Noethys : %s") % nom,
                                        texte_html=_(u"Envoi de la sauvegarde de Noethys"),
                                        fichiers=[UTILS_Fichiers.GetRepTemp(fichier=nomFichierTemp),])

    # Envoi par Email
    if listeEmails != None :
        dlgprogress.Update(numEtape, _(u"Expédition de la sauvegarde par Email..."));numEtape += 1
        try :
            messagerie = UTILS_Envoi_email.Messagerie(backend=dictAdresse["moteur"], hote=dictAdresse["smtp"], port=dictAdresse["port"], utilisateur=dictAdresse["utilisateur"],
                                                      motdepasse=dictAdresse["motdepasse"], email_exp=dictAdresse["adresse"], use_tls=dictAdresse["startTLS"],
                                                      timeout=60*3, parametres=dictAdresse["parametres"])
            messagerie.Connecter()
            messagerie.Envoyer(message)
            messagerie.Fermer()
        except Exception as err:
            dlgprogress.Destroy()
            print((err,))
            if six.PY2:
                err = str(err).decode("iso-8859-15")
            dlgErreur = wx.MessageDialog(None, _(u"Une erreur a été détectée dans l'envoi par Email !\n\nErreur : %s") % err, _(u"Erreur"), wx.OK | wx.ICON_ERROR)
            dlgErreur.ShowModal() 
            dlgErreur.Destroy()
            return False
    
    # Suppression des répertoires et fichiers temporaires
    dlgprogress.Update(numEtape, _(u"Suppression des fichiers temporaires..."));numEtape += 1
    fichier = UTILS_Fichiers.GetRepTemp(fichier=u"%s.%s" % (nom, EXTENSIONS["decrypte"]))
    if os.path.isfile(fichier) == True :
        os.remove(fichier)
    fichier = UTILS_Fichiers.GetRepTemp(fichier=u"%s.%s" % (nom, EXTENSIONS["crypte"]))
    if os.path.isfile(fichier) == True :
        os.remove(fichier)
    
    # Fin du processus
    dlgprogress.Update(numEtape, _(u"Sauvegarde terminée avec succès !"))
    dlgprogress.Destroy()
    
    return True