diff --git a/impression/couts.py b/impression/couts.py new file mode 100755 index 00000000..ef721988 --- /dev/null +++ b/impression/couts.py @@ -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 = """
+
\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() + diff --git a/impression/pjl_comm.py b/impression/pjl_comm.py new file mode 100755 index 00000000..5f3a1771 --- /dev/null +++ b/impression/pjl_comm.py @@ -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() + diff --git a/radius_digicode.py b/radius_digicode.py new file mode 100755 index 00000000..f233e13a --- /dev/null +++ b/radius_digicode.py @@ -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)