Created
March 25, 2012 18:20
-
-
Save rxdazn/2198830 to your computer and use it in GitHub Desktop.
moulinette norme epitech
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/python | |
# | |
# Made by [email protected] | |
# Version: 1.2.1 | |
# | |
''' | |
An Epitech norme checker | |
Usage: python norme.py <files to scan> [-nocheat] [-verbose] [-score] [-libc] | |
-verbose: affiche les messages impossible d\'ouvrir | |
-nocheat: desactive la detection de la triche | |
-score: affiche le nombre de faute de norme | |
-libc: active la verification des fonctions de la libc | |
-malloc: desactive le controle du malloc | |
-printline: affiche la ligne provoquant une erreur | |
-return: active verifier le retour des fonctions (return ;) | |
-comment: ne pas verifier les commentaire | |
Non geree: | |
- Indentation | |
- +<escape> | |
- verification de la presence de gl_ | |
_ macro multiligne | |
_ initialisation de variable a la declaration | |
_ separation initialisation de variable et code | |
A modifier: | |
Fonction checkant la protection contre la double inclusion des .h . | |
Appel ligne 163. | |
Bug: | |
Il est arrivee que le checker ne trouve aucune faute alors qu\'il en existe, si | |
ce bug vous arrive maillez moi. | |
''' | |
import sys,re,os,pwd | |
version = 0.5 | |
class norme: | |
def __init__(self): | |
self.user = [] | |
self.verbose = 0 | |
self.cheat = 1 | |
self.comment = 1 | |
self.score = 1 | |
self.note = 0 | |
self.libc = 1 | |
self.printline = 0 | |
self.creturn = 1 | |
def new_file(self): | |
self.nb_line = 1 | |
self.nb_return = 0 | |
self.nb_funcline = 0 | |
self.nb_func = 0 | |
self.sys_include = 0 | |
self.double_inclusion = 0 | |
self.is_func = 0 | |
self.typedef = 0 | |
if self.verbose == 1: | |
print "Scan",self.file | |
def check_header(self): | |
if (self.nb_line == 1): | |
if (self.line[:2] != '/*'): | |
self.print_error('header incorrect') | |
self.note += 20 | |
elif (self.nb_line == 9): | |
if (self.line[:2] != '*/'): | |
self.print_error('header incorrect') | |
elif self.nb_line == 4 or self.nb_line == 7 or self.nb_line == 8: | |
if self.cheat: | |
p = re.compile('([\w-]* [\w-]*)$') | |
test = re.search(p, self.line) | |
if test: | |
if not test.group(1) in self.user: | |
self.print_error('login '+ test.group(1) +' incorrect') | |
print "Note: -42" | |
sys.exit() | |
elif (self.nb_line == 5): | |
if self.cheat: | |
p = re.compile('<(.*)@') | |
test = re.search(p, self.line) | |
if test: | |
if not test.group(1) in self.user: | |
self.print_error('login '+ test.group(1) +' incorrect') | |
print "Note: -42" | |
sys.exit() | |
else: | |
if (self.line[:2] != '**'): | |
self.print_error('header incorrect') | |
def check_virgule(self): | |
if is_commented(self.line) == False: | |
n = 0 | |
quote = 0 | |
while self.line[n] != '\n': | |
if self.line[n] == '\'' or self.line[n] == '"' and self.line[n - 1] != '\\': | |
if quote: | |
quote = 0 | |
else: | |
quote = 1 | |
if (self.line[n] == ';' or self.line[n] == ',') and quote == 0: | |
if self.line[n + 1] != ' ' and self.line[n + 1] != '\n': | |
self.note += 1 | |
self.print_error('point-virgule ou virgule mal place') | |
n = n + 1 | |
def check_nbchar(self): | |
line = self.line.replace('\t', ' ') | |
if (line[80:]): | |
self.note += 1 | |
self.print_error('chaine de plus de 80 caracteres') | |
def check_return(self): | |
if (self.line[:1] == '\n'): | |
if (self.nb_return == 1): | |
self.note += 1 | |
self.print_error('double retour a la ligne') | |
else: | |
self.nb_return = 1 | |
else: | |
self.nb_return = 0 | |
def check_nbline(self): | |
if self.file[-2:] == ".c": | |
if self.line[:1] == '}': | |
self.is_func = 0 | |
self.nb_funcline = 0 | |
if self.line[:1] == '{' and self.typedef == 0: | |
self.is_func = 1 | |
self.nb_funcline = 0 | |
self.nb_func = self.nb_func + 1 | |
if self.nb_func == 6: | |
self.note += 1 | |
self.print_error('plus de 5 fonctions dans le fichier') | |
else: | |
if self.nb_func >= 1 and self.is_func: | |
self.nb_funcline = self.nb_funcline + 1 | |
if self.nb_funcline >= 26: | |
self.note += 1 | |
self.print_error('fonction de plus de 25 lignes') | |
def check_cfunc(self): | |
if is_commented(self.line) == False: | |
p = re.compile('[ \t](if|else|return|while|for)(\()') | |
test = re.search(p, self.line) | |
if test: | |
self.note += 1 | |
self.print_error('pas d\'espace apres mot clef') | |
def check_arg(self): | |
if self.line[-2:] == ")\n" and self.line[:1] != '\t' and self.line[:1] != ' ': | |
p = re.compile('(.*),(.*),(.*),(.*),(.*)\)$') | |
test = re.search(p, self.line) | |
if test: | |
self.note += 1 | |
self.print_error('plus de 4 arguments passes en parametre') | |
def check_sys_include(self): | |
if self.line[:1] == "#" and self.line[-2:] == "\"\n": | |
self.sys_include = 1 | |
else: | |
if self.line[:1] == "#" and self.line[-2:] == ">\n" and self.sys_include == 1: | |
self.note += 1 | |
self.print_error('Header systeme mal placee') | |
def check_comment(self): | |
if self.is_func and self.comment: | |
p = re.compile('(//|/\*)') | |
test = re.search(p, self.line) | |
if test: | |
self.note += 1 | |
self.print_error('Commentaires dans le code') | |
def check_malloc(self): | |
p = re.compile('[^x](malloc)(\()') | |
test = re.search(p, self.line) | |
if test and (self.file != "xmalloc.c"): | |
self.print_error('Malloc non verifiee') | |
self.note += 1 | |
def check_operateur(self, op): | |
n = 0 | |
quote = 0 | |
while self.line[n] != '\n': | |
if self.line[n] == '\'' or self.line[n] == '"' and self.line[n - 1] != '\\': | |
if quote: | |
quote = 0 | |
else: | |
quote = 1 | |
if (self.line[n] == op) and quote == 0: | |
if self.line[n + 1] != ' ' and self.line[n + 1] != ';' and self.line[n + 1] != '=': | |
if self.line[n - 1] != op and self.line[n + 1] != op: | |
msg = 'Operateur %c mal place' % op | |
self.print_error(msg) | |
self.note += 1 | |
n = n + 1 | |
def check_typedef(self): | |
if self.line[:7] == "typedef": | |
self.typedef = 1 | |
else: | |
self.typedef = 0 | |
def check_regex(self, regex, msg): | |
p = re.compile(regex) | |
test = re.search(p, self.line) | |
if test: | |
self.note += 1 | |
self.print_error(msg) | |
def check_line(self): | |
if is_commented(self.line) == False: | |
self.check_nbline() # DOIT TOUJORS ETRE EN PREMIER | |
self.check_sys_include() | |
self.check_virgule() | |
self.check_regex('[ \t]$', 'Espace en fin de ligne') | |
if self.creturn == 0: | |
self.check_regex('return( \(\)| ;|;)', 'Mauvais format de return') | |
if self.libc == 0: | |
self.check_regex('[^_](printf|atof|atoi|atol|strcmp|strlen|strcat|strncat|strncmp|strcpy|strncpy|fprintf|strstr|strtoc|sprintf|asprintf|perror|strtod|strtol|strtoul)(\()', \ | |
'Fonction de la lib C') | |
self.check_nbchar() | |
self.check_cfunc() | |
self.check_arg() | |
self.check_comment() | |
self.check_return() | |
self.check_operateur('+') | |
self.check_operateur('|') | |
self.check_typedef() #DOIT TOUJOURS ETRE EN DERNIER | |
def print_error(self, msg): | |
print "Erreur dans",self.file,"a la ligne",self.nb_line,":",msg | |
if self.printline: | |
print self.line | |
def cant_open(self, file): | |
if (self.verbose or file == sys.argv[1]): | |
print "Impossible d'ouvrir",file | |
def scan_files(self, files): | |
for file_name in files: | |
self.file = file_name | |
self.new_file() | |
try: | |
fd = open(file_name, 'r') | |
except IOError: | |
self.cant_open(file) | |
else: | |
for self.line in fd.readlines(): | |
if self.nb_line <= 9: | |
self.check_header() | |
else: | |
self.check_line() | |
self.nb_line = self.nb_line + 1 | |
fd.close() | |
def scandir(self, thedir): | |
try: | |
dir = os.listdir(thedir) | |
except: | |
self.cant_open(thedir) | |
else: | |
check_makefile(thedir) | |
for file in dir: | |
if (os.path.isdir(thedir + file)): | |
self.scandir(thedir + "/" + file + "/") | |
if file[-2:] == '.c' or file[-2:] == '.h': | |
self.file = file | |
self.new_file() | |
file = thedir + file | |
try: | |
fd = open(file, 'r') | |
except IOError: | |
self.cant_open(file) | |
else: | |
for self.line in fd.readlines(): | |
if self.nb_line <= 9: | |
self.check_header() | |
else: | |
self.check_line() | |
self.nb_line = self.nb_line + 1 | |
fd.close() | |
# Trouve le login dans la variable $MOULINETTE_USER et va chercher | |
# le nom complet dans /afs/epitech.net/site/etc/passwd | |
# Si pas de variable $MOULINETTE_USER va chercher $USER | |
def get_user(self): | |
user_list = [] | |
user = os.getenv('MOULINETTE_USER') | |
if user: | |
user_list = user.split(';') | |
if not user: | |
user_list.append(os.getenv('USER')) | |
for user_name in user_list: | |
f = open("/afs/epitech.net/site/etc/passwd", 'r') | |
while 1: | |
line = f.readline() | |
if line: | |
line = line.split(':') | |
if user_name == line[0]: | |
break | |
if not line: | |
f.close() | |
return | |
f.close() | |
self.user.append(user_name) | |
self.user.append(line[4]) | |
def check_makefile(thedir): | |
file = thedir + "Makefile" | |
if os.path.isfile(file): | |
try: | |
fd = open(file, 'r') | |
except IOError: | |
print "Impossible d'ouvrir le Makefile" | |
else: | |
buffer = fd.read() | |
p = re.compile('(-g|-pg|-lefence)') | |
test = re.search(p, buffer) | |
if test: | |
print "Options de debug dans le Makefile" | |
p = re.compile('(-Wall)') | |
test = re.search(p, buffer) | |
if not test: | |
print "-Wall n'est pas dans le Makefile" | |
p = re.compile('(-pedantic)') | |
test = re.search(p, buffer) | |
if not test: | |
print "-pedantic n'est pas dans le Makefile" | |
if buffer[:2] != "##": | |
print "Header du Makefile invalide" | |
fd.close() | |
def get_files(argv): | |
li = [] | |
pattern = re.compile('[.]c$|[.]h$') | |
for arg in sys.argv: | |
test = re.search(pattern, arg) | |
if test: | |
li.append(arg) | |
return li | |
def is_commented(line): | |
if ((line[0] == '/' or line[0] == '*') and line[1] == '*'): | |
return True | |
return False | |
def check_version(): | |
file = "/afs/epitech.net/users/prof/astek/public/norme_version" | |
if os.path.isfile(file): | |
try: | |
fd = open(file, 'r') | |
except IOError: | |
print "Impossible de verifier la version du script" | |
else: | |
buffer = fd.read() | |
if (version != float(buffer)): | |
print "Mauvaise version du script, verifiez sur le public astek" | |
def help(): | |
print "Aide" | |
print "Moulinette version " + str(version) | |
print "Usage: norme.py <files_to_scan>" | |
print "-verbose: affiche les messages impossible d'ouvrir" | |
print "-nocheat: desactive la detection de la triche" | |
print "-score: affiche le nombre de faute de norme" | |
print "-libc: active la verification des fonctions de la libc" | |
print "-printline: affiche la ligne provoquant une erreur" | |
print "-return: active verifier le retour des fonctions (return ;)" | |
print "-comment: ne pas verifier les commentaires" | |
sys.exit() | |
def main(): | |
if '-help' in sys.argv[1:]: | |
help() | |
check_version() | |
if len(sys.argv) == 1: | |
print "Usage: norme.py <files_to_scan>" | |
sys.exit() | |
moulin = norme() | |
files = get_files(sys.argv) | |
if '-verbose' in sys.argv[1:]: | |
moulin.verbose = 1 | |
if '-comment' in sys.argv[1:]: | |
moulin.comment = 0 | |
if '-nocheat' in sys.argv[1:]: | |
moulin.cheat = 0 | |
if '-score' in sys.argv[1:]: | |
moulin.score = 1 | |
if '-libc' in sys.argv[1:]: | |
moulin.libc = 0 | |
if '-printline' in sys.argv[1:]: | |
moulin.printline = 1 | |
if '-return' in sys.argv[1:]: | |
moulin.creturn = 0 | |
if moulin.cheat == 1: | |
moulin.get_user() | |
try: | |
moulin.scan_files(files) | |
except NameError: | |
print "Usage: norme.py <files_to_scan>" | |
if moulin.score: | |
print "Note:",-moulin.note, | |
if __name__ == "__main__": | |
main() |
Pour les gens intéressé j'ai mis en ligne sur mon github la version originel:
https://github.com/noplay/norme.py
duponc_j
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Attention ! Ce script récupère le fichier passwd (contenant vos mots de passe) sur l'ancien dump !
Suffit de regarger la fonction "get_user" qui fait un open sur "/afs/epitech.net/site/etc/passwd"