# -*- coding: iso-8859-1 -*- u""" _vi aZ2^ v` .we^ . . .. + _2~ ._auqXZZX ._auqXZZZ` ...._... ~ ._|ii~ .aXZZY""^~~ vX#Z?""~~~._=ii|+++++++ii=, _=|+~- JXXX` )XXX' _|i+~ .__..._. +l= -~- SXXo )XZX: |i> ._%i>~~+|ii| .i| ._s_ass,,. ._a%ssssssss -SXZ6,,. )XZX: =l> _li+~` iii| .ii _uZZXX??YZ#Za, uXUX*?!!!!!!! "!XZ#ZZZZZXZXZ` =i: .|ii| .l|.dZXr 4XXo.XXXs,. -~^^^^^^^` -||, +i|=. |ii| :i>:ZXZ( ]XZX.-"SXZUZUXoa,, +l|, ~~|++|++i|||+~:ZXZ( ]ZZX ---~"?Z#m .__;=- ~+l|=____.___, :ZXZ( ]ZXX_________auXX2 ._||>+~- . -~+~++~~~- :ZXZ( ]ZXZZ#######UX*!" -+-- .>` _ .<}` 3; . .Zc .ii^ )Xo ]XX MoinMoin - Formulaire d'inscription Un formulaire de préinscription au Crans Copyright 2009 Antoine Durand-Gasselin Licence: GPLv3 """ import os, re, locale, base64, sys, unicodedata, random from commands import getstatusoutput as gso sys.path.append("/usr/scripts/gestion") from iptools import AddrInNet from MoinMoin import wikiutil from MoinMoin.widget import html from MoinMoin.Page import Page from MoinMoin.PageEditor import PageEditor from MoinMoin.formatter.text_html import Formatter PREINSCRIPTION_DIR = '/var/local/wiki/data/preinscription/' ETABLISSEMENTS = [ ("ENS", u"ENS Cachan"), ("IUT Cachan", u"IUT Cachan"), ("Maximilien Sorre", u"Maximilien Sorre"), ("Gustave Eiffel", u"Gustave Eiffel"), ("P1", u"Paris I"), ("P2", u"Paris II"), ("P3", u"Paris III"), ("P4", u"Paris IV"), ("P5", u"Paris V"), ("P6", u"Paris VI"), ("P7", u"Paris VII"), ("P8", u"Paris VIII"), ("P9", u"Paris IX"), ("P10", u"Paris X"), ("P11", u"Paris XI"), ("P12", u"Paris XII"), ("P13", u"Paris XIII"), ("IUFM", u"IUFM"), ("other", u"Autre...") ] LABOS = [ ("CMLA", u"CMLA - Centre de Mathématiques et de Leurs Applications"), ("GAPP", u"GAPP - Groupe d'Analyse des Politiques Publiques"), ("IDHE", u"IDHE - Institutions et Dynamiques Historiques de l'Economie"), ("LBPA", u"LBPA - Laboratoire de Biotechnologies et Pharmacologie génétique Appliquées"), ("LMT", u"LMT - Laboratoire de Mécanique et Technologie"), ("LPQM", u"LPQM - Laboratoire de Photonique Quantique et Moléculaire"), ("LSV", u"LSV - Laboratoire de Spécification et Vérification"), ("LURPA", u"LURPA - Laboratoire Universitaire de Recherche en Production Automatisée"), ("PPSM", u"PPSM - Laboratoire de Photophysique et Photochimie Supramoléculaires et Macromoléculaires"), ("SATIE", u"SATIE - Systèmes et Applications des Technologies de l\'Information et de l'Energie"), ("STEF", u"STEF - Sciences Techniques Education Formation") ] ANNEE_ENS = [ ("1", u"1A (licence)"), ("2", u"2A (master 1)"), ("3", u"3A (agrégation)"), ("4", u"4A (master 2)"), ("5", u"5A (thèse 1)"), ("6", u"6A (thèse 2)"), ("7", u"7A (thèse 3)"), ("8", u"8A+") ] ANNEE_ETUDE = [ ("-2", u"Seconde"), ("-1", u"Première"), ("0", u"Terminale"), ("1", u"BAC+1 (L1)"), ("2", u"BAC+2 (L2)"), ("3", u"BAC+3 (L3)"), ("4", u"BAC+4 (M1)"), ("5", u"BAC+5 (M2)"), ("6", u"BAC+6 (thèse 1)"), ("7", u"BAC+7 (thèse 2)"), ("8", u"BAC+8 (thèse 3)"), ("9", "Autre") ] SECTIONS_ENS = [ ("A0", u"A0 - Informatique"), ("A1", u"A1 - Mathématiques"), ("A2", u"A2 - Physique fondamentale"), ("A'2", u"A'2 - Physique appliquée"), ("A''2", u"A''2 - Chimie"), ("A3", u"A3 - Biochimie"), ("EEA", u"EEA"), ("B123", u"B123 - Technologie mécanique"), ("B1", u"B1 - Mécanique"), ("B2", u"B2 - Génie civil"), ("B3", u"B3 - Génie mécanique"), ("B1", u"B1 - Mécanique"), ("B2", u"B2 - Génie civil"), ("B3", u"B3 - Génie mécanique"), ("B4", u"B4 - Génie électrique"), ("C", u"C - Art et création industrielle"), ("D2", u"D2 - Economie gestion"), ("D3", u"D3 - Sciences sociales"), ("E", u"E - Anglais") ] class FormElement(): """Une classe pour représenter un élément d'un formulaire""" def __init__(self, wikitxt): self.content = wikitxt def render(self, request, parser): return wikiutil.renderText(request, parser, self.content) class Field(): """Une classe pour représenter les champs Attention, elle ne permet que de rendre les champs en html, et d'effectuer des tests unitaires""" error_txt='' error_msg='' error_field='' def __init__(self, id, prompt, default = "", input_type = "text", check=None, CLASS="formulaire_field"): self.id = id self.prompt = html.Text(prompt) self.default = default self.input_type = input_type self.CLASS= CLASS if check != None: self.check_hook = check else: self.check_hook = (lambda x: True) def fill(self, post): self.input = post.get(self.id, [''])[0] def check(self): self.error_txt= '' # Devrait pourtant être déjà vide self.default = self.input ok = self.check_hook(self) if ok: self.content = self.__dict__.get('content', self.input) # des fois qu'on ait oublié de le faire if self.content != self.default and self.default == self.input: self.default = self.content if not self.error_txt and not ok: self.error_txt = u'Valeur %s incorrecte pour le champ %s.' % (self.input, self.id) return ok def render(self, request, parser): champ = html.UL(CLASS=self.CLASS) champ.append(html.LI(CLASS="formulaire_id").append(self.prompt)) input = html.INPUT(type=self.input_type,name=self.id,value=self.default) champ.append(html.LI(CLASS="formulaire_input").append(input)) if self.error_txt: error = wikiutil.renderText(request, parser, self.error_txt) champ.append(html.LI(CLASS="formulaire_error").append(error)) if self.error_msg: request.add_msg(self.error_msg) return champ class MenuField(Field): def __init__(self, id, prompt, fields): Field.__init__(self, id, prompt) self.fields = fields def render(self, request, parser): champ = html.UL(CLASS="formulaire_field_%s" % self.id) champ.append(html.LI(CLASS="formulaire_id").append(self.prompt)) menu = html.SELECT(NAME=self.id, onchange='TestEtudes()') for opt, legend in self.fields: menu.append(html.OPTION(VALUE=opt).append(legend)) champ.append(menu) if self.error_txt: error = wikiutil.renderText(request, parser, self.error_txt) champ.append(html.LI(CLASS="formulaire_error").append(error)) if self.error_msg: request.add_msg(self.error_msg) return champ class PasswordField(Field): def fill(self, post): self.input = post.get(self.id, [''])[0] self.input2 = post.get(self.id+'2',[''])[0] def check(self): self.error_txt= '' # Devrait pourtant être déjà vide self.default = '' if self.input == self.input2: self.content = self.input return True else: self.error_txt = u'Les deux mots de passe diffèrent' return False def render(self, request, parser): champ = html.UL(CLASS="formulaire_field") champ.append(html.LI(CLASS="formulaire_id").append(self.prompt)) input = html.INPUT(type=self.input_type,onchange="testPassword()", name=self.id) champ.append(html.LI(CLASS="formulaire_input").append(input)) champ.append(html.LI().append('')) champ2 = html.UL(CLASS="formulaire_field") champ2.append(html.LI(CLASS="formulaire_id").append('Retapez le mot de passe')) input = html.INPUT(type=self.input_type, name=self.id+'2') champ2.append(html.LI(CLASS="formulaire_input").append(input)) if self.error_txt: error = wikiutil.renderText(request, parser, self.error_txt) champ2.append(html.LI(CLASS="formulaire_error").append(error)) return u'%s\n%s\n' % (champ, champ2) def is_name(self): """Vérifie que le champ input de l'objet passé en argument est un nom valide.""" analysed_content = unicodedata.normalize('NFKD', self.input) try: stripped_content = analysed_content.encode('ASCII', 'ignore') except UnicodeEncodeError: stripped_content = '' if re.match('[a-z][-a-z _]*', stripped_content.lower()): return True else: self.error_txt = u"""Valeur %s incorrecte pour le champ %s. Seules les lettres (éventuellement accentuées), l'espace et le tiret '-' sont acceptés.""" % (self.input, self.id) return False def is_chbre(self): if re.match('[abcghijp][0-9]{1,3}[gd]?', self.input.lower()): return True else: self.error_txt = u"""Valeur %s incorrecte pour votre chambre, celle-ci doit être de la forme Bxxx, Bxxxg ou Bxxxd, avec B la première lettre de votre batiment (P pour le Pavillon des Jardins), xxx le numéro de votre chambre et g ou d si vous êtes dans un T1 bis selon que vous soyiez à gauche ou à droite""" return False def is_phonenumber(self): chiffres = self.input.replace('.', '') if re.match('(0|\+[0-9][0-9])[0-9]{9}', chiffres): return True else: self.content = '' return True def is_dns(self): dns = self.input.lower() if re.match('[a-z][-a-z0-9_]*', dns): return True else: return False def get_mac(ip): "Récupère la mac" mac= 'XX' + ':XX'*5 if AddrInNet(ip, '138.231.136.0/21'): status, mac = gso("/usr/sbin/arp %s | perl -nle '{print $& if /00(:[0-9a-f]{2}){5}/}'" % ip) # gruik, gruik, grUUIIIk ! mac= mac.strip() return mac def is_valid_mac(self): mac = self.input.lower() if re.search("00((:|-|)[a-f0-9][a-f0-9]){5}", mac): return True else: self.default = get_mac(self.ip) return False class Formulaire(): """Une classe qui représente un formulaire. Elle contient un champs ``champs'', qui contient une liste de Fields, qui est la liste des champs qui doivent être demandés (dans le bon ordre l'ordre). """ def __init__(self, champs): self.champs = champs def render(self, request, parser): url = request.page.url(request) ret = html.FORM(action=url, NAME="preinscription") ret.append(html.INPUT(type='hidden', name='action', value='inscription')) f = html.UL(CLASS="formulaire_preinscription") for field in self.champs: champ = field.render(request, parser) f.append(html.LI().append(champ)) ret.append(f) ret.append(html.HR(CLASS= "invisiblesep")) ret.append(html.INPUT(type="submit", name="inscrire", value=u"Me préinscrire")) return unicode(ret) def check(self, post): u"""Vérifie les paramètres postés par l'utilisateur. Vérifie que toutes les entrées du formulaire (formulaire.fields) sont présentes et bien valides, (en appelant check() pour chaque champs). """ errors = [] for field in self.champs: field.fill(post) for field in self.champs: if not field.check(): errors.append(field.id) # est-ce que les test unitaires passent ? return errors def _create_inscription_form(request): """Renvoie les champs du formulaire inscription pour créer un Formulaire.""" ip = request.remote_addr mac_field = Field("mac", u"Adresse physique de votre carte réseau", check=is_valid_mac, default=get_mac(ip)) mac_field.ip = ip return [ # informations personnelles Field("nom", "Nom", check=is_name), Field("prenom", u"Prénom", check=is_name), Field("chbre", u"Chambre", check=is_chbre), MenuField('etablissement', u"Établissement d'études", ETABLISSEMENTS), Field("etablissement_autre", u"Précisez votre établissement d'études", CLASS='formulaire_field_etablissement_autre'), MenuField('annee_ens', u"Année scolaire à l'ENS", ANNEE_ENS), MenuField('annee', u"Choisissez votre année scolaire", ANNEE_ETUDE), MenuField('section_ens', u"Section", SECTIONS_ENS), MenuField('labo', u"Laboratoire", LABOS), Field("section", u"Précisez votre section", CLASS="formulaire_field_section"), Field("tel", u"Numéro de téléphone", check=is_phonenumber), # compte crans PasswordField("pass", u"Mot de passe", input_type='password'), # Votre machine Field("dns", u"Nom de votre ordinateur", check=is_dns), mac_field ] def _perform_inscription(request, formulaire): rand=random.Random() rand.seed() for i in range(1000): numero = rand.randint(100000, 999999) if not os.path.exists( os.path.join( PREINSCRIPTION_DIR, str( numero ) ) ): break else: # JAMAIS JAMAIS exécuté request.theme.add_msg(u"Erreur côté serveur, merci de réessayer", "error") return request.page.send_page() print "ok" fichier = open (os.path.join( PREINSCRIPTION_DIR, str( numero ) ), 'w') for field in formulaire.champs: # if type(field) == Field: content = field.content.split('\n')[0] fichier.write(u'%s: %s\n' % (field.id, content)) fichier.close() print "ok 2" # tests of redundancy request.theme.add_msg(u"Votre préinscription est réalisée, elle a le numero %d" % numero) return Page(request, "VieCrans/PreinscriptionOk").send_page() # form = {} # for field in formulaire.champs: # if type(field) == Field: # form[field.id] = field.content # adh = {} # adh['nom'] = form['nom'] # adh['prenom'] = form['prenom'] # adh['chbre'] = form['chbre'] # adh['tel'] = form['tel'] # if form['etablissement'] == 'ENS': # if int(form['annee_ens']) > 4: # adh['etudes'] = "ENS\n%(annee_ens)s\n%(labo)s" % form # else: # adh['etudes'] = "ENS\n%(annee_ens)s\n%(section_ens)s" % form # else: # adh['etudes'] = "%(etablissement)s\n%(annee)s\n%(secion)s" %form # # machine = {} # machine['macAdress'] = form['mac'] # machine['host'] = form['dns'] def execute(pagename, request): request.page = Page(request, pagename) request.formatter.setPage(request.page) request.loadTheme('crans-www') formulaire = Formulaire(_create_inscription_form(request)) post = request.form parser = wikiutil.searchAndImportPlugin(request.cfg, "parser", request.page.pi['format']) if not request.dicts.has_member("GroupeAdmin", request.user.name) and not request.user == 'AntoineDurandGasselin': request.theme.add_msg(u"Non, car tu es méchant", "error") return(request.page.send_page()) if post.has_key('inscrire'): if formulaire.check(post) == []: return(_perform_inscription(request, formulaire)) else: request.theme.add_msg(u'des erreurs', 'error') request.emit_http_headers() request.theme.send_title(u"Formulaire de préinscription", pagename=pagename, html_head='') request.write(request.formatter.startContent("content")) form = formulaire.render(request, parser) # THIS IS A BIG HACK. IT NEEDS TO BE CLEANED UP request.write(form) request.write(request.formatter.endContent()) request.theme.send_footer(pagename) request.theme.send_closing_html()