def init_archivage(politique, taille_src): """ Preparation du repertoire d'archivage avant transfert. @param politique: objet Politique employe pour le transfert @param taille_src: taille totale des fichiers source a nettoyer, en octets """ # si le repertoire d'archivage n'existe pas, on le cree: chem_arc = path(politique.parametres['rep_archives'].valeur) try: os.makedirs(chem_arc) except: pass # calcul de la taille actuelle du répertoire archivage taille_arc = 0 for f in chem_arc.walkfiles(): taille_arc += f.size # test si la taille des fichiers source est supérieure à celle du rép d'archivage # si c'est le cas, on génère une exception if taille_src > politique.parametres['taille_archives'].valeur: msg = _( u"La taille des fichiers source est superieure a la taille du repertoire d'archivage." ) Journal.error(msg) raise RuntimeError, msg # boucle pour effacer les sous-rép les plus anciens dans le cas où il n'y a pas assez # d'espace disque dans le rép archivage pour copier les fichiers source while politique.parametres[ 'taille_archives'].valeur < taille_arc + taille_src: date_archive = 0 taille_rep_archive = 0 # boucle pour déterminer quel est le sous-rép archive le plus ancien for rep in chem_arc.dirs(): if date_archive == 0: # on récupère la date du 1er sous-rép archive lu date_archive = os.path.getmtime(rep) rep_archive = rep # si la date du sous-rép archive lu est inférieure à date_archive, # ce sous-rép devient le plus ancien elif date_archive > os.path.getmtime(rep): date_archive = os.path.getmtime(rep) rep_archive = rep if os.path.exists(rep_archive): # calcul de la taille du sous-rép archive le plus ancien for rep in rep_archive.walkfiles(): taille_rep_archive += rep.size # on met à jour la taille du rép temp principal taille_arc = taille_arc - taille_rep_archive # on efface le sous-rép temp le plus ancien rep_archive.rmtree() else: # s'il n'y a plus de sous-rép archive à effacer, on génère une exception msg = _( u"repertoire d'archivage deja vide => taille source trop grande" ) Journal.error(msg) raise RuntimeError, msg
def antivirus_fpcmd (self, politique): """ Analyse le fichier grâce à l'antivirus F-Prot 3 (fpcmd). @param politique: politique de filtrage à appliquer, objet L{Politique.Politique} ou None. Si None, la politique par défaut sera appliquée. @type politique: objet L{Politique.Politique} @return: le résultat de l'analyse, ou None si le fichier est sain. @rtype : objet L{Resultat<Resultat.Resultat>} ou None """ if sys.platform == "win32": # on récupère le chemin de fpcmd: chemin_fprot = politique.parametres['fpcmd_executable'].valeur Journal.info2(_(u"Lancement de fpcmd pour l'analyse antivirus...")) args_fprot = [chemin_fprot, '-nomem', '-noboot', '-nosub', '-silent', '-old', '-collect', str_lat1(self.copie_temp())] # A VOIR: l'option -type laisse F-Prot décider si un type de fichier doit # être scanné, alors que -collect force F-Prot à tout scanner # (risque de faux-positifs) # On lance F-Prot avec Popen_timer pour masquer son affichage # et limiter le temps d'exécution: resultat_fprot = Popen_timer(args_fprot) # codes retournés par F-Prot 3: # 0 - Normal exit - nothing found # 1 - Abnormal termination - unrecoverable error. This can mean any of # the following: # Internal error in the program. # DOS version prior to 3.0 was used. # ENGLISH.TX0, SIGN.DEF or MACRO.DEF corrupted or not present. # 2 - Selftest failed - program has been modified. # 3 - A Boot/File virus infection found. # 4 - Virus found in memory. # 5 - Program terminated with ^C or ESC. # 6 - A virus was removed. This code is only meaningful if # the program is used to scan just a single file. # 7 - Insufficient memory to run the program. # 8 - At least one suspicious file was found, but no infections. if resultat_fprot == 0: Journal.info2(u"fpcmd: "+_(u"Pas de virus détecté.")) resultat = None elif resultat_fprot in [3, 4, 6, 8]: resultat = Resultat.Resultat(Resultat.REFUSE, u"fpcmd: "+_(u"Virus détecté ou fichier suspect"), self) elif resultat_fprot == EXIT_KILL_PTIMER: resultat = Resultat.Resultat(Resultat.ERREUR_ANALYSE, u"fpcmd: "+_(u"Temps dépassé lors de la vérification antivirus"), self) else: resultat = Resultat.Resultat(Resultat.ERREUR_ANALYSE, u"fpcmd: "+_(u"Erreur lors de la vérification antivirus"), self) else: # pour l'instant seul F-Prot sous Windows est supporté: raise NotImplementedError, \ u"fpcmd: "+_(u"Antivirus non supporte ou implemente pour ce systeme.") return resultat
def test_journal_init(self): """ Verify init journal is correct. """ journal = Journal() self.assertEqual(journal.get_journal_amount(), 0.0000)
def newTempDir (suffix="", prefix=tempfile.template): """ creates a new temporary directory using tempfilemgr.newTempDir returns a str: absolute pathname of the new directory """ dirname = tempfilemgr.newTempDir(suffix=suffix, prefix=prefix, dir=getTempBase()) Journal.debug('new temp dir: %s' % dirname) return dirname
def rejeter (self): """lorsqu'un fichier doit être rejeté, supprime la copie temporaire du fichier si elle existe.""" try: if self._copie_temp != None and self._copie_temp.exists(): self._copie_temp.remove() except: #TODO: mieux gerer exception ? Journal.exception(_(u'Impossible de supprimer un fichier temporaire: %s') % self._copie_temp)
def newTempFile (suffix="", prefix=tempfile.template, text=False): """ creates a new temporary file using tempfilemgr.newTempFile, in the directory specified in the policy. returns a tuple: (file object, file name) """ f, fname = tempfilemgr.newTempFile(suffix=suffix, prefix=prefix, dir=getTempBase(), text=text) Journal.debug('new temp file: %s' % fname) return f, fname
def debug(texte): """ pour afficher un texte de débogage si MODE_DEBUG = True @param texte: le texte à afficher @type texte: str """ if MODE_DEBUG: Journal.debug(texte)
def init_archivage(politique, taille_src): """ Preparation du repertoire d'archivage avant transfert. @param politique: objet Politique employe pour le transfert @param taille_src: taille totale des fichiers source a nettoyer, en octets """ # si le repertoire d'archivage n'existe pas, on le cree: chem_arc = path(politique.parametres['rep_archives'].valeur) try: os.makedirs(chem_arc) except: pass # calcul de la taille actuelle du répertoire archivage taille_arc = 0 for f in chem_arc.walkfiles(): taille_arc += f.size # test si la taille des fichiers source est supérieure à celle du rép d'archivage # si c'est le cas, on génère une exception if taille_src > politique.parametres['taille_archives'].valeur: msg = _(u"La taille des fichiers source est superieure a la taille du repertoire d'archivage.") Journal.error(msg) raise RuntimeError, msg # boucle pour effacer les sous-rép les plus anciens dans le cas où il n'y a pas assez # d'espace disque dans le rép archivage pour copier les fichiers source while politique.parametres['taille_archives'].valeur < taille_arc + taille_src: date_archive = 0 taille_rep_archive = 0 # boucle pour déterminer quel est le sous-rép archive le plus ancien for rep in chem_arc.dirs(): if date_archive == 0: # on récupère la date du 1er sous-rép archive lu date_archive = os.path.getmtime(rep) rep_archive = rep # si la date du sous-rép archive lu est inférieure à date_archive, # ce sous-rép devient le plus ancien elif date_archive > os.path.getmtime(rep): date_archive = os.path.getmtime(rep) rep_archive = rep if os.path.exists(rep_archive): # calcul de la taille du sous-rép archive le plus ancien for rep in rep_archive.walkfiles(): taille_rep_archive += rep.size # on met à jour la taille du rép temp principal taille_arc = taille_arc - taille_rep_archive # on efface le sous-rép temp le plus ancien rep_archive.rmtree() else: # s'il n'y a plus de sous-rép archive à effacer, on génère une exception msg = _(u"repertoire d'archivage deja vide => taille source trop grande") Journal.error(msg) raise RuntimeError, msg
def rejeter(self): """lorsqu'un fichier doit être rejeté, supprime la copie temporaire du fichier si elle existe.""" try: if self._copie_temp != None and self._copie_temp.exists(): self._copie_temp.remove() except: #TODO: mieux gerer exception ? Journal.exception( _(u'Impossible de supprimer un fichier temporaire: %s') % self._copie_temp)
def test_journal_acount_numbers(self): """ Verify number of acounts in journals. """ journal = Journal() for index in xrange(1, 20): acount = Acount('luz_%s' % index) journal.add_acount(acount) self.assertEqual(journal.get_number_acounts(), index)
def __init__(self, nom_source, nom_destination, rep_relatif_source, fichier=None, politique=None): """ Constructeur de la classe abstraite Conteneur. @param nom_source: nom de fichier/répertoire du conteneur source. (chemin relatif par rapport au conteneur) @type nom_source : str @param nom_destination: nom de fichier/répertoire du conteneur nettoyé, or None/'' for scan-only mode. @type nom_destination : str @param fichier: objet Fichier du conteneur, ou bien None si c'est le premier répertoire. @type fichier: objet L{Fichier.Fichier} ou None @param politique: objet Politique contenant les parametres. @type fichier: objet L{Politique.Politique} ou None """ self.nom_src = nom_source self.nom_dest = nom_destination # may be None/'' for scan-only mode self.chem_src = path(nom_source) self.chem_dest = path(nom_destination) self.fichier = fichier self.liste_fichiers = [] self.rep_relatif_source = rep_relatif_source #TODO: test a supprimer quand tous les appels sont corriges: assert politique != None, 'Conteneur.__init__ requires politique' self.politique = politique self.rep_temp = getTempBase() self.rep_archive = politique.parametres['rep_archives'].valeur # on construit le chemin complet: if fichier == None: # on est dans le 1er répertoire, le chemin complet est vide: self.chemin_complet = path("") # si on met le nom du fichier, on a vraiment le chemin complet, # mais ça donne un affichage très lourd dans les rapports #self.chemin_complet = self.chem_src else: # sinon on récupère celui du fichier associé au conteneur: self.chemin_complet = fichier.chemin_complet Journal.debug(u"chemin_complet = %s" % self.chemin_complet) self.creer_rep_temp() Journal.debug(u"Répertoire temporaire = %s" % self.rep_temp_complet) self.type = _(u"Conteneur generique")
def run_event_loop(): cmd = "" print("Welcome to your awesome journal") journal_name = input('Load:') journal_data = Journal.load(journal_name) while (cmd != 'x'): cmd = input('[L]ist entries, [A]dd an entry, E[X]it: ') if (cmd.lower().strip() == 'l'): list_entries(journal_data) elif (cmd.lower().strip() == 'a'): Journal.add_entry(journal_data) elif (cmd.lower().strip() == 'x'): print('goodbye') Journal.save(journal_name, journal_data) exit() else: print('Error enter a valid input')
def getTempBase (): """ returns the base directory for temporary files and dirs (absolute path). If not defined by the policy, or defined as "auto", it will be a subdirectory named "xf" in the default system temp dir. Else it will be the one defined in the policy. The directory is created if it does not exist. """ try: dir=politique.parametres['rep_temp'].valeur except: dir='auto' if dir == 'auto': dir = os.path.join(tempfile.gettempdir(), 'xf') dir = os.path.abspath(dir) Journal.debug('temp base directory: %s' % dir) # create the dir if it doesn't exist: if not os.path.exists(dir): Journal.debug('creating dir %s' % dir) os.makedirs(dir) return dir
def setUp(self) -> None: # setting up testing set of instances self.item1 = Book("Tropic of Cancer", "Henry Miller", "Autobiographical novel", 1934, 318) self.item2 = Book("1984", "George Orwell", "Novel", 1949, 328) self.item3 = Book("Junkie", "William S. Burroughs", "Autobiographical novel", 1953, 166) self.item4 = Book("On the Road", "Jack Kerouac", "Autobiographical novel", 1957, 320) self.item5 = Comics("Deadpool", "Marvel", "Superhero", 2019, 25) self.item6 = Journal("ATT", "AT", "Celebrity", "10.20.2021", 14) self.item7 = Newspaper("NYT", "NY", "Weekly", "04.10.2020", 20) self.item8 = Magazine("Rolling Stone", "Wenner Media LLC", "Musical", "04.10.2020", 18) result = [self.item1, self.item2, self.item3, self.item4, self.item5, self.item6, self.item7] self.manager = BookstoreManager(result)
def nettoyer(self, politique): """ Nettoie le Conteneur et tous les fichiers qu'il contient. @param politique: politique de filtrage à appliquer, objet L{Politique.Politique} ou None. Si None, la politique par défaut sera appliquée. @type politique: objet L{Politique.Politique} """ import Conteneur_Zip # import necessaire plus bas, ne peut etre fait # a l'init du module car reference croisee... liste_resultats = [] # liste des objets Resultat de chaque fichier # on commence par lister les fichiers self.lister_fichiers() for fichier in self.liste_fichiers: Journal.info2(_(u"FICHIER: %s") % fichier.chemin_complet) # test de l'interruption de transfert par l'utilisateur if commun.continuer_transfert == False: break fichier.nettoyer(politique) # on incrémente le compteur d'avancement sauf pour les conteneurs zip #if self.type != "Archive Zip" : # test incorrect si OS non fr if isinstance(self, Conteneur_Zip.Conteneur_Zip): commun.compteur_avancement += 1 # on ajoute le résultat à la liste des résultats liste_resultats.append(fichier.resultat_fichier) #if fichier.rejet: #if fichier.resultat_fichier.code_resultat == Resultat.REFUSE: if fichier.resultat_fichier.est_refuse(): # on supprime la copie temporaire du fichier si elle existe fichier.rejeter() # maintenant tous les fichiers ont été nettoyés, on ferme le # conteneur: self.fermer() # on efface les éventuels répertoires vides de conteneur if self.rep_relatif_source != "": effacer_rep_vide(self.rep_temp_complet) # in clean mode, rebuild the container and copy it to destination: Journal.debug('clean_mode=%s' % commun.clean_mode) if commun.clean_mode: # on reconstruit le conteneur à partir des fichiers temporaires nettoyés Journal.debug( 'Rebuilding the container and copying to destination') self.reconstruire() else: # scan only mode, no rebuilding/copying Journal.debug('Scan only mode, no need to rebuild the container.') # then delete the temp dir used to scan/clean the container: self.delete_tempdir() return liste_resultats
def test_journal_add_item_acount(self): """ Verify add item acount in journal is correct. """ journal = Journal() journal.add_acount('Jorge') journal.add_item_acount('Jorge', 'Capitan del espacio', 10.0000) self.assertEqual(journal.get_journal_amount(), 10.0000)
def nettoyer(self, politique): """ Nettoie le Conteneur et tous les fichiers qu'il contient. @param politique: politique de filtrage à appliquer, objet L{Politique.Politique} ou None. Si None, la politique par défaut sera appliquée. @type politique: objet L{Politique.Politique} """ import Conteneur_Zip # import necessaire plus bas, ne peut etre fait # a l'init du module car reference croisee... liste_resultats=[] # liste des objets Resultat de chaque fichier # on commence par lister les fichiers self.lister_fichiers() for fichier in self.liste_fichiers: Journal.info2(_(u"FICHIER: %s") % fichier.chemin_complet) # test de l'interruption de transfert par l'utilisateur if commun.continuer_transfert == False: break fichier.nettoyer(politique) # on incrémente le compteur d'avancement sauf pour les conteneurs zip #if self.type != "Archive Zip" : # test incorrect si OS non fr if isinstance(self, Conteneur_Zip.Conteneur_Zip): commun.compteur_avancement += 1 # on ajoute le résultat à la liste des résultats liste_resultats.append(fichier.resultat_fichier) #if fichier.rejet: #if fichier.resultat_fichier.code_resultat == Resultat.REFUSE: if fichier.resultat_fichier.est_refuse(): # on supprime la copie temporaire du fichier si elle existe fichier.rejeter() # maintenant tous les fichiers ont été nettoyés, on ferme le # conteneur: self.fermer() # on efface les éventuels répertoires vides de conteneur if self.rep_relatif_source!= "": effacer_rep_vide(self.rep_temp_complet) # in clean mode, rebuild the container and copy it to destination: Journal.debug('clean_mode=%s' % commun.clean_mode) if commun.clean_mode: # on reconstruit le conteneur à partir des fichiers temporaires nettoyés Journal.debug('Rebuilding the container and copying to destination') self.reconstruire() else: # scan only mode, no rebuilding/copying Journal.debug('Scan only mode, no need to rebuild the container.') # then delete the temp dir used to scan/clean the container: self.delete_tempdir() return liste_resultats
def __init__( self ): App.__init__( self ) config = ConfigParser.ConfigParser() config.read('config.ini') self.journal_file = config.get( 'Journal', 'journal_file' ) self.simple_program_name = config.get('Training program', 'simple_program_name' ) self.simple_program_last_training = config.getint( 'Training program', 'simple_program_last_training' ) if os.path.isfile( self.journal_file ): self.journal = Journal.load_journal( self.journal_file ) else: self.journal = Journal( [], {} ) self.dict_of_simple_programs = self.read_simple_programs() self.simple_program = self.dict_of_simple_programs.get( self.simple_program_name )
def test_journal_add_acount(self): """ Verify add acount in journal is correct. """ journal = Journal() journal.add_acount('Jorge') self.assertEqual(journal.get_number_acounts(), 1) self.assertEqual(journal.is_acount_in_journal('Jorge'), True) self.assertEqual(journal.is_acount_in_journal('Pablo'), False)
def set_another_journal(self, *rest): app = App.get_running_app() journal_file = self.journal_file_input.text filename, file_extension = os.path.splitext(journal_file) if file_extension != '.json': self.show_not_json_popup() return if journal_file != app.journal_file: app.journal_file = journal_file if os.path.isfile(app.journal_file): app.journal = Journal.load_journal(app.journal_file) else: app.journal = Journal() app.write_config() for node in self.tree_view.iterate_all_nodes(): self.tree_view.remove_node(node) self.populate_tree_view()
def antivirus_fpscan (self, politique): """ Analyse le fichier grâce à l'antivirus F-Prot 6 (fpscan). @param politique: politique de filtrage à appliquer, objet L{Politique.Politique} ou None. Si None, la politique par défaut sera appliquée. @type politique: objet L{Politique.Politique} @return: le résultat de l'analyse, ou None si le fichier est sain. @rtype : objet L{Resultat<Resultat.Resultat>} ou None """ if sys.platform == "win32": # on récupère le chemin de F-Prot: chemin_fprot = politique.parametres['fpscan_executable'].valeur Journal.info2(_(u"Lancement de fpscan pour l'analyse antivirus...")) # Options pour fpscan: # -t: analyse des alternate data streams sur NTFS (par precaution) # -v 0: pas d'affichage sauf si erreur ou infection # /maxdepth=0: pour ne pas analyser l'interieur des archives # /report: ne tente pas de desinfecter # En mode debug on affiche tous les messages: if mode_debug(): verbose = '2' else: verbose = '0' chemin_fichier = str_lat1(self.copie_temp()) ## # si le chemin du fichier contient un espace il faut l'entourer de ## # guillemets: => seulement pour os.spawnv, pas pour popen. ## if ' ' in chemin_fichier and not chemin_fichier.startswith('"'): ## chemin_fichier = '"%s"' % chemin_fichier # Note: avec popen, '-v 0' doit etre separe en 2: '-v', '2' sinon # F-prot genere une erreur et renvoie un code 20. args_fprot = [chemin_fprot, '-t', '-v', verbose, '/maxdepth=0', '/report', chemin_fichier] Journal.debug(' '.join(args_fprot)) # On lance F-Prot avec Popen_timer pour masquer son affichage # et limiter le temps d'exécution: if mode_debug(): # on cree un fichier rapport: args_fprot += ['-o', 'fpscan_debug.txt'] # en mode debug on ne masque pas l'affichage: ## resultat_fprot = subprocess.call(args_fprot) ## resultat_fprot = os.spawnv(os.P_WAIT, chemin_fprot, args_fprot[1:]) resultat_fprot = Popen_timer(args_fprot, stdout=sys.stdout, stderr=sys.stderr) else: resultat_fprot = Popen_timer(args_fprot) Journal.debug(_(u'resultat F-Prot fpscan: %d') % resultat_fprot) if resultat_fprot == 0: Journal.info2(u"fpscan: "+_(u"Pas de virus détecté.")) resultat = None # on teste en premier s'il y a eu un timeout: elif resultat_fprot == EXIT_KILL_PTIMER: resultat = Resultat.Resultat(Resultat.ERREUR_ANALYSE, u"fpscan: "+_(u"Temps dépassé lors de la vérification antivirus"), self) elif resultat_fprot & FPSCAN_INFECTION: resultat = Resultat.Resultat(Resultat.REFUSE, u"fpscan: "+_(u"Virus détecté ou fichier suspect"), self) else: resultat = Resultat.Resultat(Resultat.ERREUR_ANALYSE, u"fpscan: "+_(u"Erreur lors de la vérification antivirus"), self) else: # pour l'instant seul F-Prot sous Windows est supporté: raise NotImplementedError, \ u"fpscan: "+_(u"Antivirus non supporte ou implemente pour ce systeme.") return resultat
def antivirus_clamd (self, politique): """ Analyse le fichier grâce à l'antivirus ClamAV en mode daemon (clamd). @param politique: politique de filtrage à appliquer, objet L{Politique.Politique} ou None. Si None, la politique par défaut sera appliquée. @type politique: objet L{Politique.Politique} @return: le résultat de l'analyse, ou None si le fichier est sain. @rtype : objet L{Resultat<Resultat.Resultat>} ou None """ if not pyclamd.use_socket: # La connexion vers le service clamd n'est pas encore initialisee serveur = politique.parametres['clamd_serveur'].valeur port = politique.parametres['clamd_port'].valeur Journal.info2(_(u'Connexion au serveur clamd %s:%d...') % (serveur, port)) try: pyclamd.init_network_socket(serveur, port, timeout=180) except pyclamd.ScanError: Journal.exception(_(u"Connexion au service clamd (%s:%d) impossible.") % (serveur, port)) raise Journal.info2(pyclamd.version()) Journal.info2(_(u"Appel de clamd pour l'analyse antivirus...")) # clamd a besoin du chemin absolu du fichier: abspath = str_lat1(self.copie_temp().abspath()) Journal.debug(_(u'analyse de %s') % abspath) try: res = pyclamd.scan_file(abspath) except socket.timeout: return Resultat.Resultat(Resultat.ERREUR_ANALYSE, "clamd: "+_(u"Temps dépassé lors de la vérification antivirus") % self.nom, self) except: msg = "clamd: "+_(u"Erreur lors de la vérification antivirus") Journal.exception(msg) return Resultat.Resultat(Resultat.ERREUR_ANALYSE, msg, self) if res == None: # resultat OK, pas de virus Journal.info2("clamd: "+_(u"Pas de virus détecté.")) # on retourne un objet Resultat vide return Resultat.Resultat(fichier=self) else: # un virus a ete detecte fichier = res.keys[0] msg_virus = res[fichier] Journal.debug("clamd: "+_(u'fichier=%s resultat=%s') %(fichier, msg_virus)) return Resultat.Resultat(Resultat.REFUSE, "clamd: "+_(u"Virus détecté ou fichier suspect: %s") % msg_virus, self)
def nettoyer (self, politique): """Nettoie un fichier, en appelant le(s) filtre(s) correspondant au format du fichier, puis en effectuant une analyse antivirus. @param politique: politique de filtrage à appliquer, objet L{Politique.Politique} ou None. Si None, la politique par défaut sera appliquée. @type politique: objet L{Politique.Politique} @return: le résultat global des filtres appliqués. @rtype : objet L{Resultat<Resultat.Resultat>} """ # si une politique est fournie on récupère son dictionnaire de filtres, # sinon on récupère celle du module Politique: # (la différence est subtile ;-) if politique: dico_filtres = politique.dico_filtres else: dico_filtres = Politique.dico_filtres # on dresse une liste des formats reconnus, pour la journalisation: formats_reconnus = [] # si le fichier est chiffré dans son conteneur, on ne peut pas l'analyser: if self.conteneur.est_chiffre(self): self.resultat_fichier.ajouter(Resultat.Resultat( Resultat.REFUSE,[ _(u"%s : Le fichier est chiffré, il ne peut être analysé.") % self.conteneur.type], self)) # sinon on teste si l'extension est reconnue par un des filtres: elif self.extension in dico_filtres: # il existe au moins un filtre pour cette extension # on récupère la liste des filtres concernés # dans dico_filtres[fichier.extension]: for filtre in dico_filtres[self.extension]: format_reconnu = False # si le format est autorisé, on appelle le filtre: if filtre.parametres['format_autorise'].valeur == True: # on appelle d'abord le filtre pour analyser le # contenu du fichier: try: format_reconnu = filtre.reconnait_format(self) except: format_reconnu = False erreur = str(sys.exc_info()[1]) msg = _(u"%s : Erreur lors de l'analyse du format (%s)") % \ (filtre.nom, erreur) resultat_filtre = Resultat.Resultat( Resultat.ERREUR_ANALYSE, msg, self) self.resultat_fichier.ajouter(resultat_filtre) # on ajoute l'exception au journal technique: Journal.info2(msg, exc_info=True) # et on fait une pause pour la lire si mode debug: debug_pause() if format_reconnu: # contenu reconnu Journal.info2(filtre.nom + _(u" : Reconnu")) # on ajoute ce format à la liste: formats_reconnus.append(filtre.nom) # on appelle le filtre pour nettoyer, # et on récupère le résultat de ce filtre: try: resultat_filtre = filtre.nettoyer(self) except zipfile.BadZipfile: # si on obtient cette exception, c'est que le module zipfile ne # supporte pas le format de ce fichier zip. erreur = str(sys.exc_info()[1]) #msg = _(u"Le format de l'archive zip est incorrect ou non supporté, ") \ # + _(u"le fichier ne peut être analysé. (%s)") % erreur #resultat_filtre = Resultat.Resultat( # Resultat.ERREUR_ANALYSE, msg, self) #Journal.info2(msg, exc_info=True) resultat_filtre = filtre.resultat_format_incorrect(self, erreur) except: erreur = str(sys.exc_info()[1]) msg = _(u"%s : Erreur lors du nettoyage (%s)") % \ (filtre.nom, erreur) resultat_filtre = Resultat.Resultat( Resultat.ERREUR_ANALYSE,msg, self) # on ajoute l'exception au journal technique: Journal.info2(msg, exc_info=True) # et on fait une pause pour la lire si mode debug: debug_pause() # on ajoute ce résultat à la liste des # autres filtres pour ce fichier: self.resultat_fichier.ajouter(resultat_filtre) for r in resultat_filtre.raison: Journal.info2(r) # Conteneur: c'est le filtre qui doit gérer: # if filtre.format_conteneur: # # on crée un objet conteneur # conteneur = filtre.conteneur(self.chemin, "", self.dico_filtres, self) # # on nettoie ce conteneur, et on récupère # # les résultats de chaque fichier (liste) # liste_resultats = conteneur.nettoyer() # # on ajoute cette liste au résultat # self.resultat_fichier.resultats_conteneur = liste_resultats # liste_resultat.append(liste_resultat2) # à compléter else: # sinon le format n'est pas reconnu, on # met à jour le résultat: resultat_filtre = Resultat.Resultat( Resultat.FORMAT_INCORRECT,[filtre.nom \ + _(u" : Format de fichier non reconnu ou non autorisé")], self) self.resultat_fichier.ajouter(resultat_filtre) else: # le fichier a une extension non autorisée: # Faut-il ajouter une raison ? pass # On appelle l'antivirus après tous les filtres, si le fichier # n'est pas déjà refusé, pour économiser son analyse qui prend du temps: # (cela peut poser problème si on veut obtenir des stats précises # de virus, et d'un autre côté quand un fichier est nettoyé il ne # devrait plus contenir de code, donc plus de virus... Mais c'est tout # de même utile pour détecter certains exploits qui se cachent dans des # données normalement non exécutables) if not self.resultat_fichier.est_refuse(): resultat_antivirus = self.antivirus(politique) # on ajoute le résultat que si qqch de suspect a été détecté: if resultat_antivirus: self.resultat_fichier.ajouter(resultat_antivirus) # tous les filtres sont passés, on regarde le code du résultat final: # on affiche les détails du résultat: #print self.resultat_fichier.details() # on journalise le résultat: if len(formats_reconnus): formats = u", ".join(formats_reconnus) + u" -> " else: formats = u"" evt_journal = u"%s : %s%s" % (self.chemin_complet, formats, self.resultat_fichier.details() ) if self.resultat_fichier.est_refuse(): # si c'est un refus, log de niveau WARNING: Journal.warning(evt_journal) else: # sinon, log de niveau INFO: Journal.info(evt_journal) # on ajoute le résultat au rapport: Rapport.ajouter_resultat(self.resultat_fichier)
else: if sys.argv[1] == 'pull': while True: try: print(">> git pull") mess = puller.pull() print(mess) break except: print("unsuccessful, retry") sleep(5) sys.exit() debug = True wtab = wt.WeekTable() # The template for planner jnal = jn.Journal() # The Journal plan = pl.Plan() # The planner time = tm.Time() # Lazy time tracker tenw = tw.TenWeek() # The long run print('wtab, jnal, plan, time, tenw: On') tick = cl.Clock(debug) # The loop print('tick: On' + int(debug) * ' (debug mode)') while not tick.exit: # Mail receive a special treatment since it needs # to be destruct and re-construct when there is connection fault # thus it is initiate inside the scope of tick.run tick.run(ml, time, tenw, wtab, jnal, plan) if tick.update: # TODO: Run git synchorise here
import Abiturient import Journal journal = Journal.Journal() stud1 = Abiturient.Abiturient() journal.add_student(stud1) stud2 = Abiturient.Abiturient() journal.add_student(stud2) stud3 = Abiturient.Abiturient() journal.add_student(stud3) ''' stud4 = Abiturient.Abiturient() stud5 = Abiturient.Abiturient() stud6 = Abiturient.Abiturient() ''' ''' journal.add_student(stud4) journal.add_student(stud5) journal.add_student(stud6) ''' #journal.del_obj() #journal.above_specified_value(5) #journal.bad_marks() #journal.grade_point_average()
def antivirus_clamd(self, politique): """ Analyse le fichier grâce à l'antivirus ClamAV en mode daemon (clamd). @param politique: politique de filtrage à appliquer, objet L{Politique.Politique} ou None. Si None, la politique par défaut sera appliquée. @type politique: objet L{Politique.Politique} @return: le résultat de l'analyse, ou None si le fichier est sain. @rtype : objet L{Resultat<Resultat.Resultat>} ou None """ if not pyclamd.use_socket: # La connexion vers le service clamd n'est pas encore initialisee serveur = politique.parametres['clamd_serveur'].valeur port = politique.parametres['clamd_port'].valeur Journal.info2( _(u'Connexion au serveur clamd %s:%d...') % (serveur, port)) try: pyclamd.init_network_socket(serveur, port, timeout=180) except pyclamd.ScanError: Journal.exception( _(u"Connexion au service clamd (%s:%d) impossible.") % (serveur, port)) raise Journal.info2(pyclamd.version()) Journal.info2(_(u"Appel de clamd pour l'analyse antivirus...")) # clamd a besoin du chemin absolu du fichier: abspath = str_lat1(self.copie_temp().abspath()) Journal.debug(_(u'analyse de %s') % abspath) try: res = pyclamd.scan_file(abspath) except socket.timeout: return Resultat.Resultat( Resultat.ERREUR_ANALYSE, "clamd: " + _(u"Temps dépassé lors de la vérification antivirus") % self.nom, self) except: msg = "clamd: " + _(u"Erreur lors de la vérification antivirus") Journal.exception(msg) return Resultat.Resultat(Resultat.ERREUR_ANALYSE, msg, self) if res == None: # resultat OK, pas de virus Journal.info2("clamd: " + _(u"Pas de virus détecté.")) # on retourne un objet Resultat vide return Resultat.Resultat(fichier=self) else: # un virus a ete detecte fichier = res.keys[0] msg_virus = res[fichier] Journal.debug("clamd: " + _(u'fichier=%s resultat=%s') % (fichier, msg_virus)) return Resultat.Resultat( Resultat.REFUSE, "clamd: " + _(u"Virus détecté ou fichier suspect: %s") % msg_virus, self)
# spécifiée, on force l'affichage de l'aide: if (len(args)==0 or (options.destination!="" and options.output_file!=""))\ and options.export_html==''\ and options.nouv_politique=='': op.print_help() print "" print 'Please specify files to be analyzed, and an optional destination.' ## print _("Il faut indiquer les fichiers/repertoires a nettoyer, ainsi qu'une destination.") sys.exit(parametres['exitcode_error'].valeur) # on exploite les éventuelles options if options.debug: mode_debug(True) # init console logging (after setting the debug mode if -v option): Journal.init_console_logging() # On crée d'abord une politique par défaut: pol = Politique.Politique() # ensuite on charge le fichier de config général si précisé: if options.config: pol.lire_config(options.config) # puis le fichier de la politique: if options.politique: pol.lire_config(options.politique) # si l'option nouvelle politique est active on sauve la politique dans un # fichier INI: if options.nouv_politique != '': pol.ecrire_fichier(options.nouv_politique) print _('Politique sauvee dans le fichier %s') % options.nouv_politique
def antivirus_fpscan(self, politique): """ Analyse le fichier grâce à l'antivirus F-Prot 6 (fpscan). @param politique: politique de filtrage à appliquer, objet L{Politique.Politique} ou None. Si None, la politique par défaut sera appliquée. @type politique: objet L{Politique.Politique} @return: le résultat de l'analyse, ou None si le fichier est sain. @rtype : objet L{Resultat<Resultat.Resultat>} ou None """ if sys.platform == "win32": # on récupère le chemin de F-Prot: chemin_fprot = politique.parametres['fpscan_executable'].valeur Journal.info2( _(u"Lancement de fpscan pour l'analyse antivirus...")) # Options pour fpscan: # -t: analyse des alternate data streams sur NTFS (par precaution) # -v 0: pas d'affichage sauf si erreur ou infection # /maxdepth=0: pour ne pas analyser l'interieur des archives # /report: ne tente pas de desinfecter # En mode debug on affiche tous les messages: if mode_debug(): verbose = '2' else: verbose = '0' chemin_fichier = str_lat1(self.copie_temp()) ## # si le chemin du fichier contient un espace il faut l'entourer de ## # guillemets: => seulement pour os.spawnv, pas pour popen. ## if ' ' in chemin_fichier and not chemin_fichier.startswith('"'): ## chemin_fichier = '"%s"' % chemin_fichier # Note: avec popen, '-v 0' doit etre separe en 2: '-v', '2' sinon # F-prot genere une erreur et renvoie un code 20. args_fprot = [ chemin_fprot, '-t', '-v', verbose, '/maxdepth=0', '/report', chemin_fichier ] Journal.debug(' '.join(args_fprot)) # On lance F-Prot avec Popen_timer pour masquer son affichage # et limiter le temps d'exécution: if mode_debug(): # on cree un fichier rapport: args_fprot += ['-o', 'fpscan_debug.txt'] # en mode debug on ne masque pas l'affichage: ## resultat_fprot = subprocess.call(args_fprot) ## resultat_fprot = os.spawnv(os.P_WAIT, chemin_fprot, args_fprot[1:]) resultat_fprot = Popen_timer(args_fprot, stdout=sys.stdout, stderr=sys.stderr) else: resultat_fprot = Popen_timer(args_fprot) Journal.debug(_(u'resultat F-Prot fpscan: %d') % resultat_fprot) if resultat_fprot == 0: Journal.info2(u"fpscan: " + _(u"Pas de virus détecté.")) resultat = None # on teste en premier s'il y a eu un timeout: elif resultat_fprot == EXIT_KILL_PTIMER: resultat = Resultat.Resultat( Resultat.ERREUR_ANALYSE, u"fpscan: " + _(u"Temps dépassé lors de la vérification antivirus"), self) elif resultat_fprot & FPSCAN_INFECTION: resultat = Resultat.Resultat( Resultat.REFUSE, u"fpscan: " + _(u"Virus détecté ou fichier suspect"), self) else: resultat = Resultat.Resultat( Resultat.ERREUR_ANALYSE, u"fpscan: " + _(u"Erreur lors de la vérification antivirus"), self) else: # pour l'instant seul F-Prot sous Windows est supporté: raise NotImplementedError, \ u"fpscan: "+_(u"Antivirus non supporte ou implemente pour ce systeme.") return resultat
import Journal, Politique import traceback import re # regex to extract the filename from a content-disposition header: re_content_disposition = re.compile(r'(?i)filename\s*=\s*"([^"]*)"') # debug mode xf.mode_debug(True) # force logfile option p = Politique.Politique() p.parametres['journal_securite'].set(True) # init console logging Journal.init_console_logging() class CherryProxy_xf(cherryproxy.CherryProxy): """ Simple web proxy with ExeFilter """ ## def filter_request_headers(self): ## # extract filename extension from URL: ## ext = os.path.splitext(self.req.path)[1] ## self.log.debug('extension: %s' % ext) ## if str(ext).lower() == '.exe': ## msg = 'Request blocked due to filename with executable extension in URL' ## self.log.warning(msg) ## self.set_response_forbidden(reason=msg)
def _transfert_not_threadsafe(liste_source, destination, type_transfert="entree", handle=None, pol=None, dest_is_a_file=False, force_extension=None, logfile=None): """ Main function to scan or clean files and directories. Not thread safe: should not be called directly, use transfert() instead. """ global nom_journal_secu global path_logfile global nom_journal_debug global path_debugfile global nom_rapport global p # obsolete, to be removed? if sys.platform == 'win32': if handle != None : win32security.ImpersonateLoggedOnUser(handle) taille_src = 0 # on récupère le nom de l'utilisateur qui lance ExeFilter, avec nom de # domaine (ou de machine) sous Windows: try: username = get_username() username_withdomain = get_username(with_domain=True) except: # workaround if user name cannot be determined username = username_withdomain = 'unknown' # création du tronc commun pour les noms des journaux et des rapports: nom_machine = socket.gethostname() date = time.strftime("%Y-%m-%d", time.localtime()) heure = time.strftime("%Hh%Mm%Ss", time.localtime()) nom_commun = date + "_" + nom_machine + "_" + username + "_" + heure # on transmet à transfert : # soit un objet Politique déjà configuré, # soit un nom de fichier de config directement, # soit une liste de fichiers de config, # soit un mot-clé " entree " ou " sortie " décrivant le type de transfert, # afin de conserver la compatibilité avec l'IHM actuelle. Dans ce cas le fichier de config filtres.cfg doit être analysé correctement. if pol != None: if isinstance(pol, Politique.Politique): p = pol elif isinstance (pol, [file, str, unicode, list]): p = Politique.Politique(pol) # obsolete, to be removed? elif type_transfert in ("entree", "sortie"): # vérifier si le fichier existe # si le fichier existe alors on le charge # sinon politque par défaut # p = Politique.Politique("politique_%s.cfg" % type_transfert) p = Politique.Politique() else: # politique par défaut p = Politique.Politique() # store policy in a global variable: to be removed for multithreading commun.politique = p # nom des fichiers log = nom de la machine + date et heure du transfert if logfile == 'auto': print 'logfile=auto' # generate log filename automatically (one per session): nom_journal_secu = nom_commun + ".log" # set full path in logs folder: logs_folder = path(p.parametres['rep_journaux'].valeur) # make sure the logs folder exists (if logging to file is enabled): if (not os.path.exists(logs_folder)) and p.parametres['journal_securite'].valeur: logs_folder.makedirs() path_logfile = (logs_folder / nom_journal_secu).abspath() elif logfile: print 'logfile=%s' % logfile # use provided log filename: nom_journal_secu = logfile # set full path directly: path_logfile = path(nom_journal_secu).abspath() else: nom_journal_secu = None path_logfile = None # debug logfile: only handled via policy, auto name nom_journal_debug = "debug_" + nom_commun + ".log" # set full path in logs folder: logs_folder = path(p.parametres['rep_journaux'].valeur) # make sure the logs folder exists (if logging to file is enabled): if (not os.path.exists(logs_folder)) and p.parametres['journal_debug'].valeur: logs_folder.makedirs() path_debugfile = (logs_folder / nom_journal_debug).abspath() # création du journal d'évènements: Journal.init_journal(p, journal_secu = path_logfile, journal_debug = path_debugfile) # création des sous-répertoires temp et archivage: commun.sous_rep_archive = "transfert_" + nom_commun Journal.important(_(u"ExeFilter v%s lancé par utilisateur %s sur la machine %s") % (XF_VERSION, username_withdomain, nom_machine)) # on ajoute la politique dans le journal: p.journaliser() Journal.info2(_(u"Début de l'analyse")) Rapport.liste_resultats = [] # liste des répertoires et/ou fichiers source liste_conteneurs_source = [] # initialisation des variables globales commun.nb_fichiers = commun.compteur_avancement = 0 commun.continuer_transfert = True commun.transfert_commence = False # if destination is a single file, check if source is one file: if dest_is_a_file: assert(len(liste_source)==1) assert(os.path.isfile(liste_source[0])) # if destination is empty (None or ''), set mode to scan-only instead of clean: if destination: commun.clean_mode = True Journal.debug('Analysis mode: clean') else: commun.clean_mode = False Journal.debug('Analysis mode: scan only') Journal.debug('clean_mode=%s' % commun.clean_mode) # boucle pour lire chaque répertoire et/ou fichier contenu dans la liste for source in liste_source : # on vérifie le type de source: répertoire ou fichier ? if os.path.isdir(source): #rep_source = Conteneur_Repertoire.Conteneur_Repertoire (source, destination) # si source est G:/tutu/tata, rep_relatif_source = tata (head, tail) = os.path.split(source) rep_relatif_source = tail rep_source = Conteneur_Repertoire.Conteneur_Repertoire (source, destination, rep_relatif_source, politique=p) # calcul de la taille du répertoire source taille_src += rep_source.compter_taille_rep() else: #rep_source = Conteneur_Fichier.Conteneur_Fichier (source, destination) rep_relatif_source = "" rep_source = Conteneur_Fichier.Conteneur_Fichier (source, destination, rep_relatif_source, politique=p, dest_is_a_file=dest_is_a_file, force_extension=force_extension) # calcul de la taille du fichier source taille_src += os.stat(source).st_size # on ajoute les conteneurs source à la liste liste_conteneurs_source.append(rep_source) # on incrémente le compteur nombre de fichiers total commun.nb_fichiers += rep_source.compter_nb_fichiers() # test si la taille des fichiers source est supérieure à celle du rép temp # si c'est le cas, on génère une exception #if taille_src > taille_temp: if taille_src > p.parametres['taille_temp'].valeur: msg = "La taille des fichiers source est superieure a la taille du repertoire temporaire." Journal.error(msg) raise RuntimeError, msg # initialisation de l'archivage: if parametres['archive_after'].valeur: init_archivage(p, taille_src) commun.transfert_commence = True # boucle d'analyse de chaque conteneur source contenu dans la liste for conteneur_source in liste_conteneurs_source: Journal.info2(u"Analyse de contenu de %s ..." % conteneur_source) # ici il faudrait un try pour gérer toutes les exceptions, journaliser # et nettoyer s'il y a des erreurs. # ou alors lancer un thread... # test de l'interruption de transfert par l'utilisateur if commun.continuer_transfert == True: # s'il n'y a pas d'interruption, on lance le nettoyage liste_resultat = conteneur_source.nettoyer(p) # s'il y a eu une interruption pendant nettoyer(), on s'arrête if commun.continuer_transfert == False: break # génération du rapport nom_rapport = "rapport_" + nom_commun Journal.info2(u"Génération du rapport: %s ..." % nom_rapport) chemin_rapport = p.parametres['rep_rapports'].valeur + nom_rapport resume = Rapport.generer_rapport(chemin_rapport, ', '.join(liste_source), destination , XF_VERSION, XF_DATE, commun.continuer_transfert) Journal.info2(u"Fin de l'analyse") # log du résumé de la dépollution Journal.important(_(u'Résumé : %d fichiers analysés ; ' u'%d fichiers acceptés ; %d fichiers nettoyés ; %d fichiers refusés ; %d erreurs') % (resume[0], resume[1], resume[2], resume[3], resume[4])) if commun.continuer_transfert == False: Journal.warning(u"TRANSFERT ANNULE par l'utilisateur") # return exit code according to results: #TODO: use results from containers instead of this quick hack: clean = resume[1] cleaned = resume[2] blocked = resume[3] errors = resume[4] if errors: exitcode = p.parametres['exitcode_error'].valeur elif (clean+cleaned>0) and (cleaned+blocked>0): exitcode = p.parametres['exitcode_cleaned'].valeur elif (clean>0) and (cleaned+blocked == 0): exitcode = p.parametres['exitcode_clean'].valeur elif (blocked>0) and (clean+cleaned == 0): exitcode = p.parametres['exitcode_blocked'].valeur else: raise ValueError, 'Summary values look wrong...' Journal.debug('Exit code: %d' % exitcode) Journal.fermer_journal() return exitcode
def __init__(self, node): Journal.__init__(self, "$paxos_journal", node)
def cli(): if not os.path.exists(CONFIG_PATH): config = install.install_jrnl(CONFIG_PATH) else: with open(CONFIG_PATH) as f: config = json.load(f) install.update_config(config, config_path=CONFIG_PATH) original_config = config.copy() # check if the configuration is supported by available modules if config['encrypt'] and not PYCRYPTO: print( "According to your jrnl_conf, your journal is encrypted, however PyCrypto was not found. To open your journal, install the PyCrypto package from http://www.pycrypto.org." ) sys.exit(-1) args = parse_args() # If the first textual argument points to a journal file, # use this! journal_name = args.text[0] if ( args.text and args.text[0] in config['journals']) else 'default' if journal_name is not 'default': args.text = args.text[1:] journal_conf = config['journals'].get(journal_name) if type( journal_conf ) is dict: # We can override the default config on a by-journal basis config.update(journal_conf) else: # But also just give them a string to point to the journal file config['journal'] = journal_conf touch_journal(config['journal']) mode_compose, mode_export = guess_mode(args, config) # open journal file or folder if os.path.isdir(config['journal']) and ( config['journal'].endswith(".dayone") or \ config['journal'].endswith(".dayone/")): journal = Journal.DayOne(**config) else: journal = Journal.Journal(**config) if mode_compose and not args.text: if config['editor']: raw = get_text_from_editor(config) else: raw = util.py23_input("[Compose Entry] ") if raw: args.text = [raw] else: mode_compose = False # Writing mode if mode_compose: raw = " ".join(args.text).strip() entry = journal.new_entry(raw, args.date) entry.starred = args.star print("[Entry added to {0} journal]".format(journal_name)) journal.write() # Reading mode elif not mode_export: journal.filter(tags=args.text, start_date=args.start_date, end_date=args.end_date, strict=args.strict, short=args.short) journal.limit(args.limit) print(journal) # Various export modes elif args.tags: print_tags(journal) elif args.json: # export to json print(exporters.to_json(journal)) elif args.markdown: # export to json print(exporters.to_md(journal)) elif (args.encrypt is not False or args.decrypt is not False) and not PYCRYPTO: print( "PyCrypto not found. To encrypt or decrypt your journal, install the PyCrypto package from http://www.pycrypto.org." ) elif args.encrypt is not False: encrypt(journal, filename=args.encrypt) # Not encrypting to a separate file: update config! if not args.encrypt: update_config(original_config, { "encrypt": True, "password": "" }, journal_name) install.save_config(original_config, config_path=CONFIG_PATH) elif args.decrypt is not False: decrypt(journal, filename=args.decrypt) # Not decrypting to a separate file: update config! if not args.decrypt: update_config(original_config, { "encrypt": False, "password": "" }, journal_name) install.save_config(original_config, config_path=CONFIG_PATH) elif args.delete_last: last_entry = journal.entries.pop() print("[Deleted Entry:]") print(last_entry) journal.write()
def nettoyer(self, politique): """Nettoie un fichier, en appelant le(s) filtre(s) correspondant au format du fichier, puis en effectuant une analyse antivirus. @param politique: politique de filtrage à appliquer, objet L{Politique.Politique} ou None. Si None, la politique par défaut sera appliquée. @type politique: objet L{Politique.Politique} @return: le résultat global des filtres appliqués. @rtype : objet L{Resultat<Resultat.Resultat>} """ # si une politique est fournie on récupère son dictionnaire de filtres, # sinon on récupère celle du module Politique: # (la différence est subtile ;-) if politique: dico_filtres = politique.dico_filtres else: dico_filtres = Politique.dico_filtres # on dresse une liste des formats reconnus, pour la journalisation: formats_reconnus = [] # si le fichier est chiffré dans son conteneur, on ne peut pas l'analyser: if self.conteneur.est_chiffre(self): self.resultat_fichier.ajouter( Resultat.Resultat(Resultat.REFUSE, [ _(u"%s : Le fichier est chiffré, il ne peut être analysé." ) % self.conteneur.type ], self)) # sinon on teste si l'extension est reconnue par un des filtres: elif self.extension in dico_filtres: # il existe au moins un filtre pour cette extension # on récupère la liste des filtres concernés # dans dico_filtres[fichier.extension]: for filtre in dico_filtres[self.extension]: format_reconnu = False # si le format est autorisé, on appelle le filtre: if filtre.parametres['format_autorise'].valeur == True: # on appelle d'abord le filtre pour analyser le # contenu du fichier: try: format_reconnu = filtre.reconnait_format(self) except: format_reconnu = False erreur = str(sys.exc_info()[1]) msg = _(u"%s : Erreur lors de l'analyse du format (%s)") % \ (filtre.nom, erreur) resultat_filtre = Resultat.Resultat( Resultat.ERREUR_ANALYSE, msg, self) self.resultat_fichier.ajouter(resultat_filtre) # on ajoute l'exception au journal technique: Journal.info2(msg, exc_info=True) # et on fait une pause pour la lire si mode debug: debug_pause() if format_reconnu: # contenu reconnu Journal.info2(filtre.nom + _(u" : Reconnu")) # on ajoute ce format à la liste: formats_reconnus.append(filtre.nom) # on appelle le filtre pour nettoyer, # et on récupère le résultat de ce filtre: try: resultat_filtre = filtre.nettoyer(self) except zipfile.BadZipfile: # si on obtient cette exception, c'est que le module zipfile ne # supporte pas le format de ce fichier zip. erreur = str(sys.exc_info()[1]) #msg = _(u"Le format de l'archive zip est incorrect ou non supporté, ") \ # + _(u"le fichier ne peut être analysé. (%s)") % erreur #resultat_filtre = Resultat.Resultat( # Resultat.ERREUR_ANALYSE, msg, self) #Journal.info2(msg, exc_info=True) resultat_filtre = filtre.resultat_format_incorrect( self, erreur) except: erreur = str(sys.exc_info()[1]) msg = _(u"%s : Erreur lors du nettoyage (%s)") % \ (filtre.nom, erreur) resultat_filtre = Resultat.Resultat( Resultat.ERREUR_ANALYSE, msg, self) # on ajoute l'exception au journal technique: Journal.info2(msg, exc_info=True) # et on fait une pause pour la lire si mode debug: debug_pause() # on ajoute ce résultat à la liste des # autres filtres pour ce fichier: self.resultat_fichier.ajouter(resultat_filtre) for r in resultat_filtre.raison: Journal.info2(r) # Conteneur: c'est le filtre qui doit gérer: # if filtre.format_conteneur: # # on crée un objet conteneur # conteneur = filtre.conteneur(self.chemin, "", self.dico_filtres, self) # # on nettoie ce conteneur, et on récupère # # les résultats de chaque fichier (liste) # liste_resultats = conteneur.nettoyer() # # on ajoute cette liste au résultat # self.resultat_fichier.resultats_conteneur = liste_resultats # liste_resultat.append(liste_resultat2) # à compléter else: # sinon le format n'est pas reconnu, on # met à jour le résultat: resultat_filtre = Resultat.Resultat( Resultat.FORMAT_INCORRECT,[filtre.nom \ + _(u" : Format de fichier non reconnu ou non autorisé")], self) self.resultat_fichier.ajouter(resultat_filtre) else: # le fichier a une extension non autorisée: # Faut-il ajouter une raison ? pass # On appelle l'antivirus après tous les filtres, si le fichier # n'est pas déjà refusé, pour économiser son analyse qui prend du temps: # (cela peut poser problème si on veut obtenir des stats précises # de virus, et d'un autre côté quand un fichier est nettoyé il ne # devrait plus contenir de code, donc plus de virus... Mais c'est tout # de même utile pour détecter certains exploits qui se cachent dans des # données normalement non exécutables) if not self.resultat_fichier.est_refuse(): resultat_antivirus = self.antivirus(politique) # on ajoute le résultat que si qqch de suspect a été détecté: if resultat_antivirus: self.resultat_fichier.ajouter(resultat_antivirus) # tous les filtres sont passés, on regarde le code du résultat final: # on affiche les détails du résultat: #print self.resultat_fichier.details() # on journalise le résultat: if len(formats_reconnus): formats = u", ".join(formats_reconnus) + u" -> " else: formats = u"" evt_journal = u"%s : %s%s" % (self.chemin_complet, formats, self.resultat_fichier.details()) if self.resultat_fichier.est_refuse(): # si c'est un refus, log de niveau WARNING: Journal.warning(evt_journal) else: # sinon, log de niveau INFO: Journal.info(evt_journal) # on ajoute le résultat au rapport: Rapport.ajouter_resultat(self.resultat_fichier)
manager = BookstoreManager(BookstoreItem.storage) book1 = Book("Tropic of Cancer", "Henry Miller", "Autobiographical novel", 1934, 318) book2 = Book("1984", "George Orwell", "Novel", 1949, 328) book3 = Book("Junkie", "William S. Burroughs", "Autobiographical novel", 1953, 166) # book4 = Book("Edinburgh", "Alexander Chee", "Autobiographical novel", 2001, 209) book5 = Book("Giovanni's Room", "James Baldwin", "Poem", 1956, 159) book6 = Book("On the Road", "Jack Kerouac", "Autobiographical novel", 1957, 320) comics1 = Comics("Deadpool", "Marvel", "Superhero", 2019, 25) newspaper1 = Newspaper("NYT", "NY", "Weekly", "04.10.2020", 20) journal1 = Journal("ATT", "AT", "Celebrity", "10.20.2021", 14) magazine1 = Magazine("Rolling Stone", "Wenner Media LLC", "Musical", "04.10.2020", 18) magazine2 = Magazine("Esquire", "Hearts Communications Inc", "Fashion", "21.11.2014", 22) magazine3 = Magazine("Vanity Fair", "Conde Nast", "Musical", "15.12.2020", 30) magazine4 = Magazine("Elle", "Kevin OMalley", "Musical", "10.04.2018", 14) print("Unsorted list of autobiographical novel genre items:\n") for item in manager.find_item_by_genre("Autobiographical novel"): print(item) print( "Sorted by ascending name list of autobiographical novel genre items:\n"
def antivirus_fpcmd(self, politique): """ Analyse le fichier grâce à l'antivirus F-Prot 3 (fpcmd). @param politique: politique de filtrage à appliquer, objet L{Politique.Politique} ou None. Si None, la politique par défaut sera appliquée. @type politique: objet L{Politique.Politique} @return: le résultat de l'analyse, ou None si le fichier est sain. @rtype : objet L{Resultat<Resultat.Resultat>} ou None """ if sys.platform == "win32": # on récupère le chemin de fpcmd: chemin_fprot = politique.parametres['fpcmd_executable'].valeur Journal.info2(_(u"Lancement de fpcmd pour l'analyse antivirus...")) args_fprot = [ chemin_fprot, '-nomem', '-noboot', '-nosub', '-silent', '-old', '-collect', str_lat1(self.copie_temp()) ] # A VOIR: l'option -type laisse F-Prot décider si un type de fichier doit # être scanné, alors que -collect force F-Prot à tout scanner # (risque de faux-positifs) # On lance F-Prot avec Popen_timer pour masquer son affichage # et limiter le temps d'exécution: resultat_fprot = Popen_timer(args_fprot) # codes retournés par F-Prot 3: # 0 - Normal exit - nothing found # 1 - Abnormal termination - unrecoverable error. This can mean any of # the following: # Internal error in the program. # DOS version prior to 3.0 was used. # ENGLISH.TX0, SIGN.DEF or MACRO.DEF corrupted or not present. # 2 - Selftest failed - program has been modified. # 3 - A Boot/File virus infection found. # 4 - Virus found in memory. # 5 - Program terminated with ^C or ESC. # 6 - A virus was removed. This code is only meaningful if # the program is used to scan just a single file. # 7 - Insufficient memory to run the program. # 8 - At least one suspicious file was found, but no infections. if resultat_fprot == 0: Journal.info2(u"fpcmd: " + _(u"Pas de virus détecté.")) resultat = None elif resultat_fprot in [3, 4, 6, 8]: resultat = Resultat.Resultat( Resultat.REFUSE, u"fpcmd: " + _(u"Virus détecté ou fichier suspect"), self) elif resultat_fprot == EXIT_KILL_PTIMER: resultat = Resultat.Resultat( Resultat.ERREUR_ANALYSE, u"fpcmd: " + _(u"Temps dépassé lors de la vérification antivirus"), self) else: resultat = Resultat.Resultat( Resultat.ERREUR_ANALYSE, u"fpcmd: " + _(u"Erreur lors de la vérification antivirus"), self) else: # pour l'instant seul F-Prot sous Windows est supporté: raise NotImplementedError, \ u"fpcmd: "+_(u"Antivirus non supporte ou implemente pour ce systeme.") return resultat
def __init__(self, node): Journal.__init__(self, "$txn_journal", node) self.node = node
def _transfert_not_threadsafe(liste_source, destination, type_transfert="entree", handle=None, pol=None, dest_is_a_file=False, force_extension=None, logfile=None): """ Main function to scan or clean files and directories. Not thread safe: should not be called directly, use transfert() instead. """ global nom_journal_secu global path_logfile global nom_journal_debug global path_debugfile global nom_rapport global p # obsolete, to be removed? if sys.platform == 'win32': if handle != None: win32security.ImpersonateLoggedOnUser(handle) taille_src = 0 # on récupère le nom de l'utilisateur qui lance ExeFilter, avec nom de # domaine (ou de machine) sous Windows: try: username = get_username() username_withdomain = get_username(with_domain=True) except: # workaround if user name cannot be determined username = username_withdomain = 'unknown' # création du tronc commun pour les noms des journaux et des rapports: nom_machine = socket.gethostname() date = time.strftime("%Y-%m-%d", time.localtime()) heure = time.strftime("%Hh%Mm%Ss", time.localtime()) nom_commun = date + "_" + nom_machine + "_" + username + "_" + heure # on transmet à transfert : # soit un objet Politique déjà configuré, # soit un nom de fichier de config directement, # soit une liste de fichiers de config, # soit un mot-clé " entree " ou " sortie " décrivant le type de transfert, # afin de conserver la compatibilité avec l'IHM actuelle. Dans ce cas le fichier de config filtres.cfg doit être analysé correctement. if pol != None: if isinstance(pol, Politique.Politique): p = pol elif isinstance(pol, [file, str, unicode, list]): p = Politique.Politique(pol) # obsolete, to be removed? elif type_transfert in ("entree", "sortie"): # vérifier si le fichier existe # si le fichier existe alors on le charge # sinon politque par défaut # p = Politique.Politique("politique_%s.cfg" % type_transfert) p = Politique.Politique() else: # politique par défaut p = Politique.Politique() # store policy in a global variable: to be removed for multithreading commun.politique = p # nom des fichiers log = nom de la machine + date et heure du transfert if logfile == 'auto': print 'logfile=auto' # generate log filename automatically (one per session): nom_journal_secu = nom_commun + ".log" # set full path in logs folder: logs_folder = path(p.parametres['rep_journaux'].valeur) # make sure the logs folder exists (if logging to file is enabled): if (not os.path.exists(logs_folder) ) and p.parametres['journal_securite'].valeur: logs_folder.makedirs() path_logfile = (logs_folder / nom_journal_secu).abspath() elif logfile: print 'logfile=%s' % logfile # use provided log filename: nom_journal_secu = logfile # set full path directly: path_logfile = path(nom_journal_secu).abspath() else: nom_journal_secu = None path_logfile = None # debug logfile: only handled via policy, auto name nom_journal_debug = "debug_" + nom_commun + ".log" # set full path in logs folder: logs_folder = path(p.parametres['rep_journaux'].valeur) # make sure the logs folder exists (if logging to file is enabled): if (not os.path.exists(logs_folder) ) and p.parametres['journal_debug'].valeur: logs_folder.makedirs() path_debugfile = (logs_folder / nom_journal_debug).abspath() # création du journal d'évènements: Journal.init_journal(p, journal_secu=path_logfile, journal_debug=path_debugfile) # création des sous-répertoires temp et archivage: commun.sous_rep_archive = "transfert_" + nom_commun Journal.important( _(u"ExeFilter v%s lancé par utilisateur %s sur la machine %s") % (XF_VERSION, username_withdomain, nom_machine)) # on ajoute la politique dans le journal: p.journaliser() Journal.info2(_(u"Début de l'analyse")) Rapport.liste_resultats = [] # liste des répertoires et/ou fichiers source liste_conteneurs_source = [] # initialisation des variables globales commun.nb_fichiers = commun.compteur_avancement = 0 commun.continuer_transfert = True commun.transfert_commence = False # if destination is a single file, check if source is one file: if dest_is_a_file: assert (len(liste_source) == 1) assert (os.path.isfile(liste_source[0])) # if destination is empty (None or ''), set mode to scan-only instead of clean: if destination: commun.clean_mode = True Journal.debug('Analysis mode: clean') else: commun.clean_mode = False Journal.debug('Analysis mode: scan only') Journal.debug('clean_mode=%s' % commun.clean_mode) # boucle pour lire chaque répertoire et/ou fichier contenu dans la liste for source in liste_source: # on vérifie le type de source: répertoire ou fichier ? if os.path.isdir(source): #rep_source = Conteneur_Repertoire.Conteneur_Repertoire (source, destination) # si source est G:/tutu/tata, rep_relatif_source = tata (head, tail) = os.path.split(source) rep_relatif_source = tail rep_source = Conteneur_Repertoire.Conteneur_Repertoire( source, destination, rep_relatif_source, politique=p) # calcul de la taille du répertoire source taille_src += rep_source.compter_taille_rep() else: #rep_source = Conteneur_Fichier.Conteneur_Fichier (source, destination) rep_relatif_source = "" rep_source = Conteneur_Fichier.Conteneur_Fichier( source, destination, rep_relatif_source, politique=p, dest_is_a_file=dest_is_a_file, force_extension=force_extension) # calcul de la taille du fichier source taille_src += os.stat(source).st_size # on ajoute les conteneurs source à la liste liste_conteneurs_source.append(rep_source) # on incrémente le compteur nombre de fichiers total commun.nb_fichiers += rep_source.compter_nb_fichiers() # test si la taille des fichiers source est supérieure à celle du rép temp # si c'est le cas, on génère une exception #if taille_src > taille_temp: if taille_src > p.parametres['taille_temp'].valeur: msg = "La taille des fichiers source est superieure a la taille du repertoire temporaire." Journal.error(msg) raise RuntimeError, msg # initialisation de l'archivage: if parametres['archive_after'].valeur: init_archivage(p, taille_src) commun.transfert_commence = True # boucle d'analyse de chaque conteneur source contenu dans la liste for conteneur_source in liste_conteneurs_source: Journal.info2(u"Analyse de contenu de %s ..." % conteneur_source) # ici il faudrait un try pour gérer toutes les exceptions, journaliser # et nettoyer s'il y a des erreurs. # ou alors lancer un thread... # test de l'interruption de transfert par l'utilisateur if commun.continuer_transfert == True: # s'il n'y a pas d'interruption, on lance le nettoyage liste_resultat = conteneur_source.nettoyer(p) # s'il y a eu une interruption pendant nettoyer(), on s'arrête if commun.continuer_transfert == False: break # génération du rapport nom_rapport = "rapport_" + nom_commun Journal.info2(u"Génération du rapport: %s ..." % nom_rapport) chemin_rapport = p.parametres['rep_rapports'].valeur + nom_rapport resume = Rapport.generer_rapport(chemin_rapport, ', '.join(liste_source), destination, XF_VERSION, XF_DATE, commun.continuer_transfert) Journal.info2(u"Fin de l'analyse") # log du résumé de la dépollution Journal.important( _(u'Résumé : %d fichiers analysés ; ' u'%d fichiers acceptés ; %d fichiers nettoyés ; %d fichiers refusés ; %d erreurs' ) % (resume[0], resume[1], resume[2], resume[3], resume[4])) if commun.continuer_transfert == False: Journal.warning(u"TRANSFERT ANNULE par l'utilisateur") # return exit code according to results: #TODO: use results from containers instead of this quick hack: clean = resume[1] cleaned = resume[2] blocked = resume[3] errors = resume[4] if errors: exitcode = p.parametres['exitcode_error'].valeur elif (clean + cleaned > 0) and (cleaned + blocked > 0): exitcode = p.parametres['exitcode_cleaned'].valeur elif (clean > 0) and (cleaned + blocked == 0): exitcode = p.parametres['exitcode_clean'].valeur elif (blocked > 0) and (clean + cleaned == 0): exitcode = p.parametres['exitcode_blocked'].valeur else: raise ValueError, 'Summary values look wrong...' Journal.debug('Exit code: %d' % exitcode) Journal.fermer_journal() return exitcode
def run(manual_args=None): args = parse_args(manual_args) configure_logger(args.debug) args.text = [p.decode('utf-8') if util.PY2 and not isinstance(p, unicode) else p for p in args.text] if args.version: version_str = "{0} version {1}".format(jrnl.__title__, jrnl.__version__) print(util.py2encode(version_str)) sys.exit(0) if not os.path.exists(CONFIG_PATH): log.debug('Configuration file not found, installing jrnl...') config = install.install_jrnl(CONFIG_PATH) else: log.debug('Reading configuration from file %s', CONFIG_PATH) config = util.load_and_fix_json(CONFIG_PATH) install.upgrade_config(config, config_path=CONFIG_PATH) if args.ls: print(util.py2encode(list_journals(config))) sys.exit(0) log.debug('Using configuration "%s"', config) original_config = config.copy() # check if the configuration is supported by available modules if config['encrypt'] and not PYCRYPTO: util.prompt("According to your jrnl_conf, your journal is encrypted, however PyCrypto was not found. To open your journal, install the PyCrypto package from http://www.pycrypto.org.") sys.exit(1) # If the first textual argument points to a journal file, # use this! journal_name = args.text[0] if (args.text and args.text[0] in config['journals']) else 'default' if journal_name is not 'default': args.text = args.text[1:] # If the first remaining argument looks like e.g. '-3', interpret that as a limiter if not args.limit and args.text and args.text[0].startswith("-"): try: args.limit = int(args.text[0].lstrip("-")) args.text = args.text[1:] except: pass log.debug('Using journal "%s"', journal_name) journal_conf = config['journals'].get(journal_name) if type(journal_conf) is dict: # We can override the default config on a by-journal basis log.debug('Updating configuration with specific jourlnal overrides %s', journal_conf) config.update(journal_conf) else: # But also just give them a string to point to the journal file config['journal'] = journal_conf if config['journal'] is None: util.prompt("You have not specified a journal. Either provide a default journal in your config file, or specify one of your journals on the command line.") sys.exit(1) config['journal'] = os.path.expanduser(os.path.expandvars(config['journal'])) touch_journal(config['journal']) log.debug('Using journal path %(journal)s', config) mode_compose, mode_export = guess_mode(args, config) # open journal file or folder if os.path.isdir(config['journal']): if config['journal'].strip("/").endswith(".dayone") or \ "entries" in os.listdir(config['journal']): journal = DayOneJournal.DayOne(**config) else: util.prompt("[Error: {0} is a directory, but doesn't seem to be a DayOne journal either.".format(config['journal'])) sys.exit(1) else: journal = Journal.Journal(journal_name, **config) # How to quit writing? if "win32" in sys.platform: _exit_multiline_code = "on a blank line, press Ctrl+Z and then Enter" else: _exit_multiline_code = "press Ctrl+D" if mode_compose and not args.text: if not sys.stdin.isatty(): # Piping data into jrnl raw = util.py23_read() elif config['editor']: raw = util.get_text_from_editor(config) else: try: raw = util.py23_read("[Compose Entry; " + _exit_multiline_code + " to finish writing]\n") except KeyboardInterrupt: util.prompt("[Entry NOT saved to journal.]") sys.exit(0) if raw: args.text = [raw] else: mode_compose = False journal.open() # Writing mode if mode_compose: raw = " ".join(args.text).strip() if util.PY2 and type(raw) is not unicode: raw = raw.decode(sys.getfilesystemencoding()) log.debug('Appending raw line "%s" to journal "%s"', raw, journal_name) journal.new_entry(raw) util.prompt("[Entry added to {0} journal]".format(journal_name)) journal.write() else: old_entries = journal.entries if args.on_date: args.start_date = args.end_date = args.on_date journal.filter(tags=args.text, start_date=args.start_date, end_date=args.end_date, strict=args.strict, short=args.short, starred=args.starred) journal.limit(args.limit) # Reading mode if not mode_compose and not mode_export: print(util.py2encode(journal.pprint())) # Various export modes elif args.short: print(util.py2encode(journal.pprint(short=True))) elif args.tags: print(util.py2encode(exporters.to_tag_list(journal))) elif args.export is not False: print(util.py2encode(exporters.export(journal, args.export, args.output))) elif (args.encrypt is not False or args.decrypt is not False) and not PYCRYPTO: util.prompt("PyCrypto not found. To encrypt or decrypt your journal, install the PyCrypto package from http://www.pycrypto.org.") elif args.encrypt is not False: encrypt(journal, filename=args.encrypt) # Not encrypting to a separate file: update config! if not args.encrypt or args.encrypt == config['journal']: update_config(original_config, {"encrypt": True}, journal_name, force_local=True) install.save_config(original_config, config_path=CONFIG_PATH) elif args.decrypt is not False: decrypt(journal, filename=args.decrypt) # Not decrypting to a separate file: update config! if not args.decrypt or args.decrypt == config['journal']: update_config(original_config, {"encrypt": False}, journal_name, force_local=True) install.save_config(original_config, config_path=CONFIG_PATH) elif args.edit: if not config['editor']: util.prompt("[You need to specify an editor in {0} to use the --edit function.]".format(CONFIG_PATH)) sys.exit(1) other_entries = [e for e in old_entries if e not in journal.entries] # Edit old_num_entries = len(journal) edited = util.get_text_from_editor(config, journal.editable_str()) journal.parse_editable_str(edited) num_deleted = old_num_entries - len(journal) num_edited = len([e for e in journal.entries if e.modified]) prompts = [] if num_deleted: prompts.append("{0} {1} deleted".format(num_deleted, "entry" if num_deleted == 1 else "entries")) if num_edited: prompts.append("{0} {1} modified".format(num_edited, "entry" if num_edited == 1 else "entries")) if prompts: util.prompt("[{0}]".format(", ".join(prompts).capitalize())) journal.entries += other_entries journal.sort() journal.write()