
Ceci dit, je ne vois pas pourquoi on ne se dbarasse pas du nom original dans sa totalit. Car avec cette mthode, on ne neutralise pas entirement le nom. Pourquoi ne pas simplement garder le rsultat de mkstemp comme nom de fichier ? darcs-hash:20060127085813-d1718-46c8257721915b7e0df16a13513f5351ac0e2272.gz
426 lines
19 KiB
Python
Executable file
426 lines
19 KiB
Python
Executable file
#! /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
|
|
sys.path.append('/usr/scripts/impression')
|
|
sys.path.append('/usr/scripts/gestion')
|
|
from config import impression
|
|
#sys.path.append('/localhome/bobot/scripts/gestion')
|
|
from ldap_crans import crans_ldap
|
|
#import vraicouts
|
|
|
|
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 #seras 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 futur amélioration
|
|
|
|
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)
|
|
#self.user_ldap = test()
|
|
return not (self.cout > (self.user_ldap.solde() - impression.decouvert)) #!impression.decouvert est négatif.
|
|
|
|
def fait_payer(self):
|
|
self.user_ldap = utilisateur(self.user,True)
|
|
#self.user_ldap = test()
|
|
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
|
|
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 verifie que le code n'est déja pas utilisé
|
|
try:
|
|
open("/var/impression/codes/%d" %code, 'r')
|
|
#open("/home/bobot/tmp/codes/%d" %code, 'r')
|
|
except :
|
|
break
|
|
i=i+1
|
|
|
|
if code:
|
|
#on enregistre le fichier avec le code pour numéro
|
|
codefichier=open("/var/impression/codes/%d" %code, 'w')
|
|
#codefichier=open("/localhome/bobot/codes/%d" %code, 'w')
|
|
codefichier.write("Utilisateur %s\n"%(self.user_ldap.Nom()))
|
|
codefichier.close()
|
|
self.code=code
|
|
self.list_messages_importants.append('code')
|
|
else :
|
|
# Grosse erreur : on logue, on previent et on stoppe.
|
|
print ("ERROR: Il n'y a pas de code disponible" )
|
|
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"})
|
|
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")
|
|
#sys.exit(1)
|
|
|
|
def impression(self):
|
|
# Envoi du fichier à CUPS
|
|
|
|
#Création de la liste d'options
|
|
#pour le nombre de copies
|
|
options ='-# '+str(self.nb_copie)
|
|
#options ='-n '+str(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 '+self.nom_job
|
|
#options +=' -t '+self.nom_job
|
|
|
|
#pour donner le login de l'adherent
|
|
options +=' -U '+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='+str(not self.couleur)
|
|
(status,rep) = commands.getstatusoutput("lpr %s %s" %(options,self.nom_fichier_pdf))
|
|
if status<>0:
|
|
print "<p>status:"+str(status)+" rep:"+rep+"</p>"
|
|
#else:
|
|
#self.job_id=rep.split(' ')[3]
|
|
|
|
def corrige (self):
|
|
#
|
|
# fic_impr=fichier_impression()
|
|
# fic_impr.user=utilisateur(arguments[2],rw)
|
|
#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 & 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 "<p>"+body+"</p>"
|
|
|
|
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=self.nom_fichier_desc[0:-5]+".pdf"
|
|
#(,self.nom_fichier_pdf) = tempfile.mkstemp(suffix='.pdf',prefix=identifiant+f_nom,dir=data_dir+identifiant)
|
|
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 '<p>ligne non parser:'+ligne+'</p>'
|
|
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.access(self.nom_fichier_pdf,os.F_OK):
|
|
if self.imprime<>-3:
|
|
self.imprime=-4
|
|
#else:
|
|
# if (time.time()-self.modif_epoch)>duree_vie_pdf:
|
|
# os.remove(self.nom_fichier_pdf)
|
|
# 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"}
|
|
#dict_imprime={-4: 'PDF indisponible', -3: 'Envoyé', -2 : 'En suspend', -1 : "En cours d'envoi", 0 : "Devis"}
|
|
#corps="<TABLE BORDER=0 CELLPADDDING=2>\n<TR><th ALIGN=CENTER COLSPAN=2><U>"+self.nom_job+"</U></th><td ALIGN=RIGHT>"+time.ctime(self.modif_epoch)+"</TR>\n"
|
|
corps="<TABLE BORDER=0 CELLPADDDING=2>\n<TR><th ALIGN=CENTER COLSPAN=2><U>"+self.nom_job+"</U></th><td ALIGN=RIGHT>"+time.ctime(0.0)+"</TR>\n"
|
|
corps+="<TR><td>\n<TABLE BORDER=2 RULES=ROWS CELLPADDDING=0>\n"
|
|
#if self.imprime>0:
|
|
# t=time.localtime(self.imprime)
|
|
# date="le %i à %i:%i" % t[2:4]
|
|
#else:
|
|
# date=dict_imprime[self.imprime]
|
|
#corps+="<TR><td>Impression</td><td>"+date+"</td></TR>\n"
|
|
for key in ("nbr_pages","nb_copie","taille","code"):
|
|
corps+='<TR><td>'+key+"</td><td>"+str(getattr(self,key))+"</td></TR>\n"
|
|
corps+="</TABLE>\n</td>\n<td>\n<TABLE BORDER=2 RULES=ROWS CELLPADDDING=0>\n"
|
|
for key in ("couleur","transparent","portrait","recto_verso"):
|
|
if getattr(self,key):
|
|
corps+='<TR><td>'+dict_normale[key]+"</td></TR>\n"
|
|
else:
|
|
corps+='<TR><td>'+dict_contraire[key]+"</td></TR>\n"
|
|
corps+="</TABLE>\n</td><td><U>"
|
|
if self.erreur_critique:
|
|
corps+="erreur de comptage"
|
|
else:
|
|
corps+=str(self.cout)+"euros"
|
|
corps+="</U></td></TR>\n</TABLE>"
|
|
#if self.job_id<>None:
|
|
# corps+="Le travaille à été imprimé sous le nom : "+self.job_id+"<BR/>
|
|
return corps
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def utilisateur(user, rw):
|
|
""" Renvoie l'adherent qui imprime le job
|
|
* user est l'utilisateur (argument n°2 des paramètres passés au backend)
|
|
* rw vaut True si on veut modifier le compte LDAP de l'adhérent,
|
|
False dans le cas contraire
|
|
"""
|
|
|
|
# Impression en local avec les certificats (possible pour le groupe adm)
|
|
if user=="root":
|
|
sys.stderr.write("ERROR: Utilisateur root passé en paramètre.\n")
|
|
sys.exit(0) # On conclue l'impression
|
|
|
|
# Récupération de l'adhérent
|
|
try:
|
|
base = crans_ldap()
|
|
if rw:
|
|
res=base.search("login=%s"%user,'w')['adherent']
|
|
else:
|
|
res=base.search("login=%s"%user)['adherent']
|
|
except:
|
|
print ("ERROR: Erreur : Base LDAP non joignable\n")
|
|
sys.exit(0) # On arrete l'avant-impression ?on arrete l'imprimante?
|
|
|
|
# Si on ne trouve rien :
|
|
if len(res) != 1 :
|
|
print ("ERROR: Erreur : adhérent %s non trouvé\n" % user)
|
|
sys.exit(0) # On conclue l'avant-impression sans stopper l'imprimante
|
|
|
|
adherent = res[0]
|
|
sys.stderr.write("DEBUG: Adherent %s recupere.\n" % adherent.Nom())
|
|
return adherent
|
|
|
|
#fonction cout calcule le pourcentage de couleur sur les pages
|
|
# renvoit un string avec le nom de l'erreur si erreur il y a
|
|
#renvoit un float dans les cas de fonctionnement...
|
|
|
|
def cout( fic_impr):
|
|
#taille peut valoir A3 ou A4
|
|
#nb_copie est le nombre de copies désirées
|
|
|
|
#nom_rep seras le dossier dans tmp ou tous les fichier créé par convert seront entreposé
|
|
nom_rep=tempfile.mkdtemp(prefix='tmpimpr')
|
|
nom_png=nom_rep + "/convert.png" #nom prefixe et chemin des png créé par convert
|
|
|
|
if (fic_impr.taille == "A3"):
|
|
# Une feuille A3 couvre 2 fois plus de surface que A4
|
|
c_taille = impression.c_a3
|
|
cout_coul = 2*impression.c_coul
|
|
cout_noir = 2*impression.c_noir
|
|
else:
|
|
cout_coul = impression.c_coul
|
|
cout_noir = impression.c_noir
|
|
if fic_impr.transparent:
|
|
c_taille = impression.c_trans
|
|
else:
|
|
c_taille = impression.c_a4
|
|
|
|
if (fic_impr.couleur):
|
|
#convertit les pdf en png couleur
|
|
#(status,rep) = commands.getstatusoutput("nice -n 5 convert %s %s" % (fic_impr.nom_fichier_pdf,nom_png))
|
|
(status,rep) = commands.getstatusoutput("nice -n 5 gs -sDEVICE=png16m -r30 -dBATCH -dNOPAUSE -dSAFER -dPARANOIDSAFER -dGraphicsAlphaBits=4 -dTextAlphaBits=4 -dMaxBitmap=50000000 -sOutputFile=%s -q %s" % (nom_png,fic_impr.nom_fichier_pdf))
|
|
if status:
|
|
return "ERREUR : Fichier invalide. Aucun png n'a été créé.\n"
|
|
|
|
#récupère la liste des fichiers
|
|
list_filepng=os.listdir(nom_rep)
|
|
#calcule le nombre de pixel de couleur
|
|
remplissage = [0, 0, 0, 0, 0] # C, M, J, N, nombre de pages
|
|
for fichier in list_filepng:
|
|
resultats = commands.getoutput("nice -n 5 /usr/scripts/impression/percentcolour %s" % (nom_rep+'/'+fichier))
|
|
#resultats = '2.103:3.363:4.131:29.300:1'
|
|
l_resultats = resultats.split(":")
|
|
for i in [0, 1, 2, 3]:
|
|
remplissage[i] += float(l_resultats[i])*float(l_resultats[4])
|
|
remplissage[4] += float(l_resultats[4])
|
|
total_noir = remplissage[3]
|
|
total_couleur = sum(remplissage[0:3])
|
|
faces = int(remplissage[4])
|
|
if (fic_impr.recto_verso == False):
|
|
pages = faces # nb de pages par copies
|
|
else:
|
|
pages = int(faces/2.+0.5)
|
|
if total_couleur > 0:
|
|
c_total = c_taille*pages+(impression.c_tambour_coul+impression.c_tambour_noir)*faces+cout_noir*total_noir+cout_coul*total_couleur
|
|
else: # Pas de couleur, malgre l'indication
|
|
c_total = c_taille*pages+impression.c_tambour_noir*faces+cout_noir*total_noir
|
|
else:
|
|
#convertit les pdf en png
|
|
#(status,rep) = commands.getstatusoutput("nice -n 5 convert -colorspace GRAY %s %s" % (fic_impr.nom_fichier_pdf,nom_png))
|
|
(status,rep) = commands.getstatusoutput("nice -n 5 gs -sDEVICE=pnggray -r30 -dBATCH -dNOPAUSE -dSAFER -dPARANOIDSAFER -dGraphicsAlphaBits=4 -dTextAlphaBits=4 -dMaxBitmap=50000000 -sOutputFile=%s -q %s" % (nom_png,fic_impr.nom_fichier_pdf))
|
|
if status:
|
|
return "ERREUR : Fichier invalide. Aucun png n'a été créé.\n"
|
|
|
|
#récupère la liste des fichiers
|
|
list_filepng=os.listdir(nom_rep)
|
|
|
|
remplissage = [0, 0] # Noir, nombre de pages
|
|
for fichier in list_filepng:
|
|
#resultats = commands.getoutput("/home/bobot/crans/impression/percentblack '%s'" % (nomrep+'/'+fichier))
|
|
resultats = commands.getoutput("nice -n 5 /usr/scripts/impression/percentblack '%s'" % (nom_rep+'/'+fichier) )
|
|
#resultats = '2.103:3.363:4.131:29.300:1'
|
|
l_resultats = resultats.split(":")
|
|
remplissage[0] += float(l_resultats[0])*float(l_resultats[1])
|
|
remplissage[1] += float(l_resultats[1])
|
|
total_noir = remplissage[0]
|
|
faces = int(remplissage[1])
|
|
if (fic_impr.recto_verso == False):
|
|
pages = faces # nb de pages par copies
|
|
else:
|
|
pages = int(faces/2.+0.5)
|
|
c_total = c_taille*pages+impression.c_tambour_noir*faces+cout_noir*total_noir
|
|
|
|
c_total = int(fic_impr.nb_copie*c_total+impression.fact+0.5) # arrondi et facture
|
|
|
|
if commands.getoutput("rm -r -f " + nom_rep):
|
|
self.list_messages_admin.append('erreur_cout')
|
|
sys.stderr.write("ERREUR : Impossible d'enlever le dossier.\n")
|
|
|
|
return float(c_total)/100
|
|
|
|
|
|
|
|
|
|
|