Scripts pour l'impression
Mis a jour par rapport a ceux de sila darcs-hash:20050519200607-c3cc4-4f4b1e259da0b201ec9a97a68b89b1f57e2fd940.gz
This commit is contained in:
parent
1f625fede3
commit
fc6003e7ae
3 changed files with 445 additions and 0 deletions
289
impression/couts.py
Executable file
289
impression/couts.py
Executable file
|
@ -0,0 +1,289 @@
|
||||||
|
#!/usr/bin/env python
|
||||||
|
# -*- coding: iso-8859-15 -*-
|
||||||
|
|
||||||
|
# Utilisé par /usr/lib/cgi-bin/impression/analyse.py
|
||||||
|
# /usr/lib/cups/backend/devis et /usr/lib/cups/backend/laserjet
|
||||||
|
# Écrit par Benoit
|
||||||
|
# modifie par Brice DUBOST
|
||||||
|
|
||||||
|
import locale
|
||||||
|
locale.setlocale(locale.LC_ALL, 'fr_FR')
|
||||||
|
|
||||||
|
import os, commands
|
||||||
|
import string
|
||||||
|
import re
|
||||||
|
import sys
|
||||||
|
import tempfile
|
||||||
|
|
||||||
|
sys.path.append('/usr/scripts/gestion')
|
||||||
|
|
||||||
|
from config import impression
|
||||||
|
|
||||||
|
|
||||||
|
class cout:
|
||||||
|
"""Classe pour le calcul du cout d'une impression et de sa mise en page"""
|
||||||
|
#en centimes
|
||||||
|
c_total=0
|
||||||
|
#en euros
|
||||||
|
c_total_euros=0
|
||||||
|
total_noir=0
|
||||||
|
total_couleur=0
|
||||||
|
faces=1
|
||||||
|
pages=1
|
||||||
|
nb_copie=1
|
||||||
|
format="NON_VALIDE"
|
||||||
|
erreur=""
|
||||||
|
recto_v="None"
|
||||||
|
|
||||||
|
def __init__(self,fichierps, mode_couleur, recto_v="None", format="A4", nb_copie=1, media="" ):
|
||||||
|
""" * fichierps est le fichier PostScript (ou pdf) à analyser
|
||||||
|
* mode_couleur = Couleur pour traiter en couleur
|
||||||
|
* recto_v = Recto si l'on ne desire pas un recto-verso
|
||||||
|
* format vaut A3 ou A4 selon le bac choisi
|
||||||
|
* nb_copie est le nombre de copies désirées
|
||||||
|
* media vaut transparent le cas écheant (dans ce cas format=A4)
|
||||||
|
Le PostScript a toujours priorité sur ces parametres
|
||||||
|
"""
|
||||||
|
|
||||||
|
self.nb_copie=nb_copie
|
||||||
|
# on compte le nb de copies et on enlève les balises pour ne pas recalculer
|
||||||
|
nb_copie_ps=0
|
||||||
|
original=open(fichierps)
|
||||||
|
fichier='/tmp/couts_temp'
|
||||||
|
try:
|
||||||
|
fic = open(fichier,'w')
|
||||||
|
except:
|
||||||
|
os.remove(fichier)
|
||||||
|
fic = open(fichier,'w')
|
||||||
|
# fic = tempfile.NamedTemporaryFile()
|
||||||
|
ligne = original.readline()
|
||||||
|
while ligne:
|
||||||
|
if ligne.startswith('%%BeginFeature: *PageSize'):
|
||||||
|
format=ligne.split(' ')[-1].replace('\n','')
|
||||||
|
if ligne.startswith('%%BeginFeature: *Duplex'):
|
||||||
|
recto_v=ligne.split(' ')[-1].replace('\n','')
|
||||||
|
if ligne.find('%RBIBeginNonPPDFeature: *NumCopies') != -1:
|
||||||
|
nb_copie_ps=int(ligne.split(' ')[-1])
|
||||||
|
while ligne.find('%RBIEndNonPPDFeature') == -1:
|
||||||
|
ligne = original.readline()
|
||||||
|
ligne = original.readline()
|
||||||
|
fic.write(ligne)
|
||||||
|
ligne = original.readline()
|
||||||
|
fic.close()
|
||||||
|
original.close()
|
||||||
|
|
||||||
|
# Le PS a priorité
|
||||||
|
if nb_copie_ps:
|
||||||
|
self.nb_copie=nb_copie_ps
|
||||||
|
|
||||||
|
if format=="A4" or format=="A3":
|
||||||
|
self.format=format
|
||||||
|
else: # format invalide
|
||||||
|
self.erreur="Format invalide"
|
||||||
|
return
|
||||||
|
|
||||||
|
if recto_v == "None" or recto_v == "Recto":
|
||||||
|
recto_v="Recto"
|
||||||
|
else:
|
||||||
|
recto_v="Recto-verso"
|
||||||
|
|
||||||
|
self.recto_v=recto_v
|
||||||
|
|
||||||
|
if (mode_couleur == "Couleur"):
|
||||||
|
device = "png16m"
|
||||||
|
else:
|
||||||
|
device = "pnggray"
|
||||||
|
|
||||||
|
if (self.format == "A3"):
|
||||||
|
# Une feuille A3 couvre 2 fois plus de surface que A4
|
||||||
|
c_format = 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 (media == "transparent"):
|
||||||
|
c_format = impression.c_trans
|
||||||
|
else:
|
||||||
|
c_format = impression.c_a4
|
||||||
|
|
||||||
|
# Conversion en PostScript si le fichier est un pdf
|
||||||
|
# pour pouvoir le decouper en petits bouts.
|
||||||
|
# Vérification du format de fichier.
|
||||||
|
try:
|
||||||
|
en_tete=open(fichier).read(4)
|
||||||
|
except:
|
||||||
|
self.erreur="Le fichier ne peut etre ouvert"
|
||||||
|
return
|
||||||
|
# On vérifie que ce que l'on nous a envoyé est bien un PS ou un PDF
|
||||||
|
if en_tete!='%!PS' and en_tete!='%PDF':
|
||||||
|
self.erreur="ERREUR : Format non supporte !!"
|
||||||
|
return
|
||||||
|
|
||||||
|
(status,rep) = commands.getstatusoutput("nice -n 10 gs -sDEVICE=%s -r100 -dBATCH -dNOPAUSE -dSAFER -dPARANOIDSAFER -dGraphicsAlphaBits=4 -dTextAlphaBits=4 -dMaxBitmap=50000000 -sOutputFile='%s' -q '%s'" % (device, fichier+"%d.png", fichier) )
|
||||||
|
if (status != 0):
|
||||||
|
self.erreur="ERREUR : Ghostscript : Fichier Postscript invalide.\n"
|
||||||
|
self.erreur+= rep
|
||||||
|
# On détaille l'erreur dans le mail et
|
||||||
|
# il faut stopper l'impression.
|
||||||
|
return
|
||||||
|
|
||||||
|
# On a plus besoin du fichier temp, donc on le supprime.
|
||||||
|
os.remove(fichier)
|
||||||
|
|
||||||
|
if not os.system("ls '%s'*.png > /dev/null" % (fichier)):
|
||||||
|
if (mode_couleur == "Couleur"):
|
||||||
|
remplissage = [0, 0, 0, 0, 0] # C, M, J, N, nombre de pages
|
||||||
|
for file in string.split(commands.getoutput("ls '%s'*.png" % (fichier)),"\n"):
|
||||||
|
resultats = commands.getoutput("/usr/scripts/impression/percentcolour '%s'" % (file) )
|
||||||
|
l_resultats = string.split(resultats,":")
|
||||||
|
for i in [0, 1, 2, 3]:
|
||||||
|
remplissage[i] += float(l_resultats[i])*float(l_resultats[4])
|
||||||
|
remplissage[4] += float(l_resultats[4])
|
||||||
|
os.system("rm -f '%s'" % (file))
|
||||||
|
self.total_noir = remplissage[3]
|
||||||
|
self.total_couleur = sum(remplissage[0:3])
|
||||||
|
self.faces = remplissage[4]
|
||||||
|
if (recto_v == "Recto"):
|
||||||
|
self.pages = self.faces # nb de pages par copies
|
||||||
|
else:
|
||||||
|
self.pages = int(self.faces/2.+0.5)
|
||||||
|
self.c_total = c_format*self.pages+(impression.c_tambour_coul+impression.c_tambour_noir)*self.faces+cout_noir*self.total_noir+cout_coul*self.total_couleur
|
||||||
|
else:
|
||||||
|
remplissage = [0, 0] # Noir, nombre de pages
|
||||||
|
for file in string.split(commands.getoutput("ls '%s'*.png" % (fichier)),"\n"):
|
||||||
|
resultats = commands.getoutput("/usr/scripts/impression/percentblack '%s'" % (file))
|
||||||
|
l_resultats = string.split(resultats,":")
|
||||||
|
remplissage[0] += float(l_resultats[0])*float(l_resultats[1])
|
||||||
|
remplissage[1] += float(l_resultats[1])
|
||||||
|
os.system("rm -f '%s'" % (file))
|
||||||
|
self.total_noir = remplissage[0]
|
||||||
|
self.faces = remplissage[1]
|
||||||
|
if (recto_v == "Recto"):
|
||||||
|
self.pages = self.faces # nb de pages par copies
|
||||||
|
else:
|
||||||
|
self.pages = int(self.faces/2.+0.5)
|
||||||
|
self.c_total = c_format*self.pages+impression.c_tambour_noir*self.faces+cout_noir*self.total_noir
|
||||||
|
self.c_total = int(self.nb_copie*self.c_total+impression.fact+0.5) # arrondi et facture
|
||||||
|
self.c_total_euros=float(self.c_total)/100
|
||||||
|
os.system("rm -f '%s'*.png" %(fichier))
|
||||||
|
else:
|
||||||
|
self.erreur=u"ERREUR : Fichier Postscript invalide. aucun png a été créé\n"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
def remplis_template(self,template):
|
||||||
|
"""Cette fonction rempli le template avec les bonnes valeurs"""
|
||||||
|
if (self.c_total < 100):
|
||||||
|
str_cout = "%s centimes d'euros" % (self.c_total)
|
||||||
|
else :
|
||||||
|
str_cout = "%s euros" % (self.c_total/100.)
|
||||||
|
|
||||||
|
if self.format=="NON_VALIDE":
|
||||||
|
format=u"Le format de papier que vous avez demandé n'est pas valide"
|
||||||
|
else:
|
||||||
|
format=self.format
|
||||||
|
try:
|
||||||
|
return template % { 'prix' : str_cout }
|
||||||
|
except:
|
||||||
|
return template % { 'noir' : "%2.2f" % (self.total_noir/self.faces), 'couleur' : "%2.2f" % (self.total_couleur/self.faces), 'faces' :int(self.faces), 'pages' : int(self.pages), 'copies' : self.nb_copie, 'format' : format, 'prix' : str_cout}
|
||||||
|
|
||||||
|
|
||||||
|
def html_cout(self):
|
||||||
|
"""Renvoie le cout formaté en html"""
|
||||||
|
# Format du PS (parfois different de celui choisi)
|
||||||
|
# Utile pour deboguage, sera supprime apres
|
||||||
|
template = """<h2>Résultats : </h2>
|
||||||
|
<ul><li><b>Format de l'impression</b> : %(format)s </li>
|
||||||
|
<li><b>Noir (par copie)</b> : %(noir)s%% </li>
|
||||||
|
<li><b>Couleur (par copie)</b> : %(couleur)s%% </li>
|
||||||
|
<li><b>Nombre de faces (par copie)</b> : %(faces)s </li>
|
||||||
|
<li><b>Nombre de pages (par copie)</b> : %(pages)s </li>
|
||||||
|
<li><b>Nombre de copies</b> : %(copies)s</li></ul><br>
|
||||||
|
<br><b>Prix total : %(prix)s </b>
|
||||||
|
</p>\n<p>
|
||||||
|
</p>\n"""
|
||||||
|
|
||||||
|
|
||||||
|
if not self.erreur:
|
||||||
|
return self.remplis_template(template)
|
||||||
|
else:
|
||||||
|
return self.erreur
|
||||||
|
|
||||||
|
|
||||||
|
def send_mail(self, Dest , sujet, template):
|
||||||
|
"""Cette fonction envoie le mail template correctement rempli
|
||||||
|
provenant de l'imprimante avec comme serveur
|
||||||
|
SMTP localhost
|
||||||
|
Arguments :
|
||||||
|
Dest : destinataire
|
||||||
|
sujet : sujet du mail
|
||||||
|
template : le corps du mail
|
||||||
|
Pour le remplissage du template voir source pour le moment"""
|
||||||
|
|
||||||
|
if not self.erreur:
|
||||||
|
mail=self.remplis_template(template)
|
||||||
|
else:
|
||||||
|
sujet="Erreur " + sujet
|
||||||
|
mail=self.erreur + "\n\n-- \nL'imprimante\n"
|
||||||
|
|
||||||
|
#l'envoi
|
||||||
|
self.send_email("Imprimante <%(From)s>" % { 'From' : impression.From_imprimante}, Dest , sujet, mail)
|
||||||
|
|
||||||
|
|
||||||
|
def send_email(self, sender, recipient, subject, body):
|
||||||
|
"""Send an email.
|
||||||
|
|
||||||
|
All arguments should be Unicode strings (plain ASCII works as well).
|
||||||
|
|
||||||
|
Only the real name part of sender and recipient addresses may contain
|
||||||
|
non-ASCII characters.
|
||||||
|
|
||||||
|
The email will be properly MIME encoded and delivered though SMTP to
|
||||||
|
localhost port 25. This is easy to change if you want something different.
|
||||||
|
|
||||||
|
The charset of the email will be the first one out of US-ASCII, ISO-8859-1
|
||||||
|
and UTF-8 that can represent all the characters occurring in the email.
|
||||||
|
"""
|
||||||
|
from smtplib import SMTP
|
||||||
|
from email.MIMEText import MIMEText
|
||||||
|
from email.Header import Header
|
||||||
|
from email.Utils import parseaddr, formataddr
|
||||||
|
|
||||||
|
# Header class is smart enough to try US-ASCII, then the charset we
|
||||||
|
# provide, then fall back to UTF-8.
|
||||||
|
header_charset = 'ISO-8859-1'
|
||||||
|
|
||||||
|
# We must choose the body charset manually
|
||||||
|
for body_charset in 'US-ASCII', 'ISO-8859-1', 'UTF-8':
|
||||||
|
try:
|
||||||
|
body.encode(body_charset)
|
||||||
|
except UnicodeError:
|
||||||
|
pass
|
||||||
|
else:
|
||||||
|
break
|
||||||
|
|
||||||
|
# Split real name (which is optional) and email address parts
|
||||||
|
sender_name, sender_addr = parseaddr(sender)
|
||||||
|
recipient_name, recipient_addr = parseaddr(recipient)
|
||||||
|
|
||||||
|
# We must always pass Unicode strings to Header, otherwise it will
|
||||||
|
# use RFC 2047 encoding even on plain ASCII strings.
|
||||||
|
sender_name = str(Header(unicode(sender_name), header_charset))
|
||||||
|
recipient_name = str(Header(unicode(recipient_name), header_charset))
|
||||||
|
|
||||||
|
# Make sure email addresses do not contain non-ASCII characters
|
||||||
|
sender_addr = sender_addr.encode('ascii')
|
||||||
|
recipient_addr = recipient_addr.encode('ascii')
|
||||||
|
|
||||||
|
# Create the message ('plain' stands for Content-Type: text/plain)
|
||||||
|
msg = MIMEText(body.encode(body_charset), 'plain', body_charset)
|
||||||
|
msg['From'] = formataddr((sender_name, sender_addr))
|
||||||
|
msg['To'] = formataddr((recipient_name, recipient_addr))
|
||||||
|
msg['Subject'] = Header(unicode(subject), header_charset)
|
||||||
|
|
||||||
|
# Send the message via SMTP to localhost:25
|
||||||
|
smtp = SMTP("localhost")
|
||||||
|
smtp.sendmail(sender, recipient, msg.as_string())
|
||||||
|
smtp.quit()
|
||||||
|
|
117
impression/pjl_comm.py
Executable file
117
impression/pjl_comm.py
Executable file
|
@ -0,0 +1,117 @@
|
||||||
|
#!/usr/bin/env python
|
||||||
|
# -*- coding: iso-8859-15 -*-
|
||||||
|
|
||||||
|
"""Classe de communication avec l'imprimante
|
||||||
|
HP9500"""
|
||||||
|
|
||||||
|
import socket
|
||||||
|
|
||||||
|
class hp9500:
|
||||||
|
"Classe de communication avec la HP9500"
|
||||||
|
#\x1B est le caractere d'échappement échap.
|
||||||
|
UEL="\x1b%-12345X"
|
||||||
|
__douille=None
|
||||||
|
def __init__(self,hostname="laserjet.adm.crans.org",port=9100):
|
||||||
|
"""Appelle à l'initalisation
|
||||||
|
hostname : nom d'hôte de l'imprimante
|
||||||
|
port : le port de communication avec l'imprimante
|
||||||
|
"""
|
||||||
|
self.hostname=hostname
|
||||||
|
self.port=port
|
||||||
|
|
||||||
|
def cx_open(self):
|
||||||
|
"""Ouvre la connexion vers l'imprimante"""
|
||||||
|
|
||||||
|
if not self.__douille:
|
||||||
|
self.__douille = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
||||||
|
self.__douille.connect((self.hostname, self.port))
|
||||||
|
#delai d'attente pour la réception des données
|
||||||
|
self.__douille.settimeout(10)
|
||||||
|
self.__douille.send(self.UEL+"@PJL\n")
|
||||||
|
|
||||||
|
def cx_close(self):
|
||||||
|
"""Ferme la connexion vers l'imprimante"""
|
||||||
|
|
||||||
|
if self.__douille:
|
||||||
|
self.__douille.send(self.UEL+"\n")
|
||||||
|
self.__douille.close()
|
||||||
|
self.__douille=None
|
||||||
|
|
||||||
|
def pjl_command(self,command):
|
||||||
|
"""Cette fonction envoie la commande command à l'imprimante
|
||||||
|
Elle doit être une commande pjl sans @PJL devant
|
||||||
|
|
||||||
|
Paramètres :
|
||||||
|
command : la commande à envoyer à l'imprimante
|
||||||
|
|
||||||
|
"""
|
||||||
|
|
||||||
|
if not self.__douille:
|
||||||
|
self.cx_open()
|
||||||
|
|
||||||
|
command=str(command)
|
||||||
|
command="@PJL " + command + "\n"
|
||||||
|
self.__douille.send(command)
|
||||||
|
|
||||||
|
#debug
|
||||||
|
print command
|
||||||
|
|
||||||
|
def pjl_read(self, display=0):
|
||||||
|
"""Cette fonction lit le retour donné par l'imprimante
|
||||||
|
Elle retourne un message commençant par \"ERREUR :\" en
|
||||||
|
cas d'échec
|
||||||
|
Elle affiche le message si la variable display est vraie
|
||||||
|
"""
|
||||||
|
|
||||||
|
if not self.__douille:
|
||||||
|
return "ERREUR : la connexion vers l'imprimante n'est pas ouverte"
|
||||||
|
message=""
|
||||||
|
caract=' '
|
||||||
|
while caract:
|
||||||
|
try:
|
||||||
|
caract=self.__douille.recv(1)
|
||||||
|
message+=caract
|
||||||
|
except:
|
||||||
|
caract=''
|
||||||
|
message+='\n'
|
||||||
|
if display:
|
||||||
|
print message
|
||||||
|
return message
|
||||||
|
|
||||||
|
def write_file(self,filename):
|
||||||
|
"""Cette fonction envoie un fichier à l'imprimante.
|
||||||
|
Elle est utile pour envoyer une série de commande ou un fichier
|
||||||
|
postscript.
|
||||||
|
|
||||||
|
Arguments :
|
||||||
|
filename : nom du fichier à envoyer
|
||||||
|
"""
|
||||||
|
|
||||||
|
if not self.__douille:
|
||||||
|
return "ERREUR : la connexion vers l'imprimante n'est pas ouverte"
|
||||||
|
|
||||||
|
fichier=open(filename)
|
||||||
|
self.__douille.sendall(fichier.read())
|
||||||
|
fichier.close()
|
||||||
|
|
||||||
|
def write_postscript(self,filename, name, display):
|
||||||
|
"""Cette fonction envoie un fichier postscript à l'imprimante.
|
||||||
|
Elle envoie avant le ENTER LANGUAGE et le EOJ a la fin.
|
||||||
|
|
||||||
|
Arguments :
|
||||||
|
filename : nom du fichier à envoyer
|
||||||
|
name : le nom du job
|
||||||
|
display : ce qu'on met sur l'afficheur
|
||||||
|
"""
|
||||||
|
if not self.__douille:
|
||||||
|
return "ERREUR : la connexion vers l'imprimante n'est pas ouverte"
|
||||||
|
self.pjl_command('JOB DISPLAY=\"%s\" NAME=\"%s\"' % (display,name))
|
||||||
|
self.pjl_command('ENTER LANGUAGE = POSTSCRIPT ')
|
||||||
|
self.write_file(filename)
|
||||||
|
self.__douille.send(self.UEL+"@PJL EOJ NAME=\"%s\"\n" % (name))
|
||||||
|
|
||||||
|
|
||||||
|
def __del__(self):
|
||||||
|
"""Destructeur : ferme la connexion"""
|
||||||
|
self.cx_close()
|
||||||
|
|
39
radius_digicode.py
Executable file
39
radius_digicode.py
Executable file
|
@ -0,0 +1,39 @@
|
||||||
|
#! /usr/bin/env python
|
||||||
|
# -*- coding: iso-8859-15 -*-
|
||||||
|
|
||||||
|
"""
|
||||||
|
Script de test du code de la porte du local de l'imprimante
|
||||||
|
"""
|
||||||
|
|
||||||
|
import os,sys
|
||||||
|
|
||||||
|
def identification ( password ) :
|
||||||
|
# test un code entré sur la porte :
|
||||||
|
# doit retourner 0 si le code n'est pas bon
|
||||||
|
# 1 pour ouvrir la porte
|
||||||
|
|
||||||
|
#codes en statique pour les tests
|
||||||
|
#Dans l'avenir tout sera sous forme de fichiers
|
||||||
|
#si le fichier existe le code est bon (evite les problemes par rapport au fait de
|
||||||
|
# stocker les codes dans un fichier
|
||||||
|
if (password in ['123456','23']) or (password in os.listdir('/var/impression/codes')):
|
||||||
|
if password in os.listdir('/var/impression/codes'):
|
||||||
|
os.remove("/var/impression/codes/%s" %password)
|
||||||
|
return 1
|
||||||
|
else :
|
||||||
|
return 0
|
||||||
|
|
||||||
|
if __name__ == '__main__' :
|
||||||
|
# on récupère le code dans les variables d'environement
|
||||||
|
try :
|
||||||
|
code = os.getenv('USER_PASSWORD','').replace('"','')
|
||||||
|
except :
|
||||||
|
code = ''
|
||||||
|
|
||||||
|
# test de l'authentification
|
||||||
|
if identification(code) :
|
||||||
|
# c'est bon
|
||||||
|
sys.exit(0)
|
||||||
|
else :
|
||||||
|
# c'est pas bon
|
||||||
|
sys.exit(1)
|
Loading…
Add table
Add a link
Reference in a new issue