#! /usr/bin/env python # -*- coding: iso-8859-15 -*- # # Class pour l'impression depuis le web par cups # Codé par Francois # Inspiré par le backend écrit par Benoit, Fred et Brice, inspirés par CUPSPykota # Licence : GNU General Public Licence, version 2 import sys, time, tempfile, os, commands, string, random sys.path.append('/usr/scripts/impression') sys.path.append('/usr/scripts/gestion') from config import impression from ldap_crans import crans_ldap duree_vie_pdf=3600 #fonction principal: impression (fichier_impression) class test: def mail(self): return u"francois.bobot@crans.org" def Nom(self): return u"francois" def solde(self,modif=0.): return (40.+modif) def save(self): pass class fichier_impression : nom_job='' nbr_pages=1 nb_copie=1 taille="A4" recto_verso=False transparent=False couleur=True cout=0.0 portrait=True user="" user_ldap=None # sera une instance de l'utilisateur dans la base ldap. imprime=-1 #-2 impression en suspend, -1 mise dans la file # d'attente, 0 devis, time pour l'heure, -3 déja # imprimé ou devis fait depuis trops longtemps : le # pdf n'est plus disponible nom_fichier_pdf="" # chemin et nom du pdf nom_fichier_desc="" # chemin et nom du fichier contenant les # options de l'utilisateur list_messages=[] # liste d'erreur et de remarque list_messages_importants=[] list_messages_admin=[] # liste d'erreur réservé au administrateur erreur_critique=False # True si une erreur empêchant # l'impression est apparue code=None # code pour le digicode modif_epoch=0.0 # moment de création du job ou devis. exprimé # en epoch (float) : nombre de seconde depuis # la référence du temps unix (+-=1970) job_id=None # champs pour de futures améliorations def actualise_cout(self): # Calcul du cout de l'impression : retour = cout(self) # Met le prix dans cout s'il n'y a pas d'erreur if type(retour) is float : self.cout = retour self.list_messages_importants.append('cout') else: self.erreur_critique = True self.list_messages_importants.append('erreur_critique') self.list_messages_admin.append('erreur_cout') sys.stderr.write(retour) # Repond vrai si le solde est assez élevé. def test_cout(self): if self.user_ldap == None: self.user_ldap = utilisateur(self.user, False) return not (self.cout > (self.user_ldap.solde() - impression.decouvert)) # /!\ decouvert est négatif. def fait_payer(self): self.user_ldap = utilisateur(self.user,True) self.user_ldap.solde(-self.cout) self.user_ldap.save() return not (self.cout > (self.user_ldap.solde() - impression.decouvert)) def gen_code(self): # Génération du code et écriture du code rand=random.Random() # Graine automatique avec le temps rand.seed() for i in range(1000): # On génère un code code = rand.randint(100000,999999) # Si le code est libre, on sort de la boucle if not os.path.exists("/var/impression/codes/%d" % code): break else: # Pas de code disponible print ("ERROR: Il n'y a pas de code disponible" ) sys.stderr.write ("ERROR: Il n'y a pas de code disponible" ) try: self.list_messages_importants.append('erreur gen_code') 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") return # On enregistre le fichier avec le code pour numéro codefichier = open("/var/impression/codes/%d" % code, 'w') codefichier.write("Utilisateur %s\n" % self.user_ldap.Nom()) codefichier.close() self.code=code self.list_messages_importants.append('code') def impression(self): # Envoi du fichier à CUPS # Création de la liste d'options # pour le nombre de copies options ='-# %d' % self.nb_copie # Pour spécifier l'imprimante options +=' -P laserjet' # Pour spécifier la version du language postscript utilisé par pdftops options +=' -o pdf-level3' # Pour donner le titre de l'impression options +=' -T %s' % self.nom_job # Pour donner le login de l'adherent options +=' -U %s' % self.user # Pour demander une page de garde options +=' -o job-sheets=crans' #page de garde de type standard if self.transparent : options += ' -o InputSlot=Tray1 -o Media=Transparency' if self.taille == 'A4': options += ' -o pdf-paper=571x817 -o PageSize=A4' else: options += ' -o pdf-paper=825x1166 -o InputSlot=Tray3 -o HPPaperPolicy=A3 -o PageSize=A3' if self.portrait: if self.recto_verso: options += ' -o sides=two-sided-long-edge' else: options += ' -o sides=one-sided' else: options += ' -o landscape' if self.recto_verso: options += ' -o sides=two-sided-short-edge' else: options += ' -o sides=one-sided' options += ' -o HPColorasGray=%s' % (not self.couleur) (status,rep) = commands.getstatusoutput("lpr %s %s" % (options, self.nom_fichier_pdf)) if status != 0: print "
status:%d rep: %s
" % (status, rep) def corrige(self): # Trouve le nombre de pages self.nbr_pages = int(os.popen("pdfinfo %s | grep Pages " % (self.nom_fichier_pdf)).readline().split()[1]) # Corrige les aberrations # Correction des aberations (transparent et recto_verso :) ) # Priorité des informations par ordre décroissant # Transparent, paper, nbr_page, recto_verso if (self.taille != 'A4') & (self.taille != 'A3'): self.list_messages_importants.append("paper") self.erreur_critique=True if self.transparent: if self.paper != 'A4': self.list_messages.append("A3 transparent") self.paper = 'A4' if self.recto_verso: self.list_messages.append("Recto_verso transparent") self.recto_verso = False if self.nbr_pages == 1 and self.recto_verso: self.list_messages.append("Recto_verso 1 page") self.recto_verso = False def affiche_messages_html(self): body="" """if self.imprime: body=string.join(map ((dico_message_laserjet.get),self.list_messages_importants)) if len(self.list_messages)<>0: body=body+'\nRemarques:\n'+string.join(map ((dico_message_laserjet.get),self.list_messages)) else: body=string.join(map ((dico_message_devis.get),self.list_messages_importants)) body=body+'\nRemarque:\n'+string.join(map ((dico_message_devis.get),self.list_messages)) body=body % {'taille' : self.taille, 'code' : self.code, 'solde' : self.user_ldap.solde(), 'cout' : self.cout , 'adresse_imprimante' : impression.From_imprimante} """ body=string.join(self.list_messages_importants) return "%s
" % body def enregistre_pdf(self,f_value,f_nom,dossier): f_nom = f_nom.translate(string.maketrans(string.punctuation + string.whitespace, '_' * len(string.punctuation+string.whitespace))) (fd_fichier_desc, self.nom_fichier_desc) = tempfile.mkstemp(suffix='.desc', prefix=f_nom, dir=dossier) os.close(fd_fichier_desc) os.chmod(self.nom_fichier_desc, 33184) self.nom_fichier_pdf = "%s.pdf" % self.nom_fichier_desc[0:-5] file_obj_pdf = open(self.nom_fichier_pdf, 'w') file_obj_pdf.write(f_value) file_obj_pdf.close() self.nbr_pages = int(os.popen("pdfinfo '%s' | grep Pages " % (self.nom_fichier_pdf)).readline().split()[1]) self.modif_epoch = time.time() def sauve_desc(self): file_obj_desc = open(self.nom_fichier_desc,'w') for key in ("erreur_critique", "nom_job", "nbr_pages", "nb_copie","taille", "recto_verso", "transparent", "couleur", "cout", "portrait", "user", "imprime", "nom_fichier_pdf", "nom_fichier_desc", "code", "modif_epoch", "job_id"): file_obj_desc.write(key+"="+str(getattr(self,key))+"\n") file_obj_desc.close() def read_desc(self): file_obj_desc = open(self.nom_fichier_desc, 'r') ligne = file_obj_desc.readline()[0:-1] while ligne != "": parse = ligne.split("=") if parse[1] == 'None': setattr(self,parse[0],None) else: if parse[0] in ("nom_job", "taille", "user", "nom_fichier_pdf", "nom_fichier_desc", "job_id"): setattr(self,parse[0],parse[1]) else: if parse[0] in ("nbr_pages", "nb_copie", "imprime", "code"): setattr(self,parse[0],int(parse[1])) else: if parse[0] in ("recto_verso", "transparent", "couleur", "portrait", "erreur_critique"): setattr(self,parse[0],(parse[1] == 'True')) else: if parse[0] in ("cout", "modif_epoch"): setattr(self, parse[0], float(parse[1])) else: self.erreur_critique = True print 'ligne non parsée: %s
' % ligne ligne=file_obj_desc.readline()[0:-1] file_obj_desc.close() # Vérifie que le fichier existe bien si il doit exister. if not os.path.exists(self.nom_fichier_pdf): if self.imprime != -3: self.imprime = -4 # Fonction utilisé par print et str : renvoie le string canonique de l'objet def __repr__(self): dict_contraire = { 'couleur' : 'Noir et Blanc', 'transparent' : 'Normal', 'portrait': 'Paysage', 'recto_verso' : 'Recto', 'erreur_critique' : "Pas d'erreur" } dict_normale = { 'couleur' : 'Couleur', 'transparent' : 'Transparent', 'portrait': 'Portrait', 'recto_verso' : 'Recto-Verso', 'erreur_critique' : "Problême survenue" } corps = "%s | %s | |||||
---|---|---|---|---|---|---|
\n
| \n\n
| " if self.erreur_critique: corps += "erreur de comptage" else: corps += "%s euros" % self.cout corps+=" |