#! /usr/bin/env python # -*- coding: iso-8859-15 -*- # # Backend CUPS pour laserjet : imprime et debite # Codé par Benoit, Fred et Braice, inspirés par CUPSPykota # Licence : GNU General Public Licence, version 2 #TODO: #Parser ce que réponds l'imprimante import sys, time, tempfile, os sys.path.append('/usr/scripts/impression') import crans_backend, pjl_comm sys.path.append('/usr/scripts/gestion') from config import impression ## Préliminaires : description = '%s laserjet "Crans" "Imprime tout en debitant"' % sys.argv[0] fic = crans_backend.preliminaires(sys.argv, description) nom_fic = fic.name ## Récuperation de l'utilisateur en écriture : utilisateur = crans_backend.utilisateur(sys.argv[2],1) # Récuperation de l'adresse mail adrmail = utilisateur.mail() if adrmail.find('@') == -1 : adrmail += "@crans.org" adrmail = adrmail.encode("iso8859-15") To = u"%s <%s>" % (utilisateur.Nom(), adrmail) ## Calcul du prix de l'impression : prix = crans_backend.calcul_prix(nom_fic,sys.argv) ## Préparation des mails sujet=u"Impression n°%(numero)s : %(fichier)s" % {'numero' : sys.argv[1], 'fichier' : unicode(sys.argv[3],"utf-8" ,'replace')} mail_err = u""" Bonjour, Il y a malheureusement eu une erreur lors de votre impression. Le message d'erreur est le suivant : %%(erreur)s Si l'erreur se reproduit, envoyez un mail à %(adresse_imprimante)s -- L'imprimante Laserjet """ % {"adresse_imprimante" : impression.From_imprimante} # Probleme de taille de papier if prix.erreur=="Taille invalide": error = u""" Le format de papier que vous avez choisi (%(taille)s) n'est pas valide. Cela ne va pas etre possible d'imprimer ce document sur Laserjet. Rappel : Si vous utilisez lp, il faut définir l'option PageSize """ % {'taille' : prix.taille} # On loggue l'erreur sys.stderr.write(("ERROR: Erreur : utilisateur : %s, format invalide : %s\n" % (utilisateur.Nom(), prix.taille)).encode('latin-1')) # et on envoi le mail d'erreur crans_backend.send_email(prix.From, To, sujet, mail_err % {'erreur' : error} ) sys.stderr.write("DEBUG: Mail envoye ;\n" ) # Postscript mal formatté : elif prix.erreur: # On loggue l'erreur sys.stderr.write(("ERROR: Erreur : utilisateur : %s, raison : %s\n" % (utilisateur.Nom(), prix.erreur)).encode('latin-1')) # et on envoi le mail d'erreur crans_backend.send_email(prix.From, To, sujet, mail_err % {'erreur' : prix.erreur} ) sys.stderr.write("DEBUG: Mail envoye ;\n" ) # Compte non suffisamment approvisionné : elif prix.c_total_euros > (utilisateur.solde() - impression.decouvert) : sys.stderr.write("DEBUG: Pas d'impression : Compte trop bas") mail_err_solde = u""" Bonjour, Votre compte n'est pas assez approvisionné pour effectuer l'impression demandée. En effet, votre solde actuel est de %(solde)s euros et l'impression coûte %(prix)s euros. -- L'imprimante Laserjet """ % { 'solde' : utilisateur.solde(), 'prix' : prix.str_cout } crans_backend.send_email(prix.From, To, sujet, mail_err_solde) sys.stderr.write("DEBUG: Mail envoye ;\n" ) # Tout est OK, on imprime else: try: #Envoi du fichier a l'imprimante nom_fic2=tempfile.mktemp() if prix.recto_v=='Recto': sys.stderr.write("DEBUG: Simple recto, on inverse juste l'ordre.\n" ) os.system("cp %s %s " % (nom_fic, nom_fic2)) os.system("psselect -r %s > %s " % (nom_fic, nom_fic2)) elif prix.faces==1: sys.stderr.write("DEBUG: Une seule face.\n" ) os.system("cp %s %s " % (nom_fic, nom_fic2)) else: sys.stderr.write("DEBUG: recto-verso on permute deux a deux.\n" ) if(prix.faces%2 ==1): sys.stderr.write("DEBUG: nombre de faces impair..\n" ) prix.faces+=1 sys.exit(0) else: sys.stderr.write("DEBUG: nombre de faces pair..\n" ) liste_pages="" for i in range(1,int(prix.faces/2)+1): liste_pages+=str(2*i)+","+str(2*i-1)+"," #on enleve la virgule superflue liste_pages=liste_pages[:-1] sys.stderr.write("DEBUG: Liste pages : %s\n" % liste_pages ) os.system("cp %s %s " % (nom_fic, nom_fic2)) os.system("psselect -p%s %s > %s 2>/dev/null" % (liste_pages, nom_fic, nom_fic2)) sys.stderr.write("DEBUG: Envoi du fichier a l'imprimante.\n" ) imprimante=pjl_comm.hp9500() imprimante.cx_open() imprimante.pjl_command('USTATUS PAGE = ON') imprimante.pjl_command('USTATUS JOB = ON') imprimante.pjl_command('USTATUS DEVICE = ON') imprimante.write_postscript(nom_fic2, sys.argv[1], utilisateur.Nom()) os.system("mv %s /tmp/last_printed.ps" % nom_fic2) os.system("chmod 644 /tmp/last_printed.ps") message=imprimante.pjl_read() i=0 sys.stderr.write("DEBUG: Message de l'imprimante : \n%s\n" %message ) while(message.find("PAGES=")==-1 and i<200): message=imprimante.pjl_read() sys.stderr.write("DEBUG: Message : %s\n" %message ) sys.stderr.write("DEBUG: Impression non terminée..\n" ) i=i+1 time.sleep(2) if i==200: sys.stderr.write("ERROR: Impression arretee car lancee depuis 400s...\n") else: sys.stderr.write("DEBUG: Impression terminée temporisation de 20s...\n") time.sleep(10) imprimante.cx_close() time.sleep(10) # Si messsage contient DISPLAY="Annulation de la tache" : # On ne debite pas l'utilisateur et on envoie le mail adequat. if "Annulation" in message: # On loggue l'erreur sys.stderr.write(("ERROR: Erreur : utilisateur : %s, Tache annulée" % utilisateur.Nom()).encode('latin-1')) # et on envoi le mail d'erreur crans_backend.send_email(prix.From, To, "Annulation : " + sujet, mail_err % {'erreur' : "Annulation de la tache"}) sys.exit(0) # On débite l'adhérent si l'impression a eu lieu utilisateur.solde(-prix.c_total_euros) utilisateur.save() #Génération du code et écriture du code i=0 code=0 import random #instance de base rand=random.Random() #graine automatique avec le temps rand.seed() while(i<1000) : #on génère le numéro de session code=rand.randint(100000,999999) #pour avoir six chiffres #on sauvegarde les données concernant la session dans un fichier qui périme dans duree_session try: open("/var/impression/codes/%d" %code, 'r') except : break i=i+1 if code: codefichier=open("/var/impression/codes/%d" %code, 'w') codefichier.write("Utilisateur %s\n"%(utilisateur.Nom())) codefichier.close() else : # Grosse erreur : on logue, on previent et on stoppe. sys.stderr.write("ERROR: Il n'y a pas de code disponible" ) try: crans_backend.send_email(prix.From, "Impression <%s>" % impression.From_imprimante , u"ERREUR " + sujet, mail_err % {'erreur' : "Il n'y a plus de code disponible.\n"}) sys.stderr.write("DEBUG: Un rapport de bug a ete automatiquement envoye.\n") except : sys.stderr.write("ERROR: Impossible d'envoyer le rapport de bug.\n") sys.stderr.write("ERROR: Plus de codes disponibles.\n") sys.stderr.write("ERROR: Penser a ouvrir a l'adherent debite...\n") sys.exit(1) #envoi du mail avec le code et le prix mail_ok = u""" Bonjour, L'ancien solde de votre compte impression valait %(solde)s euros. L'impression que vous avez demandé coûte la modique somme de %(prix)s. L'impression s'est correctement effectuée et votre compte a été débité. Pour accéder au local de l'imprimante (4ème étage du Bat J), le code unique de cette impression est : %(code)s# -- L'imprimante Laserjet """ % { 'solde' : utilisateur.solde(), 'prix' : prix.str_cout, 'code' : code } crans_backend.send_email(prix.From, To, sujet, mail_ok) sys.stderr.write("DEBUG: Mail envoye ; Fin de l'impression...\n" ) except: sys.stderr.write("ERROR: Erreur : Probleme d'impression\n" ) crans_backend.send_email(prix.From, To, sujet, mail_err % {'erreur' : u"Le fichier n'a pu être imprimé.\n Veuillez réessayer plus tard.\n"} ) # Report de bug import traceback from cStringIO import StringIO s = StringIO() sys.stderr = s traceback.print_exc() sys.stderr = sys.__stderr__ traceback = s.getvalue() try: prix.erreur = "\n" crans_backend.send_email(prix.From, "Impression <%s>" % impression.From_imprimante , sujet, "Une erreur s'est produite lors de cette impression, voici le compte rendu :\n" + traceback + "\nUne analyse des logs de CUPS peux aider a comprendre l'origine de cette erreur.\n-- \nL'imprimante Laserjet") sys.stderr.write("DEBUG: Un rapport de bug a ete automatiquement envoye.\n") except : sys.stderr.write("ERROR: Impossible d'envoyer le rapport de bug.\n") sys.stderr.write("ERROR: %s \n" % traceback) sys.exit(0)