diff --git a/gestion/arp.py b/gestion/arp.py index 3ca0ac0d..df120147 100755 --- a/gestion/arp.py +++ b/gestion/arp.py @@ -1,5 +1,5 @@ #! /usr/bin/env python -# -*- coding: utf-8 -*- +# -*- coding: utf-8 -*- # Serveur SSL qui renvoie la MAC correspondant à une IP # Ce serveur est utilisé sur Nectaris par les bornes wifi pour faire @@ -57,15 +57,15 @@ class ARPProtocol(basic.LineReceiver): return self.transport.write(str(m) + "\r\n") else: return self.transport.write("unknown\r\n") - + class ARPFactory(protocol.ServerFactory): """Backend du serveur. Effectue la résolution IP/MAC.""" protocol = ARPProtocol - + def __init__(self, network='0.0.0.0/0'): self.ldap = crans_ldap() self.network = network - + def getMac(self, IP): return defer.succeed(self._getMac(IP)) diff --git a/gestion/chgpass.py b/gestion/chgpass.py index eea5812a..c07da0e8 100755 --- a/gestion/chgpass.py +++ b/gestion/chgpass.py @@ -5,7 +5,7 @@ Script de changement de mots de passe LDAP Utilisation : - * cas 1 : sans arguements par un utlisateur lambda : + * cas 1 : sans arguements par un utlisateur lambda : changement de son propre mdp * cas 2 : avec argument par un utilisateur ayant accès total à la base LDAP (respbats) mais PAS ROOT : @@ -28,7 +28,7 @@ try : except : ldap_password = '' ldap_auth_dn = '' - + uri = 'ldap://ldap.adm.crans.org' syslog.openlog('chgpass',syslog.LOG_PID,syslog.LOG_AUTH) @@ -45,14 +45,14 @@ Il ne doit pas être basé sur un mot du dictionnaire.""", 'jaune') print "Il est conseillé d'utiliser une combinaison de minuscules, majuscules,\nde chiffres et d'au moins un caractère spécial." print "Le mot de passe tapé ne sera pas écrit à l'écran." print "Taper Ctrl-D pour abandonner" - + try : while 1 : mdp = getpass.getpass('Nouveau mot de passe : ') - + ### Test du mdp ## 1 - Longueur - if len(mdp) < 6 : + if len(mdp) < 6 : cprint(u'Mot de passe trop court', 'rouge') continue @@ -68,8 +68,8 @@ Il ne doit pas être basé sur un mot du dictionnaire.""", 'jaune') if "'" in mdp: cprint(u'Les accents ou caractères bizarres ne sont pas autorisés (mais #!@*&%{}| le sont !)', 'rouge') - continue - + continue + ## 3 - assez de caractères de types différents ? chiffres = 0 majuscules = 0 @@ -89,33 +89,33 @@ Il ne doit pas être basé sur un mot du dictionnaire.""", 'jaune') (not majuscules and not minuscules) : cprint(u'Mot de passe trop simple.', 'rouge') continue - + ## 4 - Cracklib test = commands.getoutput("echo '%s' | /usr/sbin/crack_testlib" % mdp) if test.split(':')[-1] != ' ok' : - commentaire = { + commentaire = { ' it does not contain enough DIFFERENT characters': u'Il y a trop de caractères identiques.' , ' it is based on a dictionary word': u'Le mot de passe est basé sur un mot du dictionnaire' , ' it is too simplistic/systematic': u'Le mot de passe est trop simple/répétitif' }.get(test.split(':')[-1],test.split(':')[-1]) cprint(commentaire, 'rouge') continue - + ### On redemande le mot de passe mdp1 = getpass.getpass('Retaper mot de passe : ') if mdp != mdp1 : cprint(u'Les deux mots de passe entrés sont différents, réesayer', 'rouge') continue - + break - + # Changement mdp if os.system("/usr/bin/ldappasswd -H '%s' -x -D '%s' -w '%s' '%s' -s '%s' > /dev/null" % (uri, ldap_auth_dn, ldap_password, dn, mdp) ): cprint(u'Erreur lors du changement de mot de passe', 'rouge') syslog.syslog("LDAP password changed for dn=%s" % dn) else : cprint(u'Changement effectué avec succès', u'vert') - + except KeyboardInterrupt : cprint(u'\nAbandon', 'rouge') pass @@ -130,7 +130,7 @@ if __name__ == '__main__' : # Changement de son mot de passe login = getuser() self_mode = True - + elif '-h' in sys.argv or '--help' in sys.argv or len(sys.argv) != 2 : print "%s " % sys.argv[0].split('/')[-1].split('.')[0] print "Changement du mot de passe du compte choisi." @@ -143,11 +143,11 @@ if __name__ == '__main__' : if not c.isalnum() and not c=='-' : cprint(u'Login incorrect', 'rouge') sys.exit(1) - + if getuser() == login : cprint(u'Utiliser passwd pour changer son propre mot de passe', 'rouge') sys.exit(2) - + if self_mode : s = commands.getoutput('sudo -u respbats ldap_whoami') else : @@ -155,13 +155,13 @@ if __name__ == '__main__' : if not s : cprint(u'Login non trouvé dans la base LDAP', 'rouge') sys.exit(3) - + # Ca a l'air bon if s.find('\n\n') != -1 : # Plusieurs trouvé : pas normal cprint(u'Erreur lors de la recherche du login : plusieurs occurences !', 'rouge') sys.exit(4) - + s = s.split('\n') try : dn = s[0].split()[1] @@ -172,13 +172,13 @@ if __name__ == '__main__' : except : cprint(u'Erreur lors de la recherche du login', 'rouge') sys.exit(5) - + if self_mode : # Il faut vérifier l'ancien mot de passe ldap_auth_dn = dn ldap_password = getpass.getpass('Mot de passe actuel : ') s = commands.getoutput("/usr/bin/ldapwhoami -H '%s' -x -D '%s' -w '%s'" % ( uri, ldap_auth_dn, ldap_password ) ).strip() - try : + try : resultat = s.split('\n')[0].split(':')[1].strip() except : cprint(u"Erreur lors de l'authentification", 'rouge') @@ -186,7 +186,7 @@ if __name__ == '__main__' : if resultat != dn : cprint({ 'Invalid credentials (49)': u'Mot de passe invalide' }.get(resultat, resultat), 'rouge') sys.exit(8) - + elif len(s) > 3 and os.getuid()!=0 : # Adhérent avec droits et on est pas root From = 'roots@crans.org' diff --git a/gestion/chsh.py b/gestion/chsh.py index e6e4753e..aaca8f49 100755 --- a/gestion/chsh.py +++ b/gestion/chsh.py @@ -1,9 +1,9 @@ #! /usr/bin/env python # -*- coding: utf-8 -*- -""" Changement du shell de l'utilisateur lancant le programme +""" Changement du shell de l'utilisateur lancant le programme DOIT ETRE LANCE PAR SUDO - + Copyright (C) Frédéric Pauget Licence : GPLv2 """ @@ -31,7 +31,7 @@ adh = s['adherent'] if len(adh) != 1 : print 'Erreur fatale lors de la consultation de la base LDAP' sys.exit(3) - + adh = adh[0] shell = prompt(u'Nouveau shell :') fd=open('/etc/shells') diff --git a/gestion/config.py b/gestion/config.py index f1127caf..b82d1f0c 100644 --- a/gestion/config.py +++ b/gestion/config.py @@ -171,7 +171,7 @@ Si tu as des questions, contacte disconnect@crans.org NB : L'upload consiste en l'envoi de données vers des machines n'étant pas branchées sur le CRANS. --- +-- Disconnect team""" message_hard = u"""From: %(from)s @@ -199,7 +199,7 @@ Si tu as des questions, contacte disconnect@crans.org NB: L'upload consiste en l'envoi de données vers des machines n'étant pas branchées sur le CRANS. --- +-- Disconnect team""" @@ -210,7 +210,7 @@ Content-Type: text/plain; charset="iso-8859-15" %(proprio)s uploade actuellement %(upload)s Mo. --- +-- Message créé par deconnexion.py""" message_disconnect_hard = u"""From: %(from)s @@ -220,7 +220,7 @@ Content-Type: text/plain; charset="iso-8859-15" %(proprio)s a été déconnecté pour upload (%(upload)s Mo). --- +-- Message créé par deconnexion.py""" message_disconnect_multi = u"""From: %(from)s @@ -234,23 +234,23 @@ L'adhérent %(proprio)s a été déconnecté %(nbdeco)d fois pour upload en un m Le PS a été généré et se trouve sur zamok : %(ps)s --- -Message créé par deconnexion.py""" +-- +Message créé par deconnexion.py""" message_demenagement = u"""From: %(from)s To: %(to)s -Subject: =?iso-8859-1?Q?D=E9m=E9nagement=20non=20d=E9clar=E9?= +Subject: =?iso-8859-1?Q?D=E9m=E9nagement=20non=20d=E9clar=E9?= Content-Type: text/plain; charset="iso-8859-15" Bonjour, -Il semble que tu étais inscrit dans la chambre %(chambre), mais un +Il semble que tu étais inscrit dans la chambre %(chambre), mais un autre adhérent s'y est inscrit, ce qui suppose que tu n'y es plus. Pourrais tu nous préciser ta nouvelle chambre ou adresse stp ? Si tu es parti du campus, souhaites-tu garder tes machines ? --- +-- Merci par avance, Les membres actifs du Crans""" @@ -306,7 +306,7 @@ La machine %(hostname)s a été déconnectée pendant 24h pour utilisation du protocole %(protocole)s. Nombre de paquets : %(nb_paquets)s paquets depuis le %(datedebut)s. --- +-- Message créé par deconnexion.py""" deconnexion = u"""From: %(From)s To: %(To)s @@ -332,7 +332,7 @@ il pénalise l'ensemble des adhérents de l'association. Tu seras donc déconnecté 24h. --- +-- Disconnect Team""" message_disconnect_multi = u"""From: %(from)s @@ -345,7 +345,7 @@ L'adhérent %(proprio)s a été déconnecté %(nbdeco)d fois pour p2p en un an ! Le PS a été généré et se trouve sur zamok : %(ps)s --- +-- Message créé par deconnexion.py""" @@ -449,7 +449,7 @@ Pour y avoir accés depuis l'extérieur il faut utiliser un mot de passe: Sur ce, bienvenue au Cr@ns ! PS: Il t'est conseillé de conserver ce mail à toutes fin utiles --- +-- Les membres actifs.""" @@ -469,7 +469,7 @@ de les utiliser est disponible sur la page : Si tu as des questions, n'hésite pas à les poser à d'autres câbleurs ou aux nounous. --- +-- Les nounous""" pages_infos_droits = { "Cableur" : "https://wiki.crans.org/%C3%8AtreC%C3%A2bleur", @@ -496,7 +496,7 @@ https://wiki.crans.org/CransAdministratif?action=AttachFile&do=get&target=charte Merci par avance, --- +-- Le bureau du CRANS""" txt_menage_cableurs = u"""From: Crans <%(From)s> @@ -515,5 +515,5 @@ heureux de te les remettre. Cordialement, --- +-- Le bureau du CRANS""" diff --git a/gestion/config_mail.py b/gestion/config_mail.py index c195da97..9d9d310b 100755 --- a/gestion/config_mail.py +++ b/gestion/config_mail.py @@ -3,7 +3,7 @@ ############################################################################### # config_mail : gestion du .forward et .procmailrc des adhérents ############################################################################### -# The authors of this code are +# The authors of this code are # Etienne Chové # # Copyright (C) 2006 Etienne Chové @@ -95,14 +95,14 @@ class MailConfigError(ReferenceError): def _IsMail(mail): """ Dit si la chaine fournie est une adresse mail valide - """ + """ return bool(re.match('[a-z0-9_\.-]+@[a-z0-9_-]+(\.[a-z0-9_-]+)+',mail.lower())) def _Clean(texte): """ Nettoie une chaine de caractère/liste en supprimant les lignes vides/commentés, et retourne une liste - """ + """ if type(texte) != list: texte = texte.split('\n') return [ x.strip() for x in texte if x.strip() and x[0]!='#' ] @@ -123,31 +123,31 @@ def _GetConfig(): # forward simple if _IsMail(fic_forward): return {'forward':fic_forward, 'spam':'accepte'} - + # utilisation de procmail if fic_forward != _Clean(forward_procmail)[0]: raise MailConfigError, 'Fichier forward non compréhensible' - + ## lecture du .procmailrc fic_procmail = _Clean( open('%s/.procmailrc'%home).readlines() ) - + # forward if _IsMail( fic_procmail[-1][1:].strip() ) and fic_procmail[-2] == ":0" : forward = fic_procmail[-1][1:].strip() fic_procmail = fic_procmail[:-2] else: forward = '' - + # forward simple dans le procmailrc if not fic_procmail: return {'forward':forward, 'spam':'accepte'} - + # marquage des spams tmp = _Clean( procmail_mark ) if fic_procmail[:len(tmp)] != tmp: raise MailConfigError, 'Fichier de procmail non compréhensible' fic_procmail = fic_procmail[len(tmp):] - + # suppression des spams ? if not fic_procmail: return {'forward':forward, 'spam':'marque'} @@ -158,7 +158,7 @@ def _GetConfig(): def _SetConfig(forward = None, spam= None): """ Modifie la configuration de l'utilisateur courant """ - + # variable new_spam if spam in ['accepte','supprime','marque']: new_spam = spam @@ -166,7 +166,7 @@ def _SetConfig(forward = None, spam= None): new_spam = _GetConfig()['spam'] else: raise ValueError, 'Valeur interdite pour le paramètre spam' - + # variable forward if forward == None: new_forward = _GetConfig()['forward'] @@ -174,7 +174,7 @@ def _SetConfig(forward = None, spam= None): new_forward = forward else: raise ValueError, 'Adresse mail invalide' - + # génération des fichiers if new_spam=='accepte': # suppression du .procmailrc @@ -210,17 +210,17 @@ def _Sudo(uid, forward=None, spam=None): c += " --forward=%s" % forward if spam!=None: c += " --spam=%s" % spam - + # execution de la commande status, output = getstatusoutput(c) - + # code d'erreur if status: sys.stderr.write("Erreur sudo : %s\n"%c) sys.stderr.write(output) sys.stderr.flush() sys.exit(status) - + # valeurs de retour res = {} for line in output.split('\n'): @@ -230,37 +230,37 @@ def _Sudo(uid, forward=None, spam=None): ## ############################################################################ - + def MailConfig(uid=None, forward=None, spam=None): """ Modifie ou retourne la configuration mail de l'utilisateur - + user = utilisateur à configurer, si None configure l'utilisateur courant forward = adresse vers laquelle rediriger les mails, chaine vide si pas de redirection spam = action à effectuer sur les spams (accepte, supprime, marque) - + Pour les champs forward et spam, la valeur None ne touche pas au champ. - + Retourne un dictionnaire { 'forward':'', 'spam':'' } """ - + ## demande pour un autre utilisateur if uid: return _Sudo(uid=uid, forward=forward, spam=spam) - + ## nettoyage des variables cfg = _GetConfig() if forward == cfg['forward']: forward = None if spam == cfg['spam']: spam = None - + ## modifications if forward!=None or spam!=None: _SetConfig(forward=forward, spam=spam) - + ## on renvoie la configuration return _GetConfig() - + if __name__=="__main__": ## parsage des arguments forward = None @@ -271,10 +271,10 @@ if __name__=="__main__": forward = v elif o == '--spam': spam = v - + ## execution de MailConfig res = MailConfig(forward=forward, spam=spam) - + ## affichage des résultats for i in res.items(): print "%s=%s" % i diff --git a/gestion/email_tools.py b/gestion/email_tools.py index b6e6ea36..845ad94d 100755 --- a/gestion/email_tools.py +++ b/gestion/email_tools.py @@ -20,10 +20,10 @@ def format_sender(sender, header_charset='ISO-8859-15'): """ from email.Header import Header from email.Utils import parseaddr, formataddr - + # Split real name (which is optional) and email address parts sender_name, sender_addr = parseaddr(sender) - + # We must always pass Unicode strings to Header, otherwise it will # use RFC 2047 encoding even on plain ASCII strings. sender_name = str(Header(unicode(sender_name), header_charset)) @@ -71,14 +71,14 @@ def send_email(sender, recipient, subject, body, server='localhost', cc=None, de sender = format_sender(sender) recipient = format_sender(recipient) if cc: cc = format_sender(cc) - + # Create the message ('plain' stands for Content-Type: text/plain) msg = MIMEText(body.encode(body_charset), 'plain', body_charset) msg['From'] = sender msg['To'] = recipient msg['Subject'] = Header(unicode(subject), header_charset) if cc: msg['Cc'] = cc - + if debug: actual_recipient = [debug] else: @@ -89,7 +89,7 @@ def send_email(sender, recipient, subject, body, server='localhost', cc=None, de actual_sender = format_sender(actual_sender) else: actual_sender = sender - + # Send the message if isinstance(server, SMTP): server.sendmail(actual_sender, actual_recipient, msg.as_string()) @@ -113,23 +113,23 @@ def parse_mail_template(fichier): """ if not isinstance(fichier, file): fichier = file(fichier) - + encoding = fichier.readline() matched = re.search(r'^Encoding:\s*([^\r\n]*)', encoding) if matched: encoding = matched.group(1) else: raise SyntaxError("Encoding manquant dans template") - + subject = fichier.readline() matched = re.search(r'^Subject:\s*([^\r\n]*)', subject) if matched: subject = matched.group(1).decode(encoding) else: raise SyntaxError("Subject manquant dans template") - + if fichier.readline() not in ['\r\n', '\n']: raise SyntaxError("le fichier n'a pas le bon format") - + body = fichier.read().decode(encoding) return subject, body diff --git a/gestion/hptools.py b/gestion/hptools.py index 0afb35fa..cab3a8fc 100755 --- a/gestion/hptools.py +++ b/gestion/hptools.py @@ -1,10 +1,10 @@ #!/usr/bin/env python # -*- coding: utf-8 -*- -""" +""" Fichier de base d'interface avec les switchs manageables. -Donne la classe switch qui permet d'effectuer les opérations +Donne la classe switch qui permet d'effectuer les opérations élémentaires sur les switchs manageable HP 26xx. Frédéric PAUGET @@ -52,7 +52,7 @@ import pexpect class ssh : """ Ouverture d'une connexion ssh, envoi de commandes et récupération du résultat """ - + def __init__(self,host) : """ Ouverture d'une connexion ssh vers le switch choisi """ self.switch = host.split('.')[0] # On garde pas le fqdn @@ -68,14 +68,14 @@ class ssh : traceback.print_exc() print "Contenu du buffer :" print self.ssh.before - + def __del__(self) : """Ferme la connexion : envoi logout et attend """ self.ssh.sendline("logout") self.ssh.send("y") self.ssh.send("y") self.ssh.close() - + def send_cmd(self,cmd,timeout=15): """ Envoi une commande, attend le prompt et retourne la réponse """ # Envoi de la commande @@ -89,7 +89,7 @@ class ssh : '%s\(config\)# ' % self.switch, 'quit: Control-C'], timeout=timeout) - + self.__sshout = self.__sshout + self.ssh.before if index == 0: # On répond oui @@ -100,7 +100,7 @@ class ssh : elif index == 2: # On doit continuer, on envoie espace self.ssh.send(" ") - + return self.__sshout except pexpect.TIMEOUT: print "Timeout !" @@ -115,7 +115,7 @@ class snmp : """ host doit être la machine sur laquelle se connecter version est la verion du protocole snmp à utiliser : 1, 2c ou 3 le reste des données doit être ou non fourni suivant la version - + pour v1 et v2c seule la communauté est prise en compte pour v3 authentication_protocol, authentication_pass et username sont requis si accès en authNoPriv si privacy_pass est fourni accès en authPriv @@ -127,7 +127,7 @@ class snmp : self._machine = cl.search("host=%(host)s" % {'host': host})["machineCrans"][0] except IndexError: raise ValueError(u"Cette machine n'est pas un switch du Cr@ns") - + # l'engineid du switch n'est que sa mac avec quelques fioritures autour... mac = self._machine.mac().replace(':', '') self._engineid = '0000000b0000%(mac)s0' % {'mac': mac[:-1]} @@ -136,25 +136,25 @@ class snmp : self.options = "-v %s -c '%s' %s " % ( version, community, host ) elif version =='3' : self.options = "-v 3 -e %s -u %s -a %s -A '%s' -l authNoPriv" % ( self._engineid, username, authentication_protocol, authentication_pass ) - if privacy_pass : + if privacy_pass : self.options += " -x DES -X '%s' -l authPriv" % privacy_pass self.options += " %s " % host else : raise ValueError('Version incorrecte') - + def __exec(self,cmd) : s, r = getstatusoutput(cmd) if s : r=r.replace('snmpget: ','') raise ConversationError(r,cmd) return r - + def get(self,oid) : """ Retourne le résultat correspondant à l'oid demandé """ return self.__exec('snmpget -O vq %s %s ' % ( self.options, oid ) ) def get_string(self,oid) : - """ Retourne le resultat convertit en String correspondant à l'oid demandé. Fonctionne avec les types de depart String, Integer, Hex-String. Raise ValueError sinon. """ + """ Retourne le resultat convertit en String correspondant à l'oid demandé. Fonctionne avec les types de depart String, Integer, Hex-String. Raise ValueError sinon. """ s= self.__exec('snmpget -O v %s %s ' % ( self.options, oid ) ) if s=="\"\"": return "" @@ -168,16 +168,16 @@ class snmp : return unicode(var) else: raise ValueError('Type inconnu') - + def set(self,oid,typ,val) : - """ Change la valeur le l'oid donné. + """ Change la valeur le l'oid donné. type est le type de la valeur val est la valeur à écrire """ return self.__exec('snmpset -O vq %s %s %s %s' % (self.options, oid, typ, val ) ) - + def walk(self,base_oid) : - """ Retourne le résultat de snmpwalk + """ Retourne le résultat de snmpwalk le retour est un dictionnaire { oid : valeur } """ lignes = self.__exec('snmpwalk -O q %s %s' % (self.options, base_oid ) ).split('\n') @@ -190,14 +190,14 @@ class snmp : ############################################################################################# ### Gestion des switchs proprement dite - + class hpswitch : """ Classe pour l'administration des switchs HP. """ - + # Variables internes __debug=0 __logDest=stderr - + # Variables internes switch = None # nom du switch prise = '' @@ -207,17 +207,17 @@ class hpswitch : """ Switch doit être le nom du switch """ if self.__debug : self.__logDest.write("HP DEBUG : __init__(switch=%s)\n" % switch ) self.switch = switch.lower() - + # Config snmp self.get, self.set, self.walk = config_snmp_secrete(snmp,switch) - + def send_cmd(self,cmd,timout=15) : """ Envoi une commande par ssh au switch """ if not self.__conn_ssh : self.__conn_ssh = ssh(self.switch) - + return self.__conn_ssh.send_cmd(cmd,timout) - + def show_prise_mac(self,prise='') : """ Retourne le(s) adresse(s) MAC présentes sur la prise.""" if not prise : prise = self.prise @@ -248,18 +248,18 @@ class hpswitch : # On a rien trouvé return None - + def __scp(self,destination,fichier) : if self.__debug : self.__logDest.write("HP DEBUG : scp(%s,%s,%s)\n" % (fichier, self.switch, destination)) if exists(fichier): system('scp %s %s:%s' % (fichier, self.switch, destination)) - + def update(self,file=None) : """ Upload le fichier de config fourni Fait rebooter le switch """ self.__scp('cfg/startup-config',file) - + def upgrade(self,file=None) : """ Changement de firmware, le firmware est dans le fichier fourni en argument @@ -270,18 +270,18 @@ class hpswitch : """ Ajoute la clef publique ssh aux clefs autorises par le switch """ self.scp('ssh/mgr_keys',file) - + def multicast(self,ip='') : - """ Donne la liste des ports du swich inscrits au flux multicast donné - Si aucun flux donné teste tous les flux multicast possibles. + """ Donne la liste des ports du swich inscrits au flux multicast donné + Si aucun flux donné teste tous les flux multicast possibles. Retourne un dictionnaire : { adresse du flux : [ ports inscrits ] } """ if self.__debug : self.__logDest.write("HP DEBUG : multicast(ip=%s)\n" % ip) - if ip : + if ip : data = self.walk('STATISTICS-MIB::hpIgmpStatsPortIndex2.%s' % ip) return { ip : data.values() } - + else : data = self.walk('STATISTICS-MIB::hpIgmpStatsPortIndex2') result = {} @@ -291,14 +291,14 @@ class hpswitch : except : continue result.setdefault(ip,[]) result[ip].append(port) - + return result def nb_prises(self) : """ Retourne le nombre de prises du switch """ if self.__debug : self.__logDest.write("HP DEBUG : nb_prises()\n") return int(findall(r'Switch 26([0-9]{2})', self.version())[0]) - + def version(self) : """ Retourne la version du firmware du switch """ if self.__debug : self.__logDest.write("HP DEBUG : version()\n") @@ -309,13 +309,13 @@ class hpswitch : if not prise : prise = self.prise if self.__debug : self.__logDest.write("HP DEBUG : enable(prise=%s)\n" % prise) return self.set('IF-MIB::ifAdminStatus.%d' % int(prise), 'i', 1) - + def disable(self,prise=0) : """ Désactive une prise """ if not prise : prise = self.prise if self.__debug : self.__logDest.write("HP DEBUG : disable(prise=%s)\n" % prise) return self.set('IF-MIB::ifAdminStatus.%d' % int(prise), 'i', 2) - + def __is(self,oid,prise) : if not prise : prise = self.prise prise = str(prise) @@ -328,7 +328,7 @@ class hpswitch : return nb prise = prise.replace('-','') return self.get(oid + '.' + prise) == 'up' - + def is_enable(self,prise=0) : """ Retoune True ou False suivant si la prise est activée ou non Si prise=all retourne le nombre de prises activées sur le switch """ @@ -340,7 +340,7 @@ class hpswitch : Si prise=all retourne le nombre de prises up sur le switch """ if prise != 'all': prise = int(prise) return self.__is('IF-MIB::ifOperStatus',prise) - + def nom(self,nom=None,prise=0) : """ Retourne ou attribue le nom à la prise fournie """ if not prise : prise = self.prise @@ -349,19 +349,19 @@ class hpswitch : return self.get(oid) else : self.set(oid, 's' , nom) - + def eth_mode(self,mode=None,prise=0) : - """ Fixe ou retourne le mode d'une prise - mode est un tuple : (vitesse, duplex) ou simplement "auto" + """ Fixe ou retourne le mode d'une prise + mode est un tuple : (vitesse, duplex) ou simplement "auto" vitesse est : 10 100 ou 1000 duplex est FD, HD ou auto """ if not prise : prise = self.prise oid = 'CONFIG-MIB::hpSwitchPortFastEtherMode.%d' % int(prise) - + if mode == None : return self.get(oid) - + # Conversion du mode if mode == 'auto' : code = 5 @@ -391,7 +391,7 @@ class hpswitch : return result - + class sw_chbre(hpswitch) : def __init__(self,chbre) : # On retrouve la chbre dans l'annuaire @@ -410,20 +410,20 @@ class sw_chbre(hpswitch) : self.prise10Mb = False except : raise ValueError('Chambre %s inconnue' % chbre) - + # Config snmp self.get, self.set, self.walk = config_snmp_secrete(snmp,self.switch) - - + + def reconfigure(self) : """ Reconfigure la prise (nom et vitesse) """ in10 = self.eth_mode().find('10Mbits') != 1 - + if self.prise10Mb and not in10 : self.eth_mode(('10','auto')) elif not self.prise10Mb and in10 : self.eth_mode('auto') - + nom = 'Chambre_%s' % self.chbre.capitalize() if nom != self.nom() : self.nom(nom) @@ -448,13 +448,13 @@ class sw_prise(sw_chbre): if __name__ == '__main__' : import sys, getopt, sre - + try : options, arg = getopt.getopt(sys.argv[1:], 'U:hc:', [ 'help', 'snmp' ]) except getopt.error, msg : print msg sys.exit(1) - + cmds = [] firmware='' wait=True @@ -466,17 +466,17 @@ if __name__ == '__main__' : print "L'envoi de firmware ne fait pas rebooter le switch" print "L'option --snmp ajoute les commandes de reconfiguration snmp" sys.exit(0) - - elif opt=='-c' : + + elif opt=='-c' : cmds.append(val) - + elif opt=='-U' : firmware=val - + elif opt=='--snmp' : cmds.append(reconf_snmp) cmds.append("write memory") - + # Quels switchs ? switchs=[] if arg : @@ -484,20 +484,20 @@ if __name__ == '__main__' : for sw in all_switchs() : if re.match(sw) : switchs.append(sw) - + if not switchs : print "Aucun switch trouvé" print "Note : il faut une _regex_ (!= wilcards au sens du shell)" sys.exit(3) - + if not cmds and not firmware : cmds=map(str.strip,sys.stdin.readlines()) - + # Ce que l'on va faire print "Commandes :\n\t", '\n\t'.join(cmds) - print "\nSwitchs : ", ' '.join(switchs) + print "\nSwitchs : ", ' '.join(switchs) print - + try: raw_input("Appuyer sur entrée pour continuer") except EOFError: @@ -511,8 +511,8 @@ if __name__ == '__main__' : s = hpswitch(sw) if firmware : s.upgrade(firmware) - for cmd in cmds : + for cmd in cmds : print s.send_cmd(cmd) except : print 'ERREUR' - + diff --git a/gestion/iptools.py b/gestion/iptools.py index f8dac5e8..a3ff7dbe 100755 --- a/gestion/iptools.py +++ b/gestion/iptools.py @@ -14,7 +14,7 @@ from config import NETs_regexp __QuadToDecDone = {} def QuadToDec(ip) : - """ + """ Retourne la représentation décimale d'une ip ip est de la forme xxx.xxx.xxx.xxx """ @@ -33,9 +33,9 @@ def QuadToDec(ip) : # Pour accélérer DecToQuad __DecToQuadDone = {} - + def DecToQuad(ip_dec) : - """ + """ Retourne la représentation habituelle d'une ip (xxx.xxx.xxx.xxx) ip_dec est l'IP en base 10 """ @@ -62,7 +62,7 @@ def param(net, raw=False) : 'netmask' : yyy.yyy.yyy.yyy , 'broadcast' : zzz.zzz.zzz.zzz } sinon retourne {} - + Si raw = False, alors, on ne convertit pas les résultats sous forme pointée. Ils restent sous forme d'un entier. """ @@ -70,18 +70,18 @@ def param(net, raw=False) : return __paramDone[net] reseau = {} ip, mask = net.split('/') - + try : mask = int(mask) dec_ip = QuadToDec(ip) if dec_ip == -1 : raise except : return {} - + # Calcul du netmask non_dec_netmask = netmask(mask, dec=False) dec_netmask = netmask(mask) - + reseau = { 'netmask' : dec_netmask, 'network' : dec_ip & dec_netmask, 'broadcast' : dec_ip | non_dec_netmask } @@ -91,7 +91,7 @@ def param(net, raw=False) : else: __paramDone[net] = reseau return reseau - + def AddrInNet(ip,net) : """ ip est de la forme xxx.xxx.xxx.xxx @@ -101,7 +101,7 @@ def AddrInNet(ip,net) : Note : retourne False si l'IP est une adresse de réseau ou broadcast """ if type(net)==str : net = [ net ] - + r = False ip = QuadToDec(ip) for ne in net : @@ -109,11 +109,11 @@ def AddrInNet(ip,net) : if ip == n['broadcast'] or ip == n['network'] : return False r = r or n['netmask'] & ip == n['network'] - + return r def AddrInNets(ip,nets) : - """ Vérifie si l'ip est au moins dans un des réseaux + """ Vérifie si l'ip est au moins dans un des réseaux de la liste nets (voir AddrInNet) """ for net in nets : if AddrInNet(ip,net) : diff --git a/gestion/ldap_passwd.py b/gestion/ldap_passwd.py index 039f81f8..97ca8f3d 100644 --- a/gestion/ldap_passwd.py +++ b/gestion/ldap_passwd.py @@ -3,7 +3,7 @@ # ldap_passwd.py : manipulation des mots de passes LDAP # $Id: ldap_passwd.py,v 1.7 2006-05-04 17:46:58 chove Exp $ ############################################################################### -# The authors of this code are +# The authors of this code are # Bjorn Ove Grotan # Etienne Chové # @@ -27,19 +27,19 @@ ############################################################################### # For extra strength passwords, we wanted SSHA in our LDAP-environment -# as the standard python-module 'sha' does not support ssha, but this can -# easily be implemented with a few extra functions. +# as the standard python-module 'sha' does not support ssha, but this can +# easily be implemented with a few extra functions. # # SSHA can be described as: # the SHA1-digest of a password with a sequence of "salt" bytes, where # the bytes are randomly chosen - followed by the same salt bytes -# For LDAP-use, the SHA1 and SSHA-digest has to be base64-encoded. +# For LDAP-use, the SHA1 and SSHA-digest has to be base64-encoded. # # Example-LDIF: # {SSHA}oaEG3PJ10sHxGcSxsDRRooTifL55/2NOdN3nU1VEV+NFzc9Q -# +# # This package should now support passwords compatible with [1] Samba using the [2] -# smbpasswd module for [3] Python. The samba compability is added for use with Samba +# smbpasswd module for [3] Python. The samba compability is added for use with Samba # as PDC with storing user and host-information in LDAP. # # [1] http://www.samba.org @@ -70,7 +70,7 @@ if smb: algos['lmpassword'] = 'lan man hash' algos['ntpassword'] = 'nt hash' - + def getsalt(chars=string.letters+string.digits, length=16): ''' Generate a random salt. Default length is 16 ''' salt = '' @@ -79,18 +79,18 @@ def getsalt(chars=string.letters+string.digits, length=16): return salt def mkpasswd(pwd, sambaver=3, algo='SSHA', salt=None): - ''' Make a given password cryptated, possibly with different - crypt-algorihtms. This module was written for use with + ''' Make a given password cryptated, possibly with different + crypt-algorihtms. This module was written for use with LDAP - so default is seeded sha ''' if salt == None: salt = getsalt() - + algo = algo.lower() if algo not in algos.keys(): raise TypeError, 'Algorithm <%s> not supported in this version.' % algo - + if algo == 'ssha': pwdhash = "{SSHA}" + base64.encodestring(sha.new(str(pwd) + salt).digest() + salt) elif algo =='sha': @@ -117,7 +117,7 @@ def mkpasswd(pwd, sambaver=3, algo='SSHA', salt=None): def checkpwd(pwd, pwdhash): ''' Check if the password matches the hash ''' - + algo = pwdhash[1:].split('}')[0] algo = algo.lower() @@ -134,5 +134,5 @@ def checkpwd(pwd, pwdhash): salt = base64.decodestring(pwdhash.split('}')[1])[20:] else: salt = None - + return mkpasswd(pwd, sambaver=sambaver, algo=algo, salt=salt) == pwdhash diff --git a/gestion/lock.py b/gestion/lock.py index 20779d99..20bd88bf 100755 --- a/gestion/lock.py +++ b/gestion/lock.py @@ -1,7 +1,7 @@ #!/usr/bin/env python # -*- coding: utf-8 -*- -""" Gestion de lock +""" Gestion de lock Copyright (C) Frédéric Pauget Licence : GPLv2 @@ -51,7 +51,7 @@ def wait_lock(lock_name, lock_comment='', d=None, retry=0.2): return d def make_lock(lock_name, lock_comment='',nowait=0, quiet=False) : - """ Création d'un lock + """ Création d'un lock si nowait=1 fait un sys.exit(254) quand un ancien lock actif est rencontré """ return @@ -76,7 +76,7 @@ def make_lock(lock_name, lock_comment='',nowait=0, quiet=False) : raise AssertionError('In critical section') else: sys.stderr.write('\tpropriétaire : inconnu\n\tpid : inconnu\n\tdémarré depuis inconnu\n') - sys.exit(254) + sys.exit(254) else: # La procédure de lock est deja en cours d'execution, on essaie un peu plus tard time.sleep(0.5) @@ -87,13 +87,13 @@ def make_lock(lock_name, lock_comment='',nowait=0, quiet=False) : if os.path.isfile(lock_file) : ### Lock existant - + # Lecture du lock fd = open(lock_file, "r") pid= fd.readline().strip() user = fd.readline().strip() fd.close() - + # Informations sur le processus lockant if os.system( "ps ax | grep -q '^%s '" % pid ) : # Le script lockant ne tourne plus @@ -103,16 +103,16 @@ def make_lock(lock_name, lock_comment='',nowait=0, quiet=False) : sys.stderr.write('Lock : %s\n' % lock_file) l=getoutput("ps ax -o pid,etime | awk '($1 == %s)'" % pid) data = [ user , pid , l.strip() ] - + # Formatate de etime s = data[-1].split('-') if len(s)==2 : txt = '%s jour(s) ' % s[0] s=s[1] - else : + else : txt = '' s=s[0] - + s = s.split(':') if len(s) == 3 : txt = '%sh%smin%ss' % tuple(s) @@ -140,7 +140,7 @@ def make_lock(lock_name, lock_comment='',nowait=0, quiet=False) : lockf(lock_fd_dl, LOCK_UN) lock_fd_dl.close() return make_lock(lock_name, lock_comment) - + ### Prise du lock lock_fd = file(lock_file,"w") try: @@ -153,7 +153,7 @@ def make_lock(lock_name, lock_comment='',nowait=0, quiet=False) : # On enleve le verrou système lockf(lock_fd_dl, LOCK_UN) lock_fd_dl.close() - + def remove_lock( lock_name ) : """ Destruction du lock """ diff --git a/gestion/mail-all.py b/gestion/mail-all.py index 293c8c91..ff164cc3 100755 --- a/gestion/mail-all.py +++ b/gestion/mail-all.py @@ -44,14 +44,14 @@ def reconf_postfix(): if limit == "yes": # Si oui, on demande à l'utilisateur si on y touche - + negatif = ["N", "n", ""] positif = ["O", "o", "Y", "y"] - + poursuivre = "x" while not (poursuivre in negatif + positif): poursuivre = raw_input("Il y a trop de destinataires, il faut réécrire la conf de postfix [o/N] ") - + if poursuivre in negatif: print "Ok, on ne touche pas au fichier..." sys.exit(0) @@ -69,7 +69,7 @@ def reconf_postfix(): sys.exit(1) reload_postfix() - + return(limit,lines) if __name__ == "__main__": @@ -121,7 +121,7 @@ par le script. except IOError: print "Impossible d'ouvrir le fichier à envoyer, merci, au revoir." sys.exit(1) - + echecs = [] s = smtplib.SMTP() s.connect('smtp.crans.org') @@ -141,14 +141,14 @@ par le script. else: # Tout va bien pass - + if echecs: print "\nIl y a eu des erreurs :" print echecs - + s.close() - # On rétablit la conf de postfix + # On rétablit la conf de postfix finally: if limit == "yes": try: diff --git a/gestion/majswitch.py b/gestion/majswitch.py index 15fba375..dbb6d251 100755 --- a/gestion/majswitch.py +++ b/gestion/majswitch.py @@ -1,7 +1,7 @@ #!/usr/bin/env python # -*- coding: utf-8 -*- -""" +""" Script de mise a jour des firmwares de switchs J.Benoist Leger @@ -52,7 +52,7 @@ if not file_tftp : print "Pas de fichier donné" sys.exit(1) -# On fait les tests uniquement sur batv-3 +# On fait les tests uniquement sur batv-3 # switchs=["batv-3.adm.crans.org"] @@ -87,7 +87,7 @@ for bestiole in switchs : ssh.sendline("no ip ssh filetransfer") ssh.sendline("tftp client") ssh.sendline("exit") - + try: ssh.expect("%s# " % host, timeout=40) except pexpect.TIMEOUT: diff --git a/gestion/numeros_disponibles.py b/gestion/numeros_disponibles.py index ded2ee57..bdc9859f 100755 --- a/gestion/numeros_disponibles.py +++ b/gestion/numeros_disponibles.py @@ -15,8 +15,8 @@ from iptools import AddrInNet repertoire = '/usr/scripts/var/numeros_disponibles/' """ - Un petit hack de rien du tout pour s'assurer qu'on n'attribue - pas ces adresses. Certains services risquent de continuer + Un petit hack de rien du tout pour s'assurer qu'on n'attribue + pas ces adresses. Certains services risquent de continuer d'essayer de se connecter a ces adresses """ ancien_vlan_adm = ['10.231.136.0/24'] diff --git a/gestion/pexpect.py b/gestion/pexpect.py index 6faf019d..ffa18112 100644 --- a/gestion/pexpect.py +++ b/gestion/pexpect.py @@ -90,7 +90,7 @@ class spawn: p = pexpect.spawn ('/usr/bin/ssh', ['user@example.com']) p = pexpect.spawn ('ls', ['-latr', '/tmp']) After this the child application will be created and - will be ready to talk to. For normal use, see expect() and + will be ready to talk to. For normal use, see expect() and send() and sendline(). If the command parameter is an integer AND a valid file descriptor @@ -116,7 +116,7 @@ class spawn: self.__child_fd_owner = None self.exitstatus = None self.pid = None - self.log_file = None + self.log_file = None self.before = None self.after = None self.match = None @@ -124,21 +124,21 @@ class spawn: self.name = '' # File-like object. self.flag_eof = 0 - # NEW -- to support buffering -- the ability to read more than one + # NEW -- to support buffering -- the ability to read more than one # byte from a TTY at a time. See setmaxread() method. self.buffer = '' self.maxread = 1 # Maximum to read at a time ### IMPLEMENT THIS FEATURE!!! # anything before maxsearchsize point is preserved, but not searched. #self.maxsearchsize = 1000 - + # If command is an int type then it must represent an open file descriptor. if type (command) == type(0): try: # Command is an int, so now check if it is a file descriptor. os.fstat(command) except OSError: raise ExceptionPexpect, 'Command is an int type, yet is not a valid file descriptor.' - self.pid = -1 + self.pid = -1 self.child_fd = command self.__child_fd_owner = 0 # Sets who is reponsible for the child_fd self.args = None @@ -273,7 +273,7 @@ class spawn: def setlog (self, fileobject): """This sets logging output to go to the given fileobject. - Set fileobject to None to stop logging. + Set fileobject to None to stop logging. Example: child = pexpect.spawn('some_command') fout = file('mylog.txt','w') @@ -300,13 +300,13 @@ class spawn: If a log file was set using setlog() then all data will also be written to the log file. - Notice that if this method is called with timeout=None + Notice that if this method is called with timeout=None then it actually may block. This is a non-blocking wrapper around os.read(). - It uses select.select() to implement a timeout. + It uses select.select() to implement a timeout. """ - + if self.child_fd == -1: raise ValueError ('I/O operation on closed file') @@ -320,7 +320,7 @@ class spawn: if not r: self.flag_eof = 1 raise EOF ('End Of File (EOF) in read(). Braindead platform.') - + r, w, e = select.select([self.child_fd], [], [], timeout) if not r: raise TIMEOUT('Timeout exceeded in read().') @@ -338,21 +338,21 @@ class spawn: if s == '': self.flag_eof = 1 raise EOF('End Of File (EOF) in read(). Empty string style platform.') - + if self.log_file != None: self.log_file.write (s) self.log_file.flush() - + return s raise ExceptionPexpect('Reached an unexpected state in read().') def read (self, size = -1): # File-like object. - """This reads at most size bytes from the file - (less if the read hits EOF before obtaining size bytes). - If the size argument is negative or omitted, - read all data until EOF is reached. - The bytes are returned as a string object. + """This reads at most size bytes from the file + (less if the read hits EOF before obtaining size bytes). + If the size argument is negative or omitted, + read all data until EOF is reached. + The bytes are returned as a string object. An empty string is returned when EOF is encountered immediately. """ if size == 0: @@ -366,16 +366,16 @@ class spawn: # I would catch any bugs early and ensure consistant behavior. # It's a little less efficient, but there is less for me to # worry about if I have to later modify read() or expect(). - cre = re.compile('.{%d}' % size, re.DOTALL) + cre = re.compile('.{%d}' % size, re.DOTALL) index = self.expect ([cre, EOF]) if index == 0: return self.after ### self.before should be ''. Should I assert this? return self.before - + def readline (self, size = -1): # File-like object. """This reads and returns one entire line. A trailing newline is kept in - the string, but may be absent when a file ends with an incomplete line. - Note: This readline() looks for a \\r\\n pair even on UNIX because this is + the string, but may be absent when a file ends with an incomplete line. + Note: This readline() looks for a \\r\\n pair even on UNIX because this is what the pseudo tty device returns. So contrary to what you may be used to you will receive a newline as \\r\\n. An empty string is returned when EOF is hit immediately. @@ -404,9 +404,9 @@ class spawn: return result def readlines (self, sizehint = -1): # File-like object. - """This reads until EOF using readline() and returns a list containing + """This reads until EOF using readline() and returns a list containing the lines thus read. The optional sizehint argument is ignored. - """ + """ lines = [] while 1: line = self.readline() @@ -422,7 +422,7 @@ class spawn: def writelines (self, sequence): # File-like object. """This calls write() for each element in the sequence. - The sequence can be any iterable object producing strings, + The sequence can be any iterable object producing strings, typically a list of strings. This does not add line separators There is no return value. """ @@ -449,8 +449,8 @@ class spawn: buffer to be sent to the waiting child program without waiting for end-of-line. If it is the first character of the line, the read() in the user program returns 0, which - signifies end-of-file. This means to work as expected - a sendeof() has to be called at the begining of a line. + signifies end-of-file. This means to work as expected + a sendeof() has to be called at the begining of a line. This method does not send a newline. It is the responsibility of the caller to ensure the eof is sent at the beginning of a line. """ @@ -487,7 +487,7 @@ class spawn: # If this class was created from an existing file descriptor then # I just check to see if the file descriptor is still valid. - if self.pid == -1 and not self.__child_fd_owner: + if self.pid == -1 and not self.__child_fd_owner: try: os.fstat(self.child_fd) return 1 @@ -535,7 +535,7 @@ class spawn: def compile_pattern_list(self, patterns): """This compiles a pattern-string or a list of pattern-strings. - Patterns must be a StringType, EOF, TIMEOUT, SRE_Pattern, or + Patterns must be a StringType, EOF, TIMEOUT, SRE_Pattern, or a list of those. This is used by expect() when calling expect_list(). @@ -569,7 +569,7 @@ class spawn: raise TypeError, 'Argument must be one of StringType, EOF, TIMEOUT, SRE_Pattern, or a list of those type. %s' % str(type(p)) return compiled_pattern_list - + def expect(self, pattern, timeout = -1): """This seeks through the stream until a pattern is matched. The pattern is overloaded and may take several types including a list. @@ -654,14 +654,14 @@ class spawn: #ED# incoming = '' incoming = self.buffer while 1: # Keep reading until exception or return. - #ED# c = self.read_nonblocking (1, timeout) + #ED# c = self.read_nonblocking (1, timeout) #ED# incoming = incoming + c # Sequence through the list of patterns and look for a match. index = -1 for str_target in pattern_list: index = index + 1 - if str_target is EOF or str_target is TIMEOUT: + if str_target is EOF or str_target is TIMEOUT: continue # The Exception patterns are handled differently. match_index = incoming.find (str_target) if match_index >= 0: @@ -670,9 +670,9 @@ class spawn: self.buffer = incoming [match_index + len(str_target):] self.match = None return index - c = self.read_nonblocking (self.maxread, timeout) + c = self.read_nonblocking (self.maxread, timeout) incoming = incoming + c - + except EOF: self.before = incoming self.after = EOF @@ -695,10 +695,10 @@ class spawn: self.match = None self.buffer = '' raise - + def expect_list(self, pattern_list, timeout = -1): """ - This takes a list of compiled regular expressions and returns + This takes a list of compiled regular expressions and returns the index into the pattern_list that matched the child's output. This is called by expect(). It is similar to the expect() method except that expect_list() is not overloaded and it does not have to @@ -711,7 +711,7 @@ class spawn: if timeout == -1: timeout = self.timeout - + try: #ED# incoming = '' incoming = self.buffer @@ -723,7 +723,7 @@ class spawn: index = -1 for cre in pattern_list: index = index + 1 - if cre is EOF or cre is TIMEOUT: + if cre is EOF or cre is TIMEOUT: continue # The patterns for PexpectExceptions are handled differently. match = cre.search(incoming) if match is not None: @@ -735,7 +735,7 @@ class spawn: # Read more data c = self.read_nonblocking (self.maxread, timeout) incoming = incoming + c - + except EOF: self.before = incoming self.after = EOF @@ -859,7 +859,7 @@ def _which (filename): # Oddly enough this was the one line that made Pexpect # incompatible with Python 1.5.2. - #pathlist = p.split (os.pathsep) + #pathlist = p.split (os.pathsep) pathlist = string.split (p, os.pathsep) for path in pathlist: @@ -907,7 +907,7 @@ def _split_command_line(command_line): if c != '\\'and state_esc: # escape mode lasts for one character. state_esc = 0 - # Handle last argument. + # Handle last argument. if arg != '': arg_list.append(arg) return arg_list @@ -936,7 +936,7 @@ def _split_command_line(command_line): # Nonblocking on Win32? # Reasearch this as a way to maybe make pipe work for Win32. # http://groups.google.com/groups?q=setraw+tty&hl=en&selm=uvgpvisvk.fsf%40roundpoint.com&rnum=7 -# +# # if istty: # if os.name=='posix': # import tty @@ -983,10 +983,10 @@ def _split_command_line(command_line): ## self.buffer = '' ## ## def read(self, n, timeout = None): -## """This does a read restricted by a timeout and -## it includes any cached data from previous calls. +## """This does a read restricted by a timeout and +## it includes any cached data from previous calls. ## This is a non-blocking wrapper around os.read. -## it uses select.select to supply a timeout. +## it uses select.select to supply a timeout. ## Note that if this is called with timeout=None (the default) ## then this actually MAY block. ## """ diff --git a/gestion/ressuscite.py b/gestion/ressuscite.py index 23f0cffd..73df8852 100755 --- a/gestion/ressuscite.py +++ b/gestion/ressuscite.py @@ -292,7 +292,7 @@ def ressuscite(adh, oldmachine): strmachine = u"Cette machine était une machine Wifi." strdef = 'Wifi' else: - strmachine = u"L'ancien type de cette machine est inconnu ..." + strmachine = u"L'ancien type de cette machine est inconnu ..." strdef = '' # Certaines fois, on peut vouloir transformer une machine Fixe en Wifi, diff --git a/gestion/restore.py b/gestion/restore.py index 697a3382..96d5cced 100755 --- a/gestion/restore.py +++ b/gestion/restore.py @@ -23,7 +23,7 @@ def load(file) : except : print "Impossible d'ouvrir le fichier demandé." sys.exit(1) - + obj = cPickle.load(fd) try : @@ -39,10 +39,10 @@ def load(file) : ### Modifs pour permettre une restauration # On supprime les infos de aid, mid ou cid obj.dn = obj.dn.split(',',1)[1] - + # On supprime les infos du init_data obj._init_data={} - + return obj if '-h' in sys.argv or '--help' in sys.argv or len(sys.argv) != 2 : @@ -61,7 +61,7 @@ def restore_adher(adh) : prompt(u'Appuyez sur ENTREE pour continuer') adh._data['mail'] = [] modif_adher(adh) - + def restore_machine(machine) : try : obj.proprio # crash si l'adhérent est encore dans la base @@ -77,7 +77,7 @@ def restore_machine(machine) : def restore_club(club) : modif_club(club) - + # Restauration ? q = prompt(u'Restaurer cette entrée ? [O/N]') if q not in 'oO' : diff --git a/gestion/user_tests.py b/gestion/user_tests.py index d3d18633..35595100 100755 --- a/gestion/user_tests.py +++ b/gestion/user_tests.py @@ -1,7 +1,7 @@ #!/usr/bin/env python # -*- coding: utf-8 -*- -""" Fonctions de tests sur l'utilisateur +""" Fonctions de tests sur l'utilisateur Copyright (C) Frédéric Pauget Licence : GPLv2 @@ -15,15 +15,15 @@ def getuser() : if not user : user = pwd.getpwuid(os.getuid())[0] return user - + def groups(login='') : """ Retourne la liste des droits qu'a l'utilisateur fourni, si aucun utilisateur n'est fourni prend l'utilisateur loggué """ - + if login == '': login = getuser() - + if login == 'root': groups = ['0'] else: @@ -37,9 +37,9 @@ def groups(login='') : groups = [] else: groups = adh.droits() - + return groups - + def isadm(login='') : """ Retourne True si l'utilisateur est dans le groupe 4 (adm) diff --git a/gestion/whos.py b/gestion/whos.py index 13f2864d..0c34d92a 100755 --- a/gestion/whos.py +++ b/gestion/whos.py @@ -9,29 +9,29 @@ d'un adhérent. Usage: %(prog)s [options] -La chaine de recherche peut être : - * soit un terme unique, dans ce cas la recherche sera effectuée sur les +La chaine de recherche peut être : + * soit un terme unique, dans ce cas la recherche sera effectuée sur les champs en bleu ci-dessous. * soit du type "champ1=valeur1&champ2!=valeur2 ...", les résultats seront alors limités aux entrées correspondantes à tous les critères. -Les champs de recherche possibles sont : +Les champs de recherche possibles sont : %(champs_rech)s Recherche sur prise possible (utiliser uniquement ce champ dans ce cas). -Les options de recherches sont : - * limitations sur l'affichage : +Les options de recherches sont : + * limitations sur l'affichage : -a ou --adherent : limitation de l'affichage aux adhérents -m ou --machine : limitation de l'affichage aux machines -c ou --club : limitation de l'affichage aux clubs -b ou --bornes : limitation de l'affichage aux bornes wifi --crans : recherche uniquement les machines du crans * options d'affichage : - -t ou --tech : affichages des infos techniques des machines + -t ou --tech : affichages des infos techniques des machines à la place des infos administratives dans les résumés. -i ou --ipsec : montre la clef ipsec des machines wifi - -l ou --limit= : limite du nombre de résultats pour utiliser + -l ou --limit= : limite du nombre de résultats pour utiliser le mode d'affichage condensé au lieu du mode détaillé (défaut %(limit_aff_details)i) -L ou --limit-historique= : limitation du nombre de lignes d'historique affichées (défaut %(limit_aff_historique)i) @@ -39,7 +39,7 @@ d'historique affichées (défaut %(limit_aff_historique)i) try: import sys,locale - + loc = locale.getdefaultlocale() if loc[1]: sys.reallysetdefaultencoding(loc[1]) @@ -64,22 +64,22 @@ aff_ipsec = 0 def aff(qqch,mtech=0) : """ Affichage de qqch. qqch peut être une liste d'instances des classes adhérent ou machine - (un seul type dans la liste) dans ce cas : + (un seul type dans la liste) dans ce cas : * si la longueur de la liste est inférieure à limit_aff_details affiche les propriétés détaillées de chaque élément. * sinon résume dans un tabeau des principales propriétés si qqch est une instance seul la traité comme une liste à une élément - Si mtech = 1 affiches les infomations techniques des machines plutot + Si mtech = 1 affiches les infomations techniques des machines plutot qu'administratives dans le tableau des propriétés - """ + """ if type(qqch) != list : qqch = [ qqch ] - + if len(qqch) > limit_aff_details : t = qqch[0].idn if t == 'aid': cprint(adhers_brief(qqch)) - elif t == 'mid': + elif t == 'mid': if mtech: cprint(list_machines(qqch)) else: @@ -98,11 +98,11 @@ def aff(qqch,mtech=0) : cprint(machine_details(c).strip()) elif t == 'cid': cprint(club_details(c).strip()) - + # affiche le nombre de résultats if len(qqch) > 1: cprint(u"Total: %d" % len(qqch)) - + def adhers_brief(adhers) : """ Formatage sous forme de tableau des infos sur la liste d'adhérent fournie : @@ -116,7 +116,7 @@ def adhers_brief(adhers) : # Copie locale triée par (nom, prenom) adhers = adhers[:] adhers.sort(lambda x, y: cmp((x.nom(), x.prenom()), (y.nom(), y.prenom()))) - + for a in adhers: ## État administratif ok = u'\x1b[1;32mo\x1b[1;0m' @@ -128,23 +128,23 @@ def adhers_brief(adhers) : else: paid = ok elif isinstance(a,Adherent) and not a.adherentPayant(): paid = coul('G', 'bleu') else: paid = nok - + # Précablage if ann_scol+1 in a.paiement() : paid = coul(paid,'f_vert') - + # Carte d'étudiant if ann_scol in a.carteEtudiant(): if 'c' in a.controle(): carte = ook else: carte = ok else : carte = nok - + machines = '' # Récupération des machines if len(adhers) <= limit_aff_machines: for machine in a.machines() : nom = machine.nom().split('.')[0] if machine.blacklist_actif() : k = 'rouge' - elif isinstance(machine, MachineWifi): k = 'cyan' + elif isinstance(machine, MachineWifi): k = 'cyan' else : k= '' if machines : machines += ', ' + coul(nom,k) else : machines = coul(nom,k) @@ -155,7 +155,7 @@ def adhers_brief(adhers) : data.append([a.id(), a.Nom(), a.chbre(), paid, carte, machines]) else: data.append([a.id(), a.Nom(), a.chbre(), paid, carte]) - + if len(adhers) <= limit_aff_machines: return u"Machines en rouge = machines avec limitation de services\n" + \ u"P : paiement année en cours, le fond vert indique le précâblage (G bleu = inscription gratuite)\n" + \ @@ -172,7 +172,7 @@ def adhers_brief(adhers) : titre = [u'aid', u'Prénom Nom', u'Chbre', u'P', u'C'], largeur = [5, '*', 5, 1, 1], alignement = ['d', 'c', 'g', 'c', 'c']) - + def machines_brief(machines) : """ Formatage sous forme d'un tableau des propriétés de la liste de machine : @@ -188,14 +188,14 @@ def machines_brief(machines) : # Copie locale triée par nom machines = machines[:] machines.sort(lambda x, y: cmp(x.nom(), y.nom())) - + for m in machines : t, bl = __bases_machines(m) - + # Propriétaire a = m.proprietaire() p = a.Nom() - + # A jour administrativement if ann_scol not in a.paiement() or ann_scol not in a.carteEtudiant(): if isinstance(a, Adherent) and not a.adherentPayant(): @@ -205,7 +205,7 @@ def machines_brief(machines) : # Données data.append([m.id() , t, m.nom().split('.')[0], p, a.chbre(), bl]) - + return u"Le propriétaire en rouge signale un problème administratif, en bleu une inscription gratuite\n" + \ tableau(data, titre = [u'mid', u'Type', u'Nom de machine', u'Propriétaire', u'Chbre', u'Limitation'], @@ -225,7 +225,7 @@ def clubs_brief(clubs) : # Copie locale triée par Nom clubs = clubs[:] clubs.sort(lambda x, y: cmp(x.Nom(), y.Nom())) - + for c in clubs : ## État administratif ok = u'\x1b[1;32mo\x1b[1;0m' @@ -236,10 +236,10 @@ def clubs_brief(clubs) : if 'p' in c.controle(): paid = ook else: paid = ok else : paid = nok - + # Précablage if ann_scol+1 in c.paiement() : paid = coul(paid,'f_vert') - + machines = '' # Récupération des machines for machine in c.machines() : @@ -248,13 +248,13 @@ def clubs_brief(clubs) : else : k= '' if machines : machines += ', ' + coul(nom,k) else : machines = coul(nom,k) - + # Responsable resp = c.responsable().Nom() # Données data.append([c.id() , c.Nom(), c.local(), paid, resp, machines]) - + return u"Machines en rouge = machines avec limitation de services\n" + \ u"P : signature charte année en cours, le fond vert indique le précâblage\n" + \ tableau(data, @@ -262,7 +262,7 @@ def clubs_brief(clubs) : largeur = [5, '*', 6, 1, 21, 15], alignement = ['d', 'c', 'g', 'c', 'c', 'c']) - + def list_machines(machines) : """ Formatage sous forme d'un tableau des propriétés de la liste de machine : @@ -281,10 +281,10 @@ def list_machines(machines) : for m in machines : t, bl = __bases_machines(m) - + # Données data.append([m.id(), t, m.nom().split('.')[0], m.ip(), m.mac(), bl]) - + return tableau(data, titre = [u'mid', u'Type', u'Nom de machine', u'Adresse IP', u'Adresse MAC', u'Limitation'], largeur = [5, 4, '*', 17, 19, 10], @@ -313,7 +313,7 @@ def list_bornes(bornes) : for b in bornes : t, bl = __bases_machines(b) if t != 'born' : continue - + # Données try : l = [x for x in b.info() if not x[0]=='<'][0] @@ -321,19 +321,19 @@ def list_bornes(bornes) : l = l[0:11] except : l = u'????' - + if borne_etat(b.nom()): etat = ok else: etat = nok - + if '-' in b.puissance() : puiss = coul(b.puissance(),'rouge') else : puiss = b.puissance() - + data.append([b.id(), b.nom().split('.')[0], b.ip(), b.mac(), etat, b.canal(), puiss, b.prise(), l]) - + return u"Can=canaux, P=puissance, E=état\n" + \ tableau(data, titre = [u'mid', u'Nom', u'Adresse IP', u'Adresse MAC', u'E', u'Can', u'P', u'Pris', u'Lieu'], @@ -349,10 +349,10 @@ def adher_details(adher) : f+= coul(u'aid=%s ' % adher.id() ,'bleu') # Nom, prenom f += coul(u'Nom : ','gras') + "%s\n" % adher.Nom() - + # Mail GL = RMH = u'' - if adher.mail().find(u'@')!=-1 : + if adher.mail().find(u'@')!=-1 : f += coul(u'Adresse mail : ','gras') if adher.mail_invalide(): f += coul(adher.mail(),'rouge') @@ -371,7 +371,7 @@ def adher_details(adher) : GL = u' (%s)'%coul(u'GreyList','gris') if adher.rewriteMailHeaders(): RMH = u' (%s)'%coul(u'réécriture en-têtes mail','gris') - + alias = u', '.join([adher.canonical_alias()] + adher.alias()) if alias: if alias[0] == u',': @@ -416,11 +416,11 @@ def adher_details(adher) : else: f += coul(u"cotisation %s/%d non réglée"% (ann_scol, ann_scol+1 ),'violet') jour = 0 - - if jour : + + if jour : f += coul(u"à jour",'vert') f += '\n' - + # Telephone tel = adher.tel() if tel != 'inconnu' : @@ -429,13 +429,13 @@ def adher_details(adher) : except : pass f += coul(u'Numéro de téléphone : ','gras') + "%s\n" % tel.ljust(12) - + # Adresse chbre = adher.chbre() if chbre == 'EXT' : # Adhérent extérieur addr = adher.adresse() - if addr[0] : + if addr[0] : f += coul(u'Adresse : ','gras') f += addr[0] + u'\n' if addr[1] != ' ' : f += u' ' + addr[1] + u'\n' @@ -446,13 +446,13 @@ def adher_details(adher) : # Chambre + prise (d'après annuaire) etat, vlans = prise_etat(adher.chbre()) f += coul(u'Chambre : ','gras') + u"%s " % chbre - f += u'(%s)' % etat + f += u'(%s)' % etat f += u'\n' # VLAN if vlans : f += coul(u'VLAN : ','gras') + u'%s' % vlans f += u'\n' - + # Études if adher.etudes(1).isdigit() : f += coul(u'Études : ','gras')+ "%s %s%s\n" % \ @@ -460,7 +460,7 @@ def adher_details(adher) : elif adher.etudes(0) : f += coul(u'Études : ','gras')+ "%s %s %s\n" % \ ( adher.etudes(0), adher.etudes(1), adher.etudes(2) ) - + # Solde solde = adher.solde() if solde : @@ -470,20 +470,20 @@ def adher_details(adher) : else : f += str(solde).replace('.',',') f += u" Euros\n" - + # Role dans l'assoce - d = adher.droits() - if d : + d = adher.droits() + if d : f += coul(u"Droits sur les serveurs : ",'gras') + ', '.join(d) if adher.droitsGeles(): f += coul(u" (droits gelés car pas cotisé cette année)",'bleu') f += u'\n' - + # Paiement if adher.paiement() : if len(adher.paiement()) == 1 : f += coul(u'Cotisation payée pour l\'année scolaire :','gras') - else : + else : f += coul(u'Cotisation payée pour les années scolaires :','gras') g = u'' for an in adher.paiement() : g += u" %i-%i" % ( an, an+1 ) @@ -508,7 +508,7 @@ def adher_details(adher) : f += _blacklist(adher) f += _info(adher) f += _hist(adher) - + # Formatage des machines aussi f += coul(u'Machine(s) : ','gras') m = adher.machines() @@ -532,34 +532,34 @@ def ipsec_ok(machine) : clients = [x.split("/")[0] for x in commands.getoutput("%snetstat -r -f encap | awk '($2 == \"0\") {print $6}'" % prefix).split("\n")] globals()['clients_ipsec'] = clients return machine.nom() in clients - + def machine_details(machine) : - """ + """ Formatage du détail des propriétés d'une machine """ f = '' f+= coul(u'mid=%s ' % machine.id(),'bleu') - + # Type de machine if isinstance(machine, MachineWifi): a = 'Machine wifi' elif isinstance(machine, BorneWifi): a = 'Borne wifi' else: a = 'Machine fixe' f += coul(a + ' : ', 'gras') - + f+= "%s\n" % machine.nom() - + # Alias ? alias = machine.alias() if alias : f += coul(u'Alias : ' ,'gras') + ', '.join(alias) f+= '\n' - + f+= coul(u'IP : ','gras') + "%s\t\t" %machine.ip() f+= coul(u'MAC : ','gras') + "%s\n" %machine.mac() - + # Propriétaire f+= coul(u'Propriétaire : ','gras') - try : + try : f += machine.proprio + coul(' (adhérent détruit)', 'jaune') a = AssociationCrans() except : @@ -567,12 +567,12 @@ def machine_details(machine) : f += "%s" % a.Nom() if a.chbre() in ['EXT', '????']: f += ' (%s = %s)' % (a.idn, a.id()) - elif a.chbre() != 'CRA': + elif a.chbre() != 'CRA': f += " (%s)" % a.chbre() else : f += coul(u'\t\tPrise : ','gras') + machine.prise() f+= '\n' - + if isinstance(machine, MachineCrans): n = machine.nombrePrises() if n >= 0: @@ -580,12 +580,12 @@ def machine_details(machine) : f += "%d\n" % n # Adhérent blacklisté ? - bl = a.blacklist_actif() + bl = a.blacklist_actif() if bl : f += coul(u'Restrictions sur adhérent : ','gras') f += coul(u', '.join(bl),'rouge') f += '\n' - + # Borne wifi if isinstance(machine, BorneWifi): f += coul(u'Hotspot : ', 'gras') @@ -602,10 +602,10 @@ def machine_details(machine) : f += coul(u'VLANs : ', 'gras') from hptools import sw_prise f += ', '.join(sw_prise(machine.prise()).vlans()) - f += '\n' + f += '\n' except: pass - + f += coul(u'Puissance : ','gras') + u"%4.d" % int(machine.puissance()) f += coul(u'\tCanaux : ', 'gras') + machine.canal() f += coul(u'\tÉtat : ', 'gras') @@ -654,11 +654,11 @@ def machine_details(machine) : if machine.nvram(): f += coul(u'NVRAM : ', 'gras') f += ', '.join(machine.nvram()) + '\n' - + if aff_ipsec and isinstance(machine, MachineWifi): f += coul(u'Clef IPsec : ','gras') + machine.ipsec() f += '\n' - + # Ports spéciaux if machine.portTCPin(): f += coul(u'Ports TCP ouvert ext->machine : ','gras') + ' '.join(machine.portTCPin()) + '\n' @@ -676,7 +676,7 @@ def machine_details(machine) : f += _blacklist(machine) f += _info(machine) f += _hist(machine) - + return f def club_details(club) : @@ -688,7 +688,7 @@ def club_details(club) : f+= coul(u'cid=%s ' % club.id() ,'bleu') # Nom f += coul(u'Nom : ','gras') + "%s\n" % club.Nom() - + # responsale f += coul(u'Responsable : ','gras') + "%s\n" % club.responsable().Nom() @@ -704,11 +704,11 @@ def club_details(club) : if not jour : f += ' et ' f += coul(u"charte %s/%d non signée"% (ann_scol, ann_scol+1 ),'violet') jour = 0 - - if jour : + + if jour : f += coul(u"à jour",'vert') f += '\n' - + # Chambre + prise etat, vlans = prise_etat(club.chbre()) f += coul(u'Local : ','gras') + "%s " % club.local() @@ -718,7 +718,7 @@ def club_details(club) : if vlans : f += coul(u'VLAN : ','gras') + u'%s' % vlans f += u'\n' - + # Paiement if club.paiement() : f += coul(u'Charte signée pour les années scolaires :','gras') @@ -733,7 +733,7 @@ def club_details(club) : if login : f += coul(u'Login : ','gras') + login alias = club.alias() - if alias : + if alias : f += coul(u'\tAlias : ','gras') + ', '.join(alias) f+= u'\n' @@ -781,14 +781,14 @@ def _blacklist(clas): dates = u'du %s au ' % dates dates += strftime('%d/%m/%Y %H:%M', localtime(int(event[1]))) f += u"%s\n\t " % coul(u'%s : %s [%s]' % (dates, event[2], event[3]), c) - + f = f[:-6] # supression des espaces superflus if f: return coul(u'Blackliste : ', 'gras') + f else: return '' - + def _info(clas) : """ Formatage des remarques de la classe fournie """ f= u'' @@ -812,7 +812,7 @@ def _hist(clas) : a = h[i] # Produit une erreur si i trop grand if i !=0 : f += ' ' try: - # on force l'encodage ici sinon il est fait au moment de l'impression a + # on force l'encodage ici sinon il est fait au moment de l'impression a # l'ecran et il empeche l'affichage de toutes les infos f += u'%s\n' % a.encode("iso-8859-15").decode("iso-8859-15") except Exception, e: @@ -826,25 +826,25 @@ def _hist(clas) : if h[i+1] : f += ' [...]\n' except : None - + return f def __bases_machines(m) : """ Retourne [ type de la machines, blacklist ] """ - #Type + #Type if isinstance(m, MachineWifi): t = 'wifi' elif isinstance(m, BorneWifi): t = 'born' else : t='fixe' - + # Déconnectée ? b = m.blacklist_actif() - if not b : + if not b : bl = '-' elif len(b) == 1 : bl = coul(b[0],'rouge') else : bl = coul(u'cf détails','rouge') - + return t , bl def borne_etat(borne) : @@ -937,7 +937,7 @@ def prise_etat(chbre) : count += 1 elif not prise.is_enable() : f+= u', ' + coul(u'prise désactivée','rouge') - else : + else : f+= u', activée, lien non détecté' except ConversationError, r: # Switch non manageable ou down @@ -975,12 +975,12 @@ def __usage() : for c in base.auto_search_champs.values(): for champ in c: if champ not in champs: - champs.append(champ) + champs.append(champ) for champ in champs: coul_champ = coul(champ, "bleu") if accu == "": accu = coul_champ - longueur = len(champ) + longueur = len(champ) elif longueur + 2 + len(champ) < 80: longueur += 2 + len(champ) accu += ", " + coul_champ @@ -994,7 +994,7 @@ def __usage() : for c in base.non_auto_search_champs.values(): for champ in c: if champ not in champs: - champs.append(champ) + champs.append(champ) for champ in champs: if longueur + 2 + len(champ) < 80: longueur += 2 + len(champ) @@ -1006,7 +1006,7 @@ def __usage() : # Dernière ligne liste.append(accu) - + cprint(__doc__ % { 'prog': sys.argv[0].split('/')[-1].split('.')[0], 'champs_rech': '\n'.join(liste), 'limit_aff_details': limit_aff_details, @@ -1018,7 +1018,7 @@ def __recherche() : Recherche et affichage des résultats à partir des options founies (sys.argv) """ global aff_ipsec, limit_aff_details, limit_aff_historique, debug - + # Récupération des options if len(sys.argv) == 1 : # Pas d'option fournie @@ -1028,8 +1028,8 @@ def __recherche() : options, arg = getopt.getopt(sys.argv[1:], 'hamctbil:L:', [ 'debug', 'help', 'adherent', 'machine', 'club' , 'tech', 'bornes', 'limit=', 'limit-historique=', 'ipsec', 'crans' ]) except getopt.error, msg : __usage_brief(unicode(msg)) - - + + # Traitement des options only_adh=0 only_mac=0 @@ -1037,7 +1037,7 @@ def __recherche() : only_bornes=0 only_crans=0 mtech = 0 - + for opt, val in options : if opt == '-h' or opt=='--help' : __usage() @@ -1075,7 +1075,7 @@ def __recherche() : # Recherche initiale sans critère arg = [ 'canal=*&host=*.crans.org'] elif arg[0].find('=')!=-1 : - # Recherche avec critères + # Recherche avec critères arg += [ '&canal=*' ] elif opt in [ '-t', '--tech' ] : # Format affichage des machines @@ -1083,7 +1083,7 @@ def __recherche() : elif opt in [ '-i', '--ipsec' ] : # Affichage des clefs ipsec aff_ipsec = 1 - + if only_adh + only_mac + only_club + only_bornes > 1 : __usage_brief(u'Options utilisées incompatibles') @@ -1110,7 +1110,7 @@ def __recherche() : #cprint(u"Recherche sur chambre %s" % chbre) arg = u'chbre=%s' % chbre # sinon on ne fait rien et on recherche sur le champ prise - + try: if only_crans : res = { 'machine' : AssociationCrans().machines() , 'adherent' : [] , 'club' : [] } @@ -1121,7 +1121,7 @@ def __recherche() : res = base.search(arg) except ValueError, c : __usage_brief(c.args[0]) - + # Traitement du résultat if not res['adherent'] and not res['machine'] and not res['club']: # Pas de résultat dans la base @@ -1160,14 +1160,14 @@ def __recherche() : elif res['club'] : cprint(u'Aucun résultat à afficher') sys.exit(4) - elif only_mac : + elif only_mac : if res['machine'] : aff(res['machine'],mtech) else : to_aff = [] for a in res['adherent'] + res['club'] : to_aff += a.machines() aff(to_aff) - elif only_club : + elif only_club : if res['club'] : aff(res['club']) elif res['machine'] : to_aff=[] @@ -1196,15 +1196,15 @@ def __recherche() : if res['club']: cprint(u"Résultats trouvés parmi les clubs :", 'cyan') aff(res['club']) - + if __name__ == '__main__' : global debug debug = 0 - + import sys, getopt - + base = crans_ldap() - + try : __recherche() except KeyboardInterrupt : @@ -1215,7 +1215,7 @@ if __name__ == '__main__' : sys.exit(c) except : cprint(u"""Une erreur fatale s'est produite durant l'exécution. -Pour l'amélioration de ce programme merci de prévenir nounou en spécifiant la +Pour l'amélioration de ce programme merci de prévenir nounou en spécifiant la marche à suivre pour reproduire cette erreur.""") if debug : cprint('-'*40)