# -*- coding: UTF-8 -*-
###########################################################################
# Eole NG - 2007
# Copyright Pole de Competence Eole  (Ministere Education - Academie Dijon)
# Licence CeCill  cf /root/LicenceEole.txt
# eole@ac-dijon.fr
#
# utilisateurs.py
#
# page web de gestion des utilisateurs
#
###########################################################################
from html import escape
import os, tempfile, base64

from zephir.eolerpclib import xmlrpclib
from twisted.web import static
from zephir.web.template.design import Design, proxy, get_user
from zephir.web.template.page import IPreferences
from zephir.web.html.erreur import *
from zephir.web.config import Navigation
import zephir.web.config as config
from zephir.utils.ldap_user import encrypt_passwd

js_check="""<SCRIPT LANGUAGE="JavaScript">
<!-- Begin
function CheckAll()
{
   count = document.frm.elements.length;
   for (i=0; i < count; i++) {
      if (document.frm.elements[i].type=="checkbox") {
          document.frm.elements[i].checked = 1;
      }
   }
}
function UnCheckAll()
{
   count = document.frm.elements.length;
   for (i=0; i < count; i++) {
       if (document.frm.elements[i].type=="checkbox") {
           document.frm.elements[i].checked = 0;
      }
   }
}
//  End -->
</script>"""

class Logout(Design):
    """
    """
    isLeaf=True

    def wmfactory_title(self,request):
        return "Session fermée"

    def wmfactory_content(self, request):
        return "<br><p><span id=\"message\">Session fermée</span></p><p><a href=\"/\">Se connecter</a></p><br/>"

    def renderView(self, request):
        session = request.getSession()
        session.expire()
        request.setHeader('WWW-authenticate', 'Basic realm="%s"' % ("zephir",))
        return self.content

class Preferences(Design):
    """Conteneur des pages de gestion des données utilisateur
    """
    def __init__(self, *args, **kwargs):
        self.entites = {
            'modif_prefs':ModifPrefs
            }
        super().__init__(*args, **kwargs)

    def getChild(self, name, request):
        if static.isDangerous(name):
            return static.dangerousPathError
        name = name.decode()
        if name in self.entites:
            return self.entites[name]()
        return self

    def wmfactory_title(self,request):
        return "Vos préférences"

    def wmfactory_content(self, request):
        return self.content

    def wmfactory_menu(self, request):
        return Navigation(aide="page2.html#section2").menu()

    def boolean2checked(self,boolean):
        if boolean == 1:
            return "checked"
        else:
            return ""

    def formulaire(self, d, allow_passwd=False):
        """création du contenu
        """
        l = ["""<table border=0 cellspacing=5>"""]
        l.append("""<h1>Informations utilisateur</h1>
        <script LANGUAGE="JavaScript"><!--
        function validfields(form)
        {
            //getting the values:
            if (form.nom.value.length > 40)
            {
                alert("nom : 40 caractères maximum !");
                form.nom.focus();
                return false;
            }
            if (form.prenom.value.length > 40)
            {
                alert("prenom : 40 caractères maximum !");
                form.prenom.focus();
                return false;
            }
            if (form.mail.value.length > 100)
            {
                alert("mail : 100 caractères maximum !");
                form.mail.focus();
                return false;
            }
            if (form.sms.value.length > 20)
            {
                alert("sms : 20 caractères maximum !");
                form.sms.focus();
                return false;
            }
            if (form.passwd.value != form.passwd2.value)
            {
                alert("Les mots de passe ne correspondent pas")
                form.passwd.focus();
                return false;
            }
            return true;
        }
        //--></script>
        <form method="post" action="/preferences/modif_prefs" enctype="multipart/form-data" onSubmit="return validfields(this)">
        <tr><td>Nom</td><td><input type="text" name="nom" value="%(nom)s"/></td></tr>
        <tr><td>Prénom</td><td><input type="text" name="prenom" value="%(prenom)s"/></td></tr>
        <tr><td>Mail</td><td><input type="text" name="mail" value="%(mail)s"></td></tr>
        <tr><td>SMS</td><td><input type="text" name="sms" value="%(sms)s" disabled/></td></tr>
        <tr><td>Activation du mail</td><td><input type="checkbox" name="mail_actif" %(mail_actif)s/></td></tr>
        <tr><td>Activation du SMS</td><td><input type="checkbox" name="sms_actif" %(sms_actif)s disabled/></td></tr>
        <tr><td>Clef SSH%(cle)s</td><td><input type="file" name="clef_ssh"/></td></tr>""" % d)
        # si annuaire local, champs de modification du mot de passe
        if allow_passwd:
            l.append("""<tr><td>Nouveau mot de passe</td><td><input type="password" autocomplete='off' name="passwd"/></td></tr>
            <tr><td>Confirmation du mot de passe</td><td><input type="password" autocomplete='off' name="passwd2"/></td></tr>""")
        l.append("""<tr><td>Thème actuel</td><td>%s</td></tr>""" % str(config.selected_theme))
        l.append("""<tr><td colspan="2" align="center"><input type="submit" value="Modifier"></td></tr></form> """)
        l.append("""</table><p><center><a href="/">Retour à l'accueil<a></p>""")
        return "".join(l)

    def renderView(self, request):
        d = {}
        self.user = get_user(request)
        try:
            try:
                liste = backend(proxy(request).get_user(u(self.user)))
                rights = backend(proxy(request).get_permissions(u(self.user)))
            except Exception as e:
                raise BackendError(e)
            else:
                d['mail'] = liste[1]
                d['sms'] = liste[4]
                d['sms_actif'] = self.boolean2checked(liste[6])
                d['mail_actif'] =  self.boolean2checked(liste[5])
                d['nom'] =  liste[2]
                d['prenom'] = liste[3]
                if liste[9] == 1:
                    d['cle'] = ' (présente) '
                else:
                    d['cle'] = ''
                # changement de mot de passe proposé si autorisé et annuaire local
                allow_passwd = 40 in rights and config.ADRESSE_LDAP in ('localhost', '127.0.0.1')
                self.content = self.formulaire(d, allow_passwd)

        except (FrontendError,BackendError) as e:
            self.content = e

        return self.content


class ModifPrefs(Design):
    """Conteneur des pages de gestion des données utilisateur
    """
    isLeaf = True

    def getChild(self, name, request):

        if static.isDangerous(name):
            return static.dangerousPathError
        if name == b'modif_prefs':
            return self
        return Preferences()

    def wmfactory_title(self,request):
        return "Modification des informations utilisateur"

    def wmfactory_content(self, request):
        return self.content

    def renderView(self, request):
        try:
            try:
                try:
                    if request.args[b'clef_ssh'][0]:
                        # récupération de la clef ssh
                        clef_ssh = base64.encodebytes(request.args[b'clef_ssh'][0].decode().rstrip().encode()).decode()
                        # enregistrement de la clef ssh
                        backend(proxy(request).save_key(clef_ssh))
                except KeyError:
                    pass
                except:
                    raise BackendError("clef ssh")

                mail_actif = int(b'mail_actif' in request.args)
                sms_actif = int(b'sms_actif' in request.args)
                for key in [b'nom', b'prenom', b'mail']:
                    if key not in request.args:
                        raise Exception(key.decode())
                nom = escape(request.args[b'nom'][0].decode())
                prenom = escape(request.args[b'prenom'][0].decode())
                mail = escape(request.args[b'mail'][0].decode())
                try:
                    sms = escape(request.args[b'sms'][0].decode())
                except:
                    sms = ""
                passwd_enc = ""
            except Exception as e:
                raise FrontendError(e)
            try:
                user = get_user(request)
                result = backend(proxy(request).edit_user(u(user),u(nom),u(prenom),u(mail),u(sms),u(mail_actif),u(sms_actif)))
                self.content = """<p><span id="message">Modifications effectuées</span></p><br>"""
                # gestion du changement de mot de passe si disponible
                if b'passwd' in request.args:
                    passwd = escape(request.args[b'passwd'][0].decode())
                    if passwd:
                        enc_passwd = base64.encodebytes(encrypt_passwd(passwd).encode())
                        result = backend(proxy(request).update_passwd(enc_passwd))
                        # après changement du mot de passe, on le modifie dans la session
                        prefs = request.getSession(IPreferences)
                        setattr(prefs,'password', passwd)
                        setattr(prefs,'zephir', config.build_proxy(user, passwd))
                        self.content += """<p>Votre mot de passe a été mis à jour</p>"""
                self.content += """<p><a href="/">Retour à l'accueil</a></p>"""
            except xmlrpclib.ProtocolError:
                return """Vous n'êtes pas autorisé à effectuer cette action"""
            except Exception as e:
                import traceback
                traceback.print_exc()
                raise BackendError(e)

        except (FrontendError,BackendError) as e:
            self.content = e
        return self.content

class Admin(Design):
    """Conteneur des pages d'administration
    """
    def __init__(self, *args, **kwargs):
        self.entites = {
            'droits':DroitsUtilisateur
            ,'modif_droits':ModifDroits
            ,'del_user':DelUser
            ,'conf_usb':ConfUsb
            ,'gen_usb':GenUsb
            ,'maj_client':MajClient
            ,'del_client':DelClient
            }
        super().__init__(*args, **kwargs)

    def getChild(self, name, request):


        if static.isDangerous(name):
            return static.dangerousPathError
        name = name.decode()
        if name in self.entites:
            return self.entites[name]()
        return self

    def wmfactory_title(self,request):
        return "Administration"

    def wmfactory_content(self, request):
        return self.content

    def wmfactory_menu(self, request):
        return Navigation(aide="howto/page8.html").menu()

    def formulaire(self,list_user, request):
        """génération de la page html"""
        l = []
        l.append( """<FORM METHOD='POST' ACTION='/administration/droits'><center><h1>Changement des droits d'un utilisateur</h1><table cellpadding='5' cellspacing='0' align='center' valign='middle'>""")
        if list_user is not None:
            l.append("""<tr><tr><td>Utilisateurs autorisés</td><td><select name="user">
                    <option selected="selected" value=""></option>""")
            for user in list_user:
                l.append("""<option value=%s>%s</option>""" % (user,user))
            l.append("""</select></td>""")
        l.append("""<td rowspan="2"><INPUT type='SUBMIT' value='Ok' height='100%'></td></tr>""")
        l.append("""<tr><td>(autres utilisateurs)</td><td><input type="text" size="20" name="new_user" value=""></td></tr></table></form><br/>""")
        l.append("""<p><h1>Fichiers pour clé USB</h1>
        <FORM METHOD='POST' ACTION="/administration/conf_usb">
        <INPUT type='SUBMIT' value="Générer un nouveau fichier de configuration"></FORM>
        </p><br/><br/>""")
        l.append("""<p><font size="-1" align="right">Version actuelle des paquets Zéphir : %s</font></p>
        """ % config.VERSION_ZEPHIR)
        return "".join(l)

    def renderView(self, request):
        # récupération de la liste des utilisateurs ayant des droits si on le peut
        liste_users=None
        try:
            liste_users=backend(proxy(request).list_users())
        except:
            # on n'a pas les droits de gestion des utilisateurs
            pass

        self.content=self.formulaire(liste_users, request)

        return self.content


class DroitsUtilisateur(Design):
    """formulaire de gestion des droits d'un utilisateur
    """

    def getChild(self, name, request):
        if static.isDangerous(name):
            return static.dangerousPathError
        if name == b"droits":
            return self
        return Admin()

    def sort_fonctions(self,a,b):
        if a[0]==b[0]:
            return 0
        elif a[0] > b[0]:
            return 1
        else:
            return -1

    def wmfactory_title(self,request):
        if not self.user:
            return "Erreur !"
        else:
            return "Autorisations pour l'utilisateur " + self.user

    def wmfactory_menu(self, request):
        return Navigation(aide="page2.html#section3").menu()

    def wmfactory_content(self, request):
        try:
            try:
                assert self.user != ""
            except:
                return """<p><span id="message">Nom d'utilisateur non défini</span></p><p><a href="/administration">Retour à la page d'administration</a></p>"""
            # lecture des arguments dans le cas d'un ajout ou dune suppression
            update = ''
            try:
                update = escape(request.args[b'update'][0].decode())
                assert update in ('add', 'del')
            except:
                pass
            else:
                type_res = escape(request.args[b'type_res'][0].decode())
                id_res = escape(request.args[b'id_res'][0].decode())
                if update == 'del':
                    backend(proxy(request).del_restriction(u(self.user), u(type_res), u(id_res)))
                else:
                    backend(proxy(request).add_restriction(u(self.user), u(type_res), u(id_res)))
            rights = backend(proxy(request).get_permissions(u(self.user)))
            groups = backend(proxy(request).get_rights())
            restrictions = backend(proxy(request).get_restrictions(u(self.user)))
            return self.formulaire(rights, groups, restrictions)
        except xmlrpclib.ProtocolError:
            return """<p><span id="message">Vous n'êtes pas autorisé à effectuer cette action</span></p>"""
        except Exception as e:
            if update != '':
                return """<p><span id="message">Erreur de modification des restrictions, mauvais identifiant pour la ressource sélectionnée</span></p><p><a href="/administration/droits?user=%s">Retour à la page de gestion des droits</a></p>""" % self.user
            else:
                return "erreur backend"

    def formulaire(self, rights_list, group_list, restrictions):
        """ affiche les autorisations d'un utilisateur
        autorisations est une liste (de listes) contenant les noms des fonctions disponible
        et 1 ou 0 selon qu'elles sont autorisées ou non"""

        # convertis la liste de droits
        groupes = {}
        for groupe in group_list:
            groupes[groupe[0]] = groupe[1]

        if not self.user:
            return """<p>Vous devez saisir un nom d'utilisateur.<br>
        <a href="javascript:history.back()">Retour</a></p>"""
        else:

            l = ["""<center><h1>Gestion des autorisations pour l'utilisateur %s</h1>"""%self.user]
            l.append("""<form id="form_del_user" method="POST" action="administration/del_user?user=%s"><input type="submit" value="Supprimer cet utilisateur"></form></center>""" % self.user)
            l.append(js_check)
            l.append("""<table cellpadding='15' cellspacing='0' align='center' valign='middle' width='100%'><!--contenu2-->\n<tr><td align=center>""")
            l.append("""<table id="tab_administration">\n<tr><td>""")
            l.append("""<table id="tab_fonctions"> <!--cases à cocher-->""")
            l.append("""<FORM METHOD='POST' NAME='frm' ACTION='/administration/modif_droits'>""")
            l.append("""<input type="hidden" name="user" value="%s">""" % (self.user))
            l.append("""<tr><th colspan="2"><b><center>Fonctions autorisées</b><br>
                        <input type=button value="Toutes" onclick="CheckAll()">&nbsp;/&nbsp;
                        <input type=button value="Aucune" onclick="UnCheckAll()"></center></th></tr>""")
            for groupe in list(groupes.keys()):
                if groupe in rights_list:
                    coche = " checked "
                else:
                    coche = ""
                string = """<tr><td class="td_fonctions">%s</td><td class="td_checkbox"><input type="checkbox" name="%s" %s></td></tr>""" % (groupes[groupe], str(groupe), coche)
                l.append(string)
            l.append("""<tr><td colspan="2" align="center"><input type='submit' value='Modifier'></td></tr></form>\n</table></td><!--fin:cases à cocher-->
            """)
            # message si pas de groupes de droits
            if list(groupes.keys()) == []:
                l.append("""<tr><td colspan="2">pas de fonctions référencées</td>""")

            # affichage des restrictions de l'utilisateur
            # table des restrictions
            l.append("""<td size="10%"></td><td>""")
            l.append("""<table id="tab_limitation""><tr><th colspan="3"><center><b>Limitation des ressources</b></center></th></tr><tr><td>type de ressource</td><td>identifiant autorisé</td><td></td></tr>""")
            select_type = """<select name="type_res">"""
            for type_res, data in list(config.type_res_label.items()):
                libelle = data[0]
                select_type += """<option value="%s" selected="selected">%s</option>""" % (type_res, libelle)
            select_type += """</select>"""
            if restrictions != []:
                for type_res in list(restrictions.keys()):
                    if type_res in list(config.type_res_label.keys()):
                        label = config.type_res_label[type_res][0]
                    else:
                        label = type_res
                    for id_res in restrictions[type_res]:
                        l.append("""<tr><td>%s</td><td>%s</td><td><a href=/administration/droits?user=%s&update=del&type_res=%s&id_res=%s>supprimer</a></td></tr>""" % (label, id_res, self.user, type_res, id_res))
            l.append("""<tr><FORM METHOD='POST' action='/administration/droits'><input type="hidden" name="user" value="%s">""" % (self.user))
            l.append("""<input type="hidden" name="update" value="add">
<td>%s</td><td><input type="text" name="id_res"></td>
<td><input type='submit' value='Ajouter'></td></FORM></tr>""" % select_type)
            l.append("""</table>""")
            l.append("""</td></tr>\n</table></td></table></td><!--fin:contenu2-->""")
            return "\n".join(l)


    def renderView(self, request):
        self.user = ""
        if b'new_user' in request.args:
            self.user = escape(request.args[b'new_user'][0].decode())
        if self.user == "":
            try:
                self.user = escape(request.args[b'user'][0].decode())
            except:
                pass
        # session dans self.prefs
        self.prefs=request.getSession()
        return self.content


class ModifDroits(Design):
    """Prise en compte des modifications
    """
    isLeaf = True

    def getChild(self, name, request):
        if static.isDangerous(name):
            return static.dangerousPathError
        if name == b"modif_droits" :
            return self
        return Admin()

    def wmfactory_title(self,request):
        return "Modification de l'utilisateur " + self.user

    def wmfactory_content(self, request):
        # tentative de modification des autorisations
        try:
            group_list = backend(proxy(request).get_rights())
        except xmlrpclib.ProtocolError:
            return """Vous n'êtes pas autorisé à effectuer cette action"""
        except Exception:
            return "erreur backend"

        # convertis la liste de droits
        groupes = {}
        for groupe in group_list:
            groupes[groupe[0]] = groupe[1]
        new_perms = [ int(i) for i in self.modifs ]
        libelles = [ groupes[i] for i in new_perms ]
        try:
            backend(proxy(request).save_permissions(self.user,new_perms))
        except xmlrpclib.ProtocolError:
            return """<br>Vous n'avez pas la permission d'ajouter des autorisations !<br><br>"""
        except Exception as e:
            l = ["""<br>Erreur lors de la sauvegarde des permissions dans la base de données<br><br>"""]
        else:
            l = ["""<br /><table><tr><td class="tab_titre" align="center">Nouvelles autorisations pour l'utilisateur %s<br /></td></tr>
                    <tr><td></td></tr><tr><td align="left">%s</td></tr></table>""" % (self.user, """</td></tr><tr><td align="left">""".join(libelles))]
        l.append("""<br><a href="/administration">Retour à la page d'administration</a></p>""")
        return "".join(l)

    def renderView(self, request):
        self.modifs = [arg.decode() for arg in request.args if arg != b'user']
        # récupération de la session dans self.prefs
        self.prefs = request.getSession()
        self.user = escape(request.args[b'user'][0].decode())
        return self.content

class DelUser(Design):
    """Prise en compte des modifications
    """
    isLeaf = True

    def getChild(self, name, request):
        if static.isDangerous(name):
            return static.dangerousPathError
        if name == b"del_user" :
            return self
        return Admin()

    def wmfactory_title(self,request):
        return "Suppression de l'utilisateur " + self.user

    def wmfactory_content(self, request):
        return self.content

    def renderView(self, request):
        self.user=escape(request.args[b'user'][0].decode())
        if b'confirm' in request.args:
            try:
                backend(proxy(request).del_user(u(self.user)))
            except xmlrpclib.ProtocolError:
                self.content = """Vous n'êtes pas autorisé à effectuer cette action.<p><a href="/administration">Retour</a></p>"""
            except Exception as e:
                self.content = """Erreur lors de la suppression : %s<p><a href="/administration/modif_droits?user=%s">Retour</a></p>""" % (str(e), self.user)
            else:
                self.content = """<p><span id="message">Suppression effectuée</span><p><a href="/administration">Retour à la page d'administration</a></p>"""
        else:
            # page de confirmation
            self.content = """<p><span id="message">Voulez-vous vraiment supprimer l'utilisateur %s ?</span></p><form id="form_del_user" method="POST" action="/administration/del_user?user=%s&confirm=yes"><input type="submit" value="Confirmer la suppression"></form>""" % (self.user, self.user)
            self.content += """<p><a href="/administration/droits?user=%s">Retour à la gestion des droits</a></p>""" % self.user
        return self.content

class MajClient(Design):
    """Met à jour le rpm de zephir-client mis à dispo sur le site
    """
    isLeaf = True

    def getChild(self, name, request):
        if static.isDangerous(name):
            return static.dangerousPathError
        if name == b"maj_client" :
            return self
        return Admin()

    def wmfactory_title(self,request):
        return "Mise à jour du paquet"

    def wmfactory_content(self, request):
        return self.content

    def renderView(self, request):
        try:
            try:
                # on récupère le fichier et son nom
                nom = escape(request.args[b'rpm_name'][0].decode())
                nom_deb = escape(request.args[b'deb_name'][0].decode()).split("|")
            except Exception:
                raise FrontendError("paquet zephir-client")
            try:
                contenu = request.args[b'rpm'][0].decode()
                contenu = base64.encodebytes(contenu)
            except:
                contenu = ""
            try:
                self.content = ""
                nom_deb.insert(0,nom)
                for paquet in nom_deb:
                    if paquet != "":
                        paquet = paquet.replace('\\','/')
                        if not os.path.basename(paquet).startswith('zephir-client'):
                            self.content = """Ce fichier n'est pas un paquet zephir-client (%s) !<br/>""" % paquet
                        else:
                            backend(proxy(request).update_client(u(paquet), contenu))
                            self.content += """<p>Fichier mis à jour (%s)</p>""" % paquet
                self.content += """<p><a href="/administration">Retour à la page d'administration</a></p>"""
            except:
                raise BackendError("erreur de mise en place du client")

        except Exception as e:
            self.content = e

        return self.content

class DelClient(Design):
    """supprime un rpm de zephir-client mis à dispo sur le site
    """
    isLeaf = True

    def getChild(self, name, request):
        if static.isDangerous(name):
            return static.dangerousPathError
        if name == b"del_client" :
            return self
        return Admin()

    def wmfactory_title(self,request):
        return "Suppression du paquet"

    def wmfactory_content(self, request):
        return self.content

    def renderView(self, request):
        try:
            try:
                # on récupère le fichier et son nom
                nom = request.args[b'paquet'][0].decode()
            except Exception:
                raise FrontendError("paquet zephir-client")
            try:
                nom=os.path.basename(nom.replace('\\','/'))
                if not nom.startswith('zephir-client'):
                    self.content = """Ce fichier n'est pas un paquet zephir-client !<br/>
                    <p><a href="/administration">retour au menu d'administration</a></p>"""
                else:
                    # on supprime le fichier.
                    backend(proxy(request).remove_client(u(nom)))
                    self.content = """<p><span id="message">Fichier supprimé</span></p><p><a href="/administration">Retour à la page d'administration</a></p>"""
            except Exception as e:
                raise BackendError("erreur lors de la suppression du paquet : %s" % str(e))

        except Exception as e:
            self.content = e

        return self.content

class ConfUsb(Design):
    """Formulaire de création d'un fichier de données pour clé usb
    """
    isLeaf = True
    def getChild(self, name, request):
        if static.isDangerous(name):
            return static.dangerousPathError
        if name == b"conf_usb" :
            return self
        return Admin()

    def wmfactory_menu(self, request):
        return Navigation(aide="page11.html").menu()

    def wmfactory_title(self,request):
        return "Saisie des données"

    def wmfactory_content(self, request):
        content = """<h1>Saisie des valeurs par défaut</h1><h2>Les champs vides seront ignorés</h2>
<FORM METHOD=POST ACTION="gen_usb">
<table cellpadding="8" cellspacing="0" align="center" valign="middle" >
<tr><td>Adresse du serveur Zéphir </td><td><input type=text size="20" name="adresse_zephir" value="%s"></td></tr>
<tr><td>Mettre en place une config. réseau minimale </td><td><select name="conf_net">
    <option selected="selected" value="">&nbsp;</option>
    <option value="oui">oui</option>
    <option value="non">non</option>
</select></td></tr>
<tr><td>Interface réseau ayant accès à Zéphir</td><td><input type=text size="6" name="interf" value="eth0"></td></tr>
<tr><td>Adresse IP de cette interface</td><td><input type=text size="16" name="ip_eth0" value=""></td></tr>
<tr><td>Masque réseau de cette interface</td><td><input type=text size="16" name="mask_eth0" value=""></td></tr>
<tr><td>Passerelle par défaut</td><td><input type=text size="16" name="gateway" value=""></td></tr>
<tr><td><INPUT name="submit" type=SUBMIT value="Générer le fichier"></td>
<td><input name="initialiser" value="Initialiser" type="reset" />
</td></tr>
</table>
</form>
<p><a href="/administration">Retour à la page d'administration</a></p>
""" % (config.ADRESSE_ZEPHIR)
        return content.encode(config.charset)

class GenUsb(Design):
    """Génération effective d'un fichier de configuration pour cle usb
    """
    isLeaf = True

    def getChild(self, name, request):
        if static.isDangerous(name):
            return static.dangerousPathError
        if name == b"gen_usb" :
            return self
        return Admin()

    def wmfactory_title(self,request):
        return "Génération de fichier pour clé USB - Téléchargement"

    def wmfactory_content(self, request):
        return self.content

    def formulaire(self, contenu):
        self.content = """<h1>Génération de fichier pour clé USB</h1><h2>Le fichier doit être placé à la racine d'une clé USB sous le nom zephir.conf</h2>
        <br><br><br>Contenu du fichier :<br><br>"""
        self.content += """<table><tr><td align="left">""" + "<br>".join(contenu) + """</td></tr></table>"""
        # lien sur le fichier temporaire
        filename = "zephir-" + os.path.basename(tempfile.mktemp()) + ".conf"
        # on vérifie que le répertoire temporaire existe
        if not os.path.isdir(config.PATH_TEMP):
            os.makedirs(config.PATH_TEMP)
        f = open(os.path.join(config.PATH_TEMP,filename),"w")
        f.write("\n".join(contenu))
        f.close()
        self.content += """
        <p><a href="/tmp/%s">Télécharger (clic droit → Enregistrer la cible du lien sous…)</a></p>
        <p><a href="javascript:history.back()">Retour à la saisie des valeurs</a></p>
        """ % filename

    def renderView(self, request):
        try:
            # récupération des champs non vides
            contenu = ["""# Fichier de configuration pour la procédure enregistrement zephir"""]
            try:
                adresse_zephir = escape(request.args[b'adresse_zephir'][0].decode())
            except KeyError:
                pass
            else:
                if adresse_zephir != "":
                    contenu.append('adresse_zephir="%s"' % adresse_zephir)
            try:
                conf_net = escape(request.args[b'conf_net'][0].decode())
            except KeyError:
                pass
            else:
                if conf_net != "":
                    contenu.append('conf_net="%s"' % conf_net)
            try:
                interf= escape(request.args[b'interf'][0].decode())
            except KeyError:
                pass
            else:
                if interf != "":
                    contenu.append('interf="%s"' % interf)
            try:
                ip_eth0 = escape(request.args[b'ip_eth0'][0].decode())
            except KeyError:
                pass
            else:
                if ip_eth0 != "":
                    contenu.append('ip_eth0="%s"' % ip_eth0)
            try:
                mask_eth0 = escape(request.args[b'mask_eth0'][0].decode())
            except KeyError:
                pass
            else:
                if mask_eth0 != "":
                    contenu.append('mask_eth0="%s"' % mask_eth0)
            try:
                gateway = escape(request.args[b'gateway'][0].decode())
            except KeyError:
                pass
            else:
                if gateway != "":
                    contenu.append('gateway="%s"' % gateway)


        except Exception as e:
            self.content = e
        else:
            self.formulaire(contenu)

        return self.content

class AffCodeEnt(Design):
    """Page d'affichage des plages d'identifiants réservées pour un ent
    """
    isLeaf = True

    def getChild(self, name, request):
        if static.isDangerous(name):
            return static.dangerousPathError
        if name == b'aff_ent':
            return self
        return Preferences()

    def wmfactory_title(self,request):
        return "Gestion des identifiants ENT"

    def wmfactory_content(self, request):
        return self.content

    def _dump_html(self, code_ent, codes, data, invert, sort_serv):
        """rendu html de la page"""
        # fonctions javascript
        self.content = """
<script language='javascript'>
function switch_ent(sel_ent) {
    form_ent = document.forms['form_ent'];
    val = sel_ent.options[sel_ent.selectedIndex].value;
    form_ent['code_ent'].value=val;
    form_ent.submit();
}
function valide_code(code1, code2) {
    code_ent = document.forms['form_ent']['code_ent'].value;
    code = code1 + code2;
    var regex  = /(^[a-z]{2}\d{4}$)/;
    if (regex.test(code) == false)
    {
        alert("Valeur incorrecte : " + code_ent[0] + code1 + code_ent[1] + code2);
        return false;
    }
    return true;
}
function update_l_max() {
    document.forms['form_res']['code_l_max'].value=document.forms['form_res']['code_l_min'].value;
}
function update_c_max() {
    document.forms['form_res']['code_c_max'].value=document.forms['form_res']['code_c_min'].value;
}
function update_code_ent() {
    document.forms['form_res']['code_ent'].value = document.forms['form_res']['code_l_min'].value + document.forms['form_res']['code_c_min'].value;
}
function confirm_reserv(form_res) {
    if (valide_code(form_res['res_min1'].value, form_res['res_min2'].value) == false) {
        return false;
    }
    if (valide_code(form_res['res_max1'].value, form_res['res_max2'].value) == false) {
        return false;
    }
    if (confirm("Valider la reservation de cette plage ?") == false) {
        return false;
    }
    form_res.submit();
}
function confirm_manuel(form_res) {
    update_code_ent();
    return confirm_reserv(form_res);
}
</script>"""
        if code_ent:
            self.content += "<h1>Plages d'identifiants réservées pour l'ENT&nbsp;"
        else:
            self.content += """<h1>Choisissez un code d'ENT&nbsp;"""
        self.content += """<select name="code_ent_sel" onChange="switch_ent(this)">"""
        codes.insert(0,"")
        for code in codes:
            if code == code_ent:
                self.content += """<option value="%s" selected="selected">%s</option>""" % (code, code)
            else:
                self.content += """<option value="%s">%s</option>""" % (code, code)
        self.content += """</select></h1><FORM METHOD="POST" action="/aff_ent" name="form_ent">"""
        if sort_serv:
            self.content += """<input type="checkbox" name="sort_serv" checked="checked">Tri par serveur&nbsp"""
        else:
            self.content += """<input type="checkbox" name="sort_serv">Tri par serveur&nbsp"""
        if invert:
            self.content += """<input type="checkbox" name="invert" checked="checked">Tri inversé&nbsp"""
        else:
            self.content += """<input type="checkbox" name="invert">Tri inversé&nbsp"""
        if code_ent != "":
            self.content += """<input type="submit" value="Trier">"""
        self.content += """<input type="hidden" name="code_ent" value="%s"/></FORM><BR/>""" % code_ent
        inputs_sort = ""
        if invert:
            inputs_sort += """<input type="hidden" name="invert" value="1"/>"""
        if sort_serv:
            inputs_sort += """<input type="hidden" name="sort_serv" value="1"/>"""
        # affichage des intervalles
        if data:
            self.content += """<table border="1"><tr><th>Premier identifiant</th><th>Dernier identifiant</th><th>Réservation</th></tr>"""
            code, free_space, rngs, free_rngs = data[0]
            # formulaire de réservation de plage
            self.content += """<tr><form action="/aff_ent" name="form_res" method="POST"  onSubmit="return confirm_reserv(this);">
<td>%s<input type="text" name="res_min1" size="2" maxlength="2"/>%s<input type="text" name="res_min2" size="4" maxlength="4"/></td>
<td>%s<input type="text" name="res_max1" size="2" maxlength="2"/>%s<input type="text" name="res_max2" size="4" maxlength="4"/></td>
<td>%s<input type="hidden" name="code_ent" value="%s"/><input type="submit" value="Réservation manuelle"></td>
</form></tr>""" % (code[0], code[1], code[0], code[1], inputs_sort, code_ent)
            # plages libres
            for minid, maxid in free_rngs:
                self.content += """<tr><td><font color="green">%s</font></td><td><font color="green">%s</font></td><td><font color="green">Disponible</td></font></tr>""" % (minid, maxid)
            # calcul des lignes du tableau
            if invert and sort_serv == False:
                rngs.reverse()
            for minid, maxid, serv in rngs:
                if (serv == -1) and (sort_serv == True):
                    self.content += """<tr><td><font color="red">%s</font></td><td><font color="red">%s</font></td><td><font color="red">Réservé</td></font></tr>""" % (minid, maxid)
            lignes = []
            # tri par serveur ou ordre numérique
            if sort_serv == True:
                rngs.sort(key=lambda x:x[2], reverse=invert)
            for minid, maxid, serv in rngs:
                if (serv != -1) or (sort_serv == False):
                    if serv != -1:
                        serv = """<a href="/serveur/aff?id=%s">serveur %s</a>""" % (serv, serv)
                        lignes.append("""<tr><td>%s</td><td>%s</td><td>%s</td></tr>""" % (minid, maxid, serv))
                    else:
                        lignes.append("""<tr><td><font color="red">%s</font></td><td><font color="red">%s</font></td><td><font color="red">Réservé</td></font></tr>""" % (minid, maxid))
            self.content += "\n".join(lignes)
            self.content += "</table>"
            self.content += """<p>Nombre d'identifiants restants : %s</p>""" % str(free_space)
        else:
            opt_letters = "<option>%s</option>" % "</option><option>".join([chr(ind) for ind in range(65,91)])
            opt_nums = "<option>%s</option>" % "</option><option>".join([str(num) for num in range(10)])
            # aucun code ent choisi (ou pas de réservations existantes), on autorise le blocage de plages manuel
            self.content += """<table><tr><form action="/aff_ent" name="form_res" method="POST"  onSubmit="return confirm_manuel(this);">
<td><select name="code_l_min" onchange="update_l_max()" value="">%s</select><input type="text" name="res_min1" size="2" maxlength="2"/><select name="code_c_min" onchange="update_c_max()" value="">%s</select><input type="text" name="res_min2" size="4" maxlength="4"/></td>""" % (opt_letters, opt_nums)
            self.content += """<td><input type="text" name="code_l_max" size="1" maxlength="1" disabled="true" value="A"/><input type="text" name="res_max1" size="2" maxlength="2"/><input name="code_c_max" size="1" maxlength="1" disabled="true" value="0"/><input type="text" name="res_max2" size="4" maxlength="4"/></td>"""
            self.content += """<td>%s<input type="hidden" name="code_ent" value=""/><input type="submit" value="Réservation manuelle"></td>
</form></tr></table>""" % (inputs_sort,)

    def renderView(self, request):
        try:
            try:
                data = []
                code_ent = ""
                if b'code_ent' in request.args:
                    code_ent = request.args[b'code_ent'][0].decode()
                    if code_ent:
                        # réservation d'une plage si demandé
                        if b'res_min1' in request.args and request.args[b'res_min1'][0].decode() != '':
                            code_min = code_ent[0] + request.args[b'res_min1'][0].decode() + code_ent[1] + request.args[b'res_min2'][0].decode()
                            code_max = code_ent[0] + request.args[b'res_max1'][0].decode() + code_ent[1] + request.args[b'res_max2'][0].decode()
                            result = backend(proxy(request).entid.reserve_range(code_min, code_max))
                        data = backend(proxy(request).entid.get_id_pools(code_ent))
                codes = backend(proxy(request).entid.get_code_ent())
                invert = False
                if b'invert' in request.args:
                    invert = True
                sort_serv = False
                if b'sort_serv' in request.args:
                    sort_serv = True
                self._dump_html(code_ent, codes, data, invert, sort_serv)
            except xmlrpclib.ProtocolError:
                return """Vous n'êtes pas autorisé à effectuer cette action"""
            except Exception as e:
                raise FrontendError(e)
        except (FrontendError,BackendError) as e:
            self.content = e

        return self.content


