[impression] menage

This commit is contained in:
Daniel STAN 2013-03-19 02:27:06 +01:00
parent 7af07b09a8
commit 452be81693
10 changed files with 449 additions and 0 deletions

View file

@ -0,0 +1,51 @@
#!/usr/bin/env python
# -*- encoding: iso8859-15 -*-
#
# bourrages.py : récupération des fichiers de logs de bourrage l'imprimante.
#
# Stocke les logs de l'imprimante au fur et à mesure
#
# Copyright (c) 2008 Nicolas Dandrimont <Nicolas.Dandrimont@crans.org>
#
import urllib
import sys
import re
nom_fichier_log = "/var/log/bourrages.log"
URL = "https://laserjet.adm.crans.org/hp/device/this.LCDispatcher?dispatch=html&cat=0&pos=3"
span_rex = re.compile(r'<span[^>]+class="hpPageText"[^>]*>(?P<contenu>[^<]+)</span>', re.IGNORECASE)
try:
f = open(nom_fichier_log)
except:
sys.stderr.write("Erreur d'ouverture du fichier de logs en lecture...\n")
lastpage = 0
else:
lastpage = f.readlines()[-1].strip().split()[0]
f.close()
try:
lignesimpr = urllib.urlopen(URL).readlines()
except:
sys.stderr.write("Problème de lecture de la page d'impression...\n")
else:
lignes_recup = [span_rex.match(ligne).group("contenu") for ligne in lignesimpr if span_rex.match(ligne)]
premier_indice = lignes_recup.index('Num\xe9ro') + 4
erreurs = []
for i in xrange(premier_indice, len(lignes_recup), 4):
erreurs.append(tuple(lignes_recup[i+1:i+4]))
try:
fichier_log = open(nom_fichier_log, 'a')
except:
sys.stderr.write("Erreur d'ouverture du fichier de logs en écriture...\n")
else:
for erreur in reversed(erreurs):
if erreur[0] > lastpage:
fichier_log.write("%s %s %s\n" % erreur)
fichier_log.close()

View file

@ -0,0 +1,14 @@
#!/bin/sh
# Rend les pdf compatibles avec Ghostscript
exec >/dev/null 2>/dev/null
if head -n 1 $1 | egrep -q "1.[45]"; then
cd `dirname $1`
FICHIER_PDF=`basename $1`
FICHIER_PS=${FICHIER_PDF%.pdf}.ps
pdftops $FICHIER_PDF
ps2pdf $FICHIER_PS $FICHIER_PDF
rm -f $FICHIER_PS
fi

View file

@ -0,0 +1,189 @@
#!/usr/bin/env python
# -*- coding: iso-8859-15 -*-
# Fonctions utilisées par les backend devis et laserjet
# Écrit par Benoit avec la contribution de Brice et Fred
# Licence : GNU General Public Licence, version 2
import sys, tempfile
import couts
sys.path.append('/usr/scripts/gestion')
from ldap_crans import crans_ldap
def preliminaires(arguments, description):
""" Verifie le nombre d'arguments passes.
Si pas d'arguments : print description,
si le bon nombre d'argument : retourne le fichier nettoye,
sinon sort sans stopper.
"""
# \x1B est le caractere d'échappement échap.
UEL="\x1B%-12345X"
if len(arguments) == 1 :
print description
sys.exit(0)
if len(arguments) not in (6, 7) :
sys.stderr.write("ERROR: %s job-id user title copies options [file]\n" % arguments[0])
sys.exit(0) # On n'arrête pas l'imprimante
if arguments[-1].find('/') != -1 :
try:
# Fichier fourni
entree = open(arguments[-1])
except:
# Des fois les options contiennent un / ...
entree = sys.stdin
else :
# Lecture sur entrée standard
entree = sys.stdin
## On nettoie le fichier :
fic = tempfile.NamedTemporaryFile()
ligne = entree.readline()
# On enlève les options qui nous gènent et on rend le fichier propre
while ligne:
# On ne choisit pas le bac de sortie
if ligne.find('%%BeginFeature: *OutputBin') != -1:
while ligne.find('%%EndFeature') == -1:
ligne = entree.readline()
ligne = entree.readline()
# On ne choisit pas le bac d'entree sauf si transparent
if ligne.find('%%BeginFeature: *InputSlot') != -1:
if ligne.find('Transparency') == -1:
while ligne.find('%%EndFeature') == -1:
ligne = entree.readline()
ligne = entree.readline()
# On élimine les instructions PJL
# Normalement on n'est pas obligé de retirer le UEL
# mais c'est plus propre
while ligne.startswith('@PJL') or ligne.startswith(UEL):
ligne = entree.readline()
fic.write(ligne)
ligne = entree.readline()
fic.flush()
return fic
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 1 si on veut modifier le compte LDAP de l'adhérent,
0 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 == 0 :
res=base.search("login=%s"%user)['adherent']
else:
res=base.search("login=%s"%user,'w')['adherent']
except:
sys.stderr.write("ERROR: Erreur : Base LDAP non joignable\n")
sys.exit(0) # On arrete l'impression
# Si on ne trouve rien :
if len(res) != 1 :
sys.stderr.write("ERROR: Erreur : adhérent %s non trouvé\n" % user)
sys.exit(0) # On conclue l'impression sans stopper l'imprimante
adherent = res[0]
sys.stderr.write("DEBUG: Adherent %s recupere.\n" % adherent.Nom())
return adherent
def calcul_prix(nom_fic):
"""Calcul le prix du fichier nom_fic"""
## #Temporaire pour debugage
## fs=open(nom_fic,'r')
## fd=open('/tmp/benoit_Routard','w')
## while 1:
## txt=fs.readline()
## if txt == '':
## break
## fd.write(txt)
## fs.close()
## fd.close()
# Calcul du cout de l'impression :
try:
prix = couts.cout(nom_fic)
except:
sys.stderr.write("ERROR: Erreur : Impossible de calculer le couts de %s." % nom_fic)
sys.exit(1) # On arrete l'imprimante
if prix.erreur == "Taille invalide":
sys.stderr.write("ERROR: Erreur de taille de papier (%s).\n" % prix.taille)
elif prix.erreur:
sys.stderr.write("ERROR: Erreur du calcul du prix : %s.\n" % prix.erreur)
else:
sys.stderr.write("DEBUG: Prix calcule : %s euros (%s, %s).\n" % (prix.c_total_euros, prix.taille, prix.recto_v) )
return prix
def send_email(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()

View file

@ -0,0 +1,525 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# #############################################################
# ..
# .... ............ ........
# . ....... . .... ..
# . ... .. .. .. .. ..... . ..
# .. .. ....@@@. .. . ........ .
# .. . .. ..@.@@..@@. .@@@@@@@ @@@@@@. ....
# .@@@@. .@@@@. .@@@@..@@.@@..@@@..@@@..@@@@.... ....
# @@@@... .@@@.. @@ @@ .@..@@..@@...@@@. .@@@@@. ..
# .@@@.. . @@@. @@.@@..@@.@@..@@@ @@ .@@@@@@.. .....
# ...@@@.... @@@ .@@.......... ........ ..... ..
# . ..@@@@.. . .@@@@. .. ....... . .............
# . .. .... .. .. . ... ....
# . . .... ............. .. ...
# .. .. ... ........ ... ...
# ................................
#
# #############################################################
# __init__.py
#
# Classe impression
#
# Copyright (c) 2006 by www.crans.org
# #############################################################
"""
Classe pour gérer l'envoie de pdf à l'imprimante.
Calcule le coût des options d'impression.
"""
__version__ = '1'
import sys, syslog, os.path
sys.path.append('/usr/scripts/gestion')
import config
import cout
from crans.utils import QuoteForPOSIX as escapeForShell
import crans.utils.logs
log = crans.utils.logs.getFileLogger('impression')
# Début : Ajout log pour réestimer les coûts
import time
import hptools
comm = hptools.snmp(host="imprimante.adm.crans.org",version="1",community="public")
# Fin
# ######################################################## #
# CONSTANTES #
# ######################################################## #
#
#
# Début : Ajout log pour réestimer les coûts
FICHIER_LOG="/var/log/log_couts/impressions"
SNMP_CAR_B_PC="enterprises.11.2.3.9.4.2.1.4.1.10.1.1.18.1.0"
SNMP_CAR_C_PC="enterprises.11.2.3.9.4.2.1.4.1.10.1.1.18.2.0"
SNMP_CAR_M_PC="enterprises.11.2.3.9.4.2.1.4.1.10.1.1.18.3.0"
SNMP_CAR_Y_PC="enterprises.11.2.3.9.4.2.1.4.1.10.1.1.18.4.0"
SNMP_CAR_B_PR="enterprises.11.2.3.9.4.2.1.4.1.10.5.1.1.1.0"
SNMP_CAR_C_PR="enterprises.11.2.3.9.4.2.1.4.1.10.5.1.1.2.0"
SNMP_CAR_M_PR="enterprises.11.2.3.9.4.2.1.4.1.10.5.1.1.3.0"
SNMP_CAR_Y_PR="enterprises.11.2.3.9.4.2.1.4.1.10.5.1.1.4.0"
SNMP_TAM_B_PC="enterprises.11.2.3.9.4.2.1.4.1.10.1.1.37.5.0"
SNMP_TAM_C_PC="enterprises.11.2.3.9.4.2.1.4.1.10.1.1.37.6.0"
SNMP_TAM_M_PC="enterprises.11.2.3.9.4.2.1.4.1.10.1.1.37.7.0"
SNMP_TAM_Y_PC="enterprises.11.2.3.9.4.2.1.4.1.10.1.1.37.8.0"
SNMP_TAM_B_PR="enterprises.11.2.3.9.4.2.1.4.1.10.5.1.1.5.0"
SNMP_TAM_C_PR="enterprises.11.2.3.9.4.2.1.4.1.10.5.1.1.6.0"
SNMP_TAM_M_PR="enterprises.11.2.3.9.4.2.1.4.1.10.5.1.1.7.0"
SNMP_TAM_Y_PR="enterprises.11.2.3.9.4.2.1.4.1.10.5.1.1.8.0"
# Fin
DECOUVERT_AUTHORISE = config.impression.decouvert
PAS_D_AGRAPHES = "pasdagraphes"
AGRAPHE_DIAGONALE = "agraphediagonale"
UNE_AGRAPHE = "uneagraphe"
DEUX_AGRAPHE = "Deuxagraphes"
TROIS_AGRAPHE = "troisAgraphes"
STITCHING = "stitching"
AGRAPHES_VALEURS_POSSIBLES = [PAS_D_AGRAPHES, AGRAPHE_DIAGONALE, UNE_AGRAPHE, DEUX_AGRAPHE, TROIS_AGRAPHE, STITCHING]
NB_AGRAPHES = {
PAS_D_AGRAPHES: 0,
AGRAPHE_DIAGONALE: 1,
UNE_AGRAPHE: 1,
DEUX_AGRAPHE: 2,
TROIS_AGRAPHE: 3,
STITCHING: 6,
}
PAPIER_A4 = "A4"
PAPIER_A4_TRANSPARENT = "A4tr"
PAPIER_A3 = "A3"
PAPIER_VALEURS_POSSIBLES = [PAPIER_A4, PAPIER_A4_TRANSPARENT]
IMPRESSION_COULEUR = "couleurs"
IMPRESSION_NB = "nb"
COULEURS_VALEURS_POSSIBLES = [IMPRESSION_COULEUR, IMPRESSION_NB]
IMPRESSION_RECTO = "recto"
IMPRESSION_RECTO_VERSO = "rectoverso"
IMPRESSION_RECTO_VERSO_SHORT = "rectoversoshort"
DISPOSITION_VALEURS_POSSIBLES = [IMPRESSION_RECTO, IMPRESSION_RECTO_VERSO, IMPRESSION_RECTO_VERSO_SHORT]
PU_AGRAPHE = config.impression.c_agrafe / 100.
PU_FEUILLE = {
PAPIER_A4: config.impression.c_a4/100,
PAPIER_A4_TRANSPARENT: config.impression.c_trans/100,
PAPIER_A3: config.impression.c_a3/1000,
}
LABELS = {
PAS_D_AGRAPHES: "pas d'agrafe",
AGRAPHE_DIAGONALE: 'une agrafe en diagonale',
UNE_AGRAPHE: 'une agrafe en haut',
DEUX_AGRAPHE: '2 agrafes',
TROIS_AGRAPHE: '3 agrafes',
STITCHING: 'stitching (6 agrafes)',
PAPIER_A4: "A4",
PAPIER_A4_TRANSPARENT: "A4 transparent",
PAPIER_A3: "A3",
IMPRESSION_COULEUR: "impression couleurs",
IMPRESSION_NB: "impression noir et blanc",
IMPRESSION_RECTO: "impression recto",
IMPRESSION_RECTO_VERSO: "impression recto-verso",
IMPRESSION_RECTO_VERSO_SHORT: "impression recto-verso",
}
LPR_OPTIONS = {
PAS_D_AGRAPHES: ' -o StapleLocation=None',
AGRAPHE_DIAGONALE: ' -o StapleLocation=1diagonal',
UNE_AGRAPHE: ' -o StapleLocation=1parallel',
DEUX_AGRAPHE: ' -o StapleLocation=2parallel',
TROIS_AGRAPHE: ' -o StapleLocation=3parallel',
STITCHING: ' -o StapleLocation=Stitching',
PAPIER_A4: ' -o InputSlot=Tray4 -o pdf-paper=571x817 -o PageSize=A4',
PAPIER_A4_TRANSPARENT: ' -o PageSize=A4 -o InputSlot=Tray1 -o Media=Transparency',
PAPIER_A3: ' -o pdf-expand -o pdf-paper=825x1166 -o InputSlot=Tray3 -o HPPaperPolicy=A3 -o PageSize=A3',
IMPRESSION_COULEUR: ' -o HPColorasGray=False',
IMPRESSION_NB: ' -o HPColorasGray=True',
IMPRESSION_RECTO: ' -o sides=one-sided',
IMPRESSION_RECTO_VERSO: ' -o sides=two-sided-long-edge',
IMPRESSION_RECTO_VERSO_SHORT: ' -o sides=two-sided-short-edge',
}
# ######################################################## #
# ERREURS #
# ######################################################## #
#
class FichierInvalide(Exception):
"""
Exception renvoyée lorsqu'un fichier ne passe pas.
utilisée avec deux arguments : une chaîne décrivant l'erreur et une chaîne avec le nom du fichier
"""
def __str__(self):
"""
Description de l'erreur.
"""
return self.args[0]
def file(self):
"""
Nom du fichier qui pose problème
"""
try:
return self.args[1]
except:
return "n/a"
class SoldeInsuffisant(Exception):
"""
Solde insuffisant pour l'impression demandée
"""
pass
class PrintError(Exception):
"""
Erreur lors de l'impression
"""
pass
class SettingsError(Exception):
"""
Erreur de paramètres.
"""
pass
# ######################################################## #
# CLASSE IMPRESSION #
# ######################################################## #
#
#
class impression:
"""impression
Un objet impression correspond à un fichier pdf et un adhérent.
"""
# fichier (chemin)
_fichier = ""
# adherent (instance)
_adh = None
# paramettres
_settings = {
'agraphes': PAS_D_AGRAPHES,
'papier': PAPIER_A4,
'couleurs': IMPRESSION_COULEUR,
'recto_verso': IMPRESSION_RECTO_VERSO,
'copies':1,
}
# le prix de l'impression
_prix = 0.0
_nb_pages = 0
_details_devis = []
# le cout de base encre pour une impression en couleurs/n&b
# (prix pour papier A4)
_base_prix_nb = 0.0
_base_prix_couleurs = 0.0
def __init__(self, path_to_pdf, adh = None):
"""impression(path_to_pdf [, adh])
Crée un nouvel objet impression à partir du fichier pdf pointé
par path_to_pdf. Si adh ext donné, il peut être soit une
instance d'un objet adhérent de crans_ldap soit le login de
l'adhérent. Lève l'exception FichierInvalide si le fichier
n'existe pas ou si ce n'est pas un pdf.
"""
self._fichier = path_to_pdf
# on verifie que le fichier existe
if not os.path.isfile(path_to_pdf):
raise FichierInvalide, ("Fichier introuvable", path_to_pdf)
if not open(path_to_pdf).read().startswith("%PDF"):
raise FichierInvalide, ("Le fichier ne semble pas etre un PDF", path_to_pdf)
self._adh = adh
# calcule le prix de l'encre tout de suite
try:
self._base_prix_couleurs, self._nb_pages = cout.base_prix_couleurs(path_to_pdf)
self._base_prix_nb, self._nb_pages = cout.base_prix_nb(path_to_pdf)
except ValueError, e:
raise FichierInvalide, ("PDF bugge, Analyse impossible : %s." % e, path_to_pdf)
except Exception, e:
raise Exception, "Erreur dans le calcul du cout : %s " % str(e)
self._calcule_prix()
def changeSettings(self, agraphes = None, papier = None, couleurs = None, recto_verso=None, copies=None):
"""changeSettings([keyword=value])
Change les parametres de l'impression, recalcule et renvoie le nouveau prix.
Lève une exceotion SettingError si les paramètres son invalides.
"""
#recalcule et renvoie le prix
if (couleurs):
if couleurs not in COULEURS_VALEURS_POSSIBLES:
raise SettingsError, "Valeur de couleurs inconnue : %s" % str(couleurs)
self._settings['couleurs'] = couleurs
if (papier):
if papier not in PAPIER_VALEURS_POSSIBLES:
raise SettingsError, "Valeur de papier inconnue : %s" % str(papier)
self._settings['papier'] = papier
if (copies):
try:
int(copies)
if int(copies) <1:
raise Exception
except:
raise SettingsError, "Valeur incorecte pour le nombre de copies"
self._settings['copies'] = copies
if (recto_verso):
if recto_verso not in DISPOSITION_VALEURS_POSSIBLES:
raise SettingsError, "Valeur inconnue : %s" % str(recto_verso)
if papier==PAPIER_A4_TRANSPARENT and (recto_verso==IMPRESSION_RECTO_VERSO or recto_verso==IMPRESSION_RECTO_VERSO_SHORT):
raise SettingsError, "Pas de recto-verso sur du papier transparent !!"
self._settings['recto_verso'] = recto_verso
if (agraphes):
if agraphes not in AGRAPHES_VALEURS_POSSIBLES:
raise SettingsError, "Valeur inconnue pour agrafes : %s" % str(agrafes)
if papier!=PAPIER_A4 and agraphes!=PAS_D_AGRAPHES:
raise SettingsError, "Le type de papier choisi ne permet pas d'utiliser l'agrafeuse"
if recto_verso==IMPRESSION_RECTO_VERSO or recto_verso==IMPRESSION_RECTO_VERSO_SHORT:
if self._nb_pages > 100 and agraphes!=PAS_D_AGRAPHES:
raise SettingsError, "Le document est trop volumineux pour utiliser l'agrafeuse"
else:
if self._nb_pages > 50 and agraphes!=PAS_D_AGRAPHES:
raise SettingsError, "Le document est trop volumineux pour utiliser l'agrafeuse"
self._settings['agraphes'] = agraphes
return self._calcule_prix()
def printSettings(self):
"""printSettings()
Affiche les paramètres courrants sur la sortie standard
"""
print "Type impression: " + LABELS[self._settings['couleurs']]
print "Agraphes: " + LABELS[self._settings['agraphes']]
print "Papier: " + LABELS[self._settings['papier']]
print "Disposition: " + LABELS[self._settings['recto_verso']]
print "Copies: " + str(self._settings['copies'])
def prix(self):
"""prix()
Renvoie le prix courrant de l'impression
"""
return self._prix
def fileName(self):
"""fileName()
renvoie le nom du fichier pdf (exemple : monPdf.pdf)
"""
return os.path.basename(self._fichier)
def filePath(self):
"""filePath()
renvoie le chemin d'accs au fichier pdf.
"""
return self._fichier
def devisDetaille(self):
"""devisDetaille()
renvoie un disctionnaire contenant le devis (intitulé, PU., quantité) pour tous les éléments de l'impression
(papier, encre, agrafes...)
"""
return self._details_devis
def pages(self):
"""pages()
renvoie le nombre de pages du document (page au sens nombre de faces à imprimer et non le nombre de feuilles)
"""
return self._nb_pages
def imprime(self):
"""imprime()
imprime le document pdf. débite l'adhérent si adhérent il y a.
(si il a été indiqué à l'initialisation de l'objet)
"""
# debite l'adhérent si adherent il y a
if (self._adh != None):
adh = self._get_adh(self._adh)
if (self._prix > (adh.solde() - DECOUVERT_AUTHORISE)):
raise SoldeInsuffisant
adh.solde(-self._prix, "impression: " + self._fichier)
adh.save()
del adh
# imprime le document
self._exec_imprime()
def printDevis(self):
"""printDevis()
Affiche le devis sur la sortie standard.
"""
print "titre \t\t | p.u. \t quandtite \t total"
for anItem in self._details_devis:
print anItem[0][:5] + "\t\t | " + str(anItem[1]) + "\t\t | " + str(anItem[2]) + "\t\t | " + str(anItem[1]*anItem[2])
def _calcule_prix(self):
prix = 0
facture = []
# clacul du prix total pour l'encre
if (self._settings['couleurs'] == IMPRESSION_COULEUR):
base_prix_encre = self._base_prix_couleurs
else:
base_prix_encre = self._base_prix_nb
if (self._settings['papier'] == PAPIER_A3):
pu_encre = base_prix_encre * 2
else:
pu_encre = base_prix_encre
facture.append((
LABELS[self._settings['couleurs']] + ' sur papier ' + LABELS[self._settings['papier']],
pu_encre, self._settings['copies']))
prix+= self._settings['copies'] * pu_encre
#calcul du prix des feuilles
if (self._settings['recto_verso'] == IMPRESSION_RECTO_VERSO) or (self._settings['recto_verso'] == IMPRESSION_RECTO_VERSO_SHORT):
nbfeuilles = int(self._nb_pages/2.+0.5) * self._settings['copies']
else:
nbfeuilles = self._nb_pages * self._settings['copies']
facture.append((
'feuilles ' + LABELS[self._settings['papier']],
PU_FEUILLE[self._settings['papier']],
nbfeuilles))
prix+= PU_FEUILLE[self._settings['papier']] * nbfeuilles
# calcul prix des Agraphes
facture.append((
'agrafes',
PU_AGRAPHE,
NB_AGRAPHES[self._settings['agraphes']] * self._settings['copies']))
prix+= NB_AGRAPHES[self._settings['agraphes']] * self._settings['copies'] * PU_AGRAPHE
# arrondit
prix = int((prix*100) + 0.5)/100.
self._prix = prix
self._details_devis = facture
return prix
def _get_adh(self, adh):
if type(adh) == str:
import sys
sys.path.append("/usr/scripts/gestion/")
#from ldap_crans_test import crans_ldap
from ldap_crans import CransLdap
adh = CransLdap().getProprio(adh, 'w')
return adh
## ################################# ##
## fonction qui imprime pour de vrai ##
## ################################# ##
##
def _exec_imprime(self):
""" Envoie l'impression a l'imprimante avec les parametres actuels """
if (self._adh != None):
log.info('Impression [%s] : %s' % (self._adh, self._fichier))
else:
log.info("Impression : %s" % self._fichier)
# Envoi du fichier a CUPS
options =''
# Creation de la liste d'options
# pour le nombre de copies et specifie non assemblee
#options += '-# %d -o Collate=True' % self.nb_copies
# Pour specifier l'imprimante
options += ' -P laserjet'
#Indique la presence d'un bac de sortie avec agrafeuse
options += " -o Option20=MBMStaplerStacker -o OutputBin=StackerStapled"
# Pour specifier la version du language postscript utilise par pdftops
options += ' -o pdf-level3'
# Pour donner le titre de l'impression
options += " -T '%s'" % self._fichier
# Pour donner le login de l'adherent
if (self._adh != None):
options += ' -U %s' % self._adh
# Pour demander une page de garde
#options += ' -o job-sheets=crans' #page de garde de type standard
#options += " -o job-billing=%.2f" % self.cout
#options += ' -o job-sheets=none'
# option agrafes
options += LPR_OPTIONS[self._settings['agraphes']]
# option papier
options += LPR_OPTIONS[self._settings['papier']]
# option disposition
options += LPR_OPTIONS[self._settings['recto_verso']]
# options couleurs
options += LPR_OPTIONS[self._settings['couleurs']]
# Début : Ajout log pour réestimer les coûts
# Commandes snmp recuperation des etats
val_car_b_pc=int(comm.get(SNMP_CAR_B_PC))
val_car_c_pc=int(comm.get(SNMP_CAR_C_PC))
val_car_m_pc=int(comm.get(SNMP_CAR_M_PC))
val_car_y_pc=int(comm.get(SNMP_CAR_Y_PC))
val_car_b_pr=int(comm.get(SNMP_CAR_B_PR))
val_car_c_pr=int(comm.get(SNMP_CAR_C_PR))
val_car_m_pr=int(comm.get(SNMP_CAR_M_PR))
val_car_y_pr=int(comm.get(SNMP_CAR_Y_PR))
val_tam_b_pc=int(comm.get(SNMP_TAM_B_PC))
val_tam_c_pc=int(comm.get(SNMP_TAM_C_PC))
val_tam_m_pc=int(comm.get(SNMP_TAM_M_PC))
val_tam_y_pc=int(comm.get(SNMP_TAM_Y_PC))
val_tam_b_pr=int(comm.get(SNMP_TAM_B_PR))
val_tam_c_pr=int(comm.get(SNMP_TAM_C_PR))
val_tam_m_pr=int(comm.get(SNMP_TAM_M_PR))
val_tam_y_pr=int(comm.get(SNMP_TAM_Y_PR))
fichier_log_imp=open(FICHIER_LOG,"a")
fichier_log_imp.write("%d %3d %2s : %3d %3d %3d %3d : %5d %5d %5d %5d : %3d %3d %3d %3d : %5d %5d %5d %5d : %s\n" %
(time.time(),self._settings['copies'],self._settings['papier'],
val_car_b_pc,
val_car_c_pc,
val_car_m_pc,
val_car_y_pc,
val_car_b_pr,
val_car_c_pr,
val_car_m_pr,
val_car_y_pr,
val_tam_b_pc,
val_tam_c_pc,
Val_tam_m_pc,
val_tam_y_pc,
val_tam_b_pr,
val_tam_c_pr,
val_tam_m_pr,
val_tam_y_pr,
self._fichier) )
fichier_log_imp.close()
# Fin
liste_nom_fichier_pdf=(' '+escapeForShell( self._fichier ) )*self._settings['copies']
import commands
#(status,rep) = commands.getstatusoutput("lpr %s %s" % (options, self.nom_fichier_pdf))
(status,rep) = commands.getstatusoutput("lpr %s %s" % (options, liste_nom_fichier_pdf))
if status != 0:
log.error("erreur impression")
log.error("lpr status:%d | rep: %s" % (status, rep))
raise PrintError, "lpr %s %s \n status:%d rep: %s" % (options, liste_nom_fichier_pdf, status, rep)

View file

@ -0,0 +1,70 @@
import crans.impression
import crans.impression.digicode
import crans.ldap_crans_test
import os, sys
# ######################################################## #
# COMMAND LINE OPTION #
# ######################################################## #
#
#
OPTIONS_AGRAFES = {
0: crans.impression.PAS_D_AGRAPHES,
-1: crans.impression.AGRAPHE_DIAGONALE,
1: crans.impression.UNE_AGRAPHE,
2: crans.impression.DEUX_AGRAPHE,
3: crans.impression.TROIS_AGRAPHE,
6: crans.impression.STITCHING,
}
OPTIONS_NOIRETBLANC = {
False: crans.impression.IMPRESSION_COULEUR,
True: crans.impression.IMPRESSION_NB
}
OPTIONS_RECTOVERSO = {
False: crans.impression.IMPRESSION_RECTO,
True: crans.impression.IMPRESSION_RECTO_VERSO
}
from optparse import OptionParser
parser = OptionParser("usage: %prog [options] pdf")
parser.add_option("-a", "--agrafes",
action="store", type='int', dest="agrafes", default=0,
help="Choix du mode d'agrafes (%s)" % ", ".join(["%s: %s" % (val, crans.impression.LABELS[OPTIONS_AGRAFES[val]]) for val in OPTIONS_AGRAFES.keys()]))
parser.add_option("-p", "--papier",
action="store", type="string", dest="typepapier",
help="Choix papier (%s)" % ", ".join(["%s: %s" % (val, crans.impression.LABELS[val]) for val in crans.impression.PAPIER_VALEURS_POSSIBLES]))
parser.add_option("-r", "--recto-verso",
action="store_true", dest="rectoverso", default=False,
help="Impression recto-verso")
parser.add_option("-c", "--copies",
action="store", type="int", dest="copies",
help="Nombre de copies")
parser.add_option("-n", "--noir-et-blanc",
action="store_true", dest="noiretblanc", default=False,
help="impression en noir et blanc")
(options, args) = parser.parse_args()
if len(args) != 1:
parser.error("Nombre d'arguments incorect")
PDF_PATH = os.path.join(os.getcwd(), args[0])
USER_LOGIN = os.getlogin()
print("Analyse du fichier...")
lpr = crans.impression.impression(PDF_PATH, USER_LOGIN)
try:
lpr.changeSettings(agraphes=OPTIONS_AGRAFES[options.agrafes],
papier=options.typepapier,
couleurs=OPTIONS_NOIRETBLANC[options.noiretblanc],
recto_verso = OPTIONS_RECTOVERSO[options.rectoverso],
copies=options.copies )
except crans.impression.SettingsError, e:
print "erreur: %s" % e
sys.exit(1)
lpr.printSettings()
print "Prix total : %s Euros" % str(lpr.prix())

186
archive/impression_old/ipp.py Executable file
View file

@ -0,0 +1,186 @@
#! /usr/bin/env python
# -*- coding: ISO-8859-15 -*-
#
# PyKota - Print Quotas for CUPS and LPRng
#
# (c) 2003-2004 Jerome Alet <alet@librelogiciel.com>
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
#
# $Id: ipp.py,v 1.2 2004/12/03 20:29:33 jalet Exp $
#
# $Log: ipp.py,v $
# Revision 1.2 2004/12/03 20:29:33 jalet
# ipp.py can now be run in standalone mode for testing purposes
#
# Revision 1.1 2004/11/06 22:35:58 jalet
# Added a miniparser for IPP messages (RFC 2910). The job-originating-host-name
# retrieval is now fiable, unless the CUPS developpers change something...
#
#
import sys
from struct import unpack
OPERATION_ATTRIBUTES_TAG = 0x01
JOB_ATTRIBUTES_TAG = 0x02
END_OF_ATTRIBUTES_TAG = 0x03
PRINTER_ATTRIBUTES_TAG = 0x04
UNSUPPORTED_ATTRIBUTES_TAG = 0x05
class PyKotaIPPError(Exception):
"""An exception for PyKota IPP related stuff."""
def __init__(self, message = ""):
self.message = message
Exception.__init__(self, message)
def __repr__(self):
return self.message
__str__ = __repr__
class IPPMessage :
"""A class for IPP message files."""
def __init__(self, data) :
"""Initializes an IPP Message object."""
self.data = data
self._attributes = {}
self.curname = None
self.tags = [ None ] * 256 # by default all tags reserved
# Delimiter tags
self.tags[0x01] = "operation-attributes-tag"
self.tags[0x02] = "job-attributes-tag"
self.tags[0x03] = "end-of-attributes-tag"
self.tags[0x04] = "printer-attributes-tag"
self.tags[0x05] = "unsupported-attributes-tag"
# out of band values
self.tags[0x10] = "unsupported"
self.tags[0x11] = "reserved-for-future-default"
self.tags[0x12] = "unknown"
self.tags[0x13] = "no-value"
# integer values
self.tags[0x20] = "generic-integer"
self.tags[0x21] = "integer"
self.tags[0x22] = "boolean"
self.tags[0x23] = "enum"
# octetString
self.tags[0x30] = "octetString-with-an-unspecified-format"
self.tags[0x31] = "dateTime"
self.tags[0x32] = "resolution"
self.tags[0x33] = "rangeOfInteger"
self.tags[0x34] = "reserved-for-collection"
self.tags[0x35] = "textWithLanguage"
self.tags[0x36] = "nameWithLanguage"
# character strings
self.tags[0x20] = "generic-character-string"
self.tags[0x41] = "textWithoutLanguage"
self.tags[0x42] = "nameWithoutLanguage"
# self.tags[0x43] = "reserved"
self.tags[0x44] = "keyword"
self.tags[0x45] = "uri"
self.tags[0x46] = "uriScheme"
self.tags[0x47] = "charset"
self.tags[0x48] = "naturalLanguage"
self.tags[0x49] = "mimeMediaType"
# now parses the IPP message
self.parse()
def __getattr__(self, attrname) :
"""Allows self.attributes to return the attributes names."""
if attrname == "attributes" :
keys = self._attributes.keys()
keys.sort()
return keys
raise AttributeError, attrname
def __getitem__(self, ippattrname) :
"""Fakes a dictionnary d['key'] notation."""
value = self._attributes.get(ippattrname)
if value is not None :
if len(value) == 1 :
value = value[0]
return value
get = __getitem__
def parseTag(self) :
"""Extracts information from an IPP tag."""
pos = self.position
valuetag = self.tags[ord(self.data[pos])]
# print valuetag.get("name")
pos += 1
posend = pos2 = pos + 2
namelength = unpack(">H", self.data[pos:pos2])[0]
if not namelength :
name = self.curname
else :
posend += namelength
self.curname = name = self.data[pos2:posend]
pos2 = posend + 2
valuelength = unpack(">H", self.data[posend:pos2])[0]
posend = pos2 + valuelength
value = self.data[pos2:posend]
oldval = self._attributes.setdefault(name, [])
oldval.append(value)
return posend - self.position
def operation_attributes_tag(self) :
"""Indicates that the parser enters into an operation-attributes-tag group."""
return self.parseTag()
def job_attributes_tag(self) :
"""Indicates that the parser enters into an operation-attributes-tag group."""
return self.parseTag()
def printer_attributes_tag(self) :
"""Indicates that the parser enters into an operation-attributes-tag group."""
return self.parseTag()
def parse(self) :
"""Parses an IPP Message.
NB : Only a subset of RFC2910 is implemented.
We are only interested in textual informations for now anyway.
"""
self.version = "%s.%s" % (ord(self.data[0]), ord(self.data[1]))
self.operation_id = "0x%04x" % unpack(">H", self.data[2:4])[0]
self.request_id = "0x%08x" % unpack(">I", self.data[4:8])[0]
self.position = 8
try :
tag = ord(self.data[self.position])
while tag != END_OF_ATTRIBUTES_TAG :
self.position += 1
name = self.tags[tag]
if name is not None :
func = getattr(self, name.replace("-", "_"), None)
if func is not None :
self.position += func()
if ord(self.data[self.position]) > UNSUPPORTED_ATTRIBUTES_TAG :
self.position -= 1
continue
tag = ord(self.data[self.position])
except IndexError :
raise PyKotaIPPError, "Unexpected end of IPP message."
if __name__ == "__main__" :
if len(sys.argv) < 2 :
print "usage : python ipp.py /var/spool/cups/c00005 (for example)\n"
else :
infile = open(sys.argv[1])
message = IPPMessage(infile.read())
infile.close()
print "Client user name : %s" % message["job-originating-user-name"]

View file

@ -0,0 +1,48 @@
#! /usr/bin/env python
# -*- coding: iso-8859-15 -*-
# Script de suppression des pdfs trop vieux et des descriptions perverties.
# Codé par Francois
# Licence : GNU General Public Licence, version 2
import os,sys,time
sys.path.append('/usr/script/impression')
import class_impression
#espérance de vie d'un pdf en seconde
duree_vie_pdf=3600
#répertoire racine des dossier d'impression
data_dir='/var/spool/impression/'
def suppr_vieux_pdf(arg,dir_name,list_file):
#print dir_name+':\n'
list_desc=filter(lambda x : (x.endswith('.desc')),list_file)
if list_desc<>[]:
#Ouverture des descriptions et suppression du pdf si nécessaire
for nom_fichier_desc in list_desc:
fic_impr=class_impression.fichier_impression()
fic_impr.nom_fichier_desc=os.path.join(dir_name,nom_fichier_desc)
fic_impr.read_desc()
if fic_impr.nom_fichier_pdf=='':
print '\t'+fic_impr.nom_fichier_pdf+' supprimé et\n'
print '\t'+fic_impr.nom_fichier_desc+' supprimé car nom_fichier_pdf inconnue\n'
os.remove(fic_impr.nom_fichier_desc)
elif fic_impr.modif_epoch==None:
print '\t'+fic_impr.nom_fichier_pdf+' supprimé et\n'
print '\t'+fic_impr.nom_fichier_desc+' supprimé car modif_epoch inconnue\n'
os.remove(fic_impr.nom_fichier_pdf)
os.remove(fic_impr.nom_fichier_desc)
elif (time.time()-fic_impr.modif_epoch)>duree_vie_pdf and os.access(fic_impr.nom_fichier_pdf,os.F_OK):
os.remove(fic_impr.nom_fichier_pdf)
#print '\t'+fic_impr.nom_fichier_pdf+" supprimé\n"
fic_impr.imprime=-4
fic_impr.sauve_desc()
def main():
#print 'Suppression des descriptions perverties'
#print 'Suppression des fichiers pdf vieux de plus de '+str(duree_vie_pdf)+'s'
os.path.walk(data_dir,suppr_vieux_pdf,None)
main()

View file

@ -0,0 +1,162 @@
#!/usr/bin/perl -w
# pdftops.pl - wrapper script for xpdf's pdftops utility to act as a CUPS filter
# ==============================================================================
# 1.00 - 2004-10-05/Bl
# Initial implementation
#
# Copyright: Helge Blischke / SRZ Berlin 2004
# This program is free seoftware and governed by the GNU Public License Version 2.
#
# Description:
# ------------
# This program wraps the pdftops utility from the xpdf 3.00 (and higher) suite
# to behave as a CUPS filter as a replacement for the original pdftops filter.
#
# The main purpose of this approach is to keep the properties of a PDF to be
# printed as undesturbed as possible, especially with respect to page size,
# scaling, and positioning.
#
# The pdftops utility reads a configuration file 'pdftops.conf' in the
# CUPS_SERVERROOT directory, which must exist but may be empty. The sample
# configuration file accompanying this program sets the defaults which
# seem plausible to me with respect to high end production printers.
#
# To give the user highest possible flexibility, this program accepts and
# evaluates a set of job attributes special to this filter, which are
# described below:
#
# pdf-pages=<f>,<l>
# expands to the -f and -l options of pdftops
# to select a page range to process. This is independent
# of the page-ranges attribute and may significantly
# increase throughput when printing page ranges.
# Either of these numbers may be omitted.
#
# pdf-paper=<name>
# pdf-paper=<width>x<height>
# <name> may be one of letter, legal , A4, A3, or match;
# <width> and <height> are the paper width and height
# in printers points (1/72 inch). This expands to
# either the -paper or the -paperh and -paperw options
# of pdftops
#
# pdf-opw=<password>
# pdf-upw=<password>
# expand to the -opw and -upw options of pdftops,
# respectively and permit printing of password
# protected PDFs.
#
# pdf-<option> where <option> is one of
# level1, level1sep, level2, level2sep, level3, level3sep,
# opi, nocrop, expand, noshrink, nocenter.
# See the pdftops manpage for a detailed description of
# the respective options.
#
# All other pdftops commandline options are refused.
#
# When printing from STDIN, the program copies the input to a temporary file
# in TMPDIR, which is deleted on exit.
#
# The return code of the pdftops utility, if nonzero, is used as the exit code
# of this program; error messages of the pdftops utility are only visible
# if 'debug' is specified as LogLevel in cupsd.conf.
#
# Site specific parameters - modify as needed
# ------------------------------------------------------------------------------
$pdftops_path = "/usr/bin/pdftops"; # path to the xpdf utility
# ------------------------------------------------------------------------------
use File::Copy;
#
# Check the arguments
#
die ("ERROR: wrong number of arguments\n") if (scalar @ARGV < 5);
$jobid = $username = $title = $copies = undef;
$jobid = shift; # Job ID
$username = shift; # Job requesting user name
$title = shift; # Job title
$copies = shift; # Number of requested copies
$options = shift; # Textual representation of job attributes
$pdffile = shift; # Pathname of PDF file to process
# If we are reading from STDIN, we must copy the input to a temporary file
# as the PDF consumer needs a seekable input.
if (! defined $pdffile)
{
my $tmpfile = $ENV{TMPDIR} . "pdfin.$$.tmp";
open (TEMP, ">$tmpfile") || die ("ERROR: pdftops wrapper: $tmpfile: $!\n");
if (! copy (STDIN, TEMP))
{
close (TEMP);
unlink $tmpfile;
die ("ERROR: pdftops wrapper: $tmpfile: $!\n");
}
close (TEMP);
$pdffile = $tmpfile;
$delete_input = 1; # for deleting the temp file after converting
}
#
# Check the options string for options to modify the bahaviour of the pdftops utility:
#
@optarr = split (/\s+/, $options);
$cmdopt = "-cfg " . $ENV{CUPS_SERVERROOT} . "/pdftops.conf"; # This cannot be changed
# The following are the (parameterless) command line options that may be used to change the
# defaults defiend by pdftops.conf
$simple = 'level1|level1sep|level2|level2sep|level3|level3sep|opi|nocrop|expand|noshrink|nocenter';
foreach my $option (@optarr)
{
if ($option =~ /^pdf-(.+)$/)
{ # We assume this is an option to evaluate
my $optkey = $1; # possible pdftops option
if ($optkey =~ /^pages=(\d*),(\d*)$/)
{
# We do this hack here to avoid clashes with the page-ranges atrribute
# which is handled by the pstops filter. And we allow one of the numbers
# to be omitted.
my $first = $1;
my $lastp = $2;
$cmdopt .= " -f $1" if ($1); # first page
$cmdopt .= " -l $2" if ($2); # last page
}
elsif ($optkey =~ /^paper=(letter|legal|A4|A3|match)$/)
{
$cmdopt .= " -paper $1"; # paper name
}
elsif ($optkey =~ /^paper=(\d+)x(\d+)$/)
{
$cmdopt .= " -paperw $1 -paperh $2"; # paper dimensions
}
elsif ($optkey =~ /^(o|u)pw=(\S+)$/)
{
$cmdopt .= " $1" . 'pw ' . $2; # owner/user password
}
elsif ($optkey =~ /^($simple)$/)
{
$cmdopt .= ' -' . $1; # allowed simple options
}
else
{
warn ("ERROR: pdftops wrapper: illegal attribute \"pdf-$optkey\"\n");
}
}
# All other attributes are processed elsewhere
}
#
# Complete the command
#
warn ("ERROR: pdftops-options: $cmdopt\n");
$rc = system ("/usr/scripts/impression/compatibilise $pdffile $cmdopt ; $pdftops_path $cmdopt $pdffile - ");
if ($rc)
{
$ir = $rc & 127;
$rc >>= 8;
warn ("ERROR: pdftops_path exited with ", ($ir) ? "signal $ir, " : " exit code $rc", "\n");
exit $rc;
}
unlink ($pdffile) if (defined $delete_input); # Delete the temp file if any
exit 0;

View file

@ -0,0 +1,160 @@
(*
* WRAPPER_CANON.ML--
*
* Copyright (C) 2009 Antoine Durand-Gasselin
* Author: Antoine Durand-Gasselin <adg@crans.org>
*
* License: GPLv3
*
* Dependances: libperl4ocaml-dev (>= 0.9.5-2), libwww-mechanize-perl
* Compilation: ocamlfind ocamlc -linkpkg -package unix,perl wrapper_canon.ml
*
#use "topfind";;
#require "perl";;
#require "unix";;
*)
let (%) a b = Printf.sprintf a b;;
let (&) f x = f x
open Perl
open Unix
open Pl_WWW_Mechanize
let timestamp = (** on a besoin d'un timestamp *)
"%d" % (int_of_float (Unix.time()))
(** {1 : Fonctions de conversion des options} *)
let filename = (** le nom du fichier pdf *) ref ""
let copies = ref 1
let _Copies () = "%d" % !copies
let papier = ref "a4"
let _MediaSize () = string_of_int (match String.lowercase (!papier) with
| "a4" -> 5
| "a3" -> 6
| "a5" -> 16
| "b4" -> 12
| "b5" -> 13
| "ltr" -> 1
| "lgl" -> 2
| "11x17" -> 3
| "exec" -> 4
| "com-10" -> 7
| "monarch" -> 8
| "c5 env" -> 9
| "b5 env" -> 10
| "dl env" -> 11
| _ -> raise (Arg.Bad ("%s wrong papersize" % !papier)))
let papertype = ref "Ordinaire"
let _MediaType () = List.assoc !papertype& List.map (fun (x,y) -> y,x)
[ "0", "Ordinaire"; "2", "Recyclé"; "3", "Couleur"; "21", "Ordinaire (Epais)";
"22", "Ordinaire (Fin)"; "1", "Papier épais 1"; "16", "Papier épais 2";
"9", "Carte postale"; "10", "Carte postale"; "11", "Enveloppe";
"6", "Transparent"; "23", "Transparent"; "24", "Couché"; "5", "Calque";
"7", "Etiquettes"; "12", "Papier machine"; "14", "Pré-perforé" ]
let expand = ref false
let _FitSize () = if !expand then "1" else "0"
let duplex = ref true
let binding_long_edge = ref true
let finition = ref "none"
let _DuplexType() =
if !finition = "book" or not !duplex then "0"
else if !binding_long_edge then "2" else "1"
let finition = ref "none"
let _Sort() = match !finition with "none" -> "0" | _ -> "1"
let _StapleType () = List.assoc !finition
[ "TopLeft","5"; "TopRight","6"; "BottomLeft","7"; "BottomRight","8";
"Top","1"; "Bottom","2"; "Left","3"; "Right","4"; "none","0"; "book","9"]
let couleur = ref false
let _ColorMode () = if !couleur then "2" else "1"
(** {1: Le formulaire} *)
let fields () =
[ "Url","http://"; "Mode","100"; "ManualNo","0"; "DocPasswd","";
"WebUserName",""; "WebPasswd","";
"PageMode","0"; "StartPage","1"; "EndPage","1";
"Copies", _Copies();
"MediaSize", _MediaSize();
"MediaType", _MediaType();
"ManualFeed", "0";
"FitSize", _FitSize();
"DuplexType", _DuplexType();
"Sort", _Sort();
"PunchPos","0";
"StapleType", _StapleType();
"BookType","2";
"Annotation","2";
"ColorMode", _ColorMode();
"C_Render","0"; "C_RGB_Pro","1"; "C_CMYK_Pro","4";"C_OUT_Pro","1";
"C_GRAY_Pro","1"; "C_Matching","0"; "SPOT_Color","1"; "C_Pure_B","1";
"C_B_OVPrn","1"; "C_Bright", "100"; "C_Gray_Com","1";"C_OVR_EFF","1";
"WidePrn","0"; "NupPrint","0"; "NupStart","0"; "Resolution","1";
"HalfToneTxt","1"; "HalfToneGrp","1"; "HalfToneImg","1";
"AstIntensity","2"; "AstText","0"; "AstGrap", "1"; "AstImag","1";
"StoreBox","0"; "BoxNo","00"; "RGBDLName",""; "CMYKDLName","";
"OUTDLName",""; "BOXName","";
"Flag","Exec_Data_Pdf";
"Dummy",timestamp;
"Direct","100";
"File", !filename
]
let set_positive r s =
try let a = int_of_string s in assert (a>0); r := a
with _ -> raise (Arg.Bad "copies doivent être un entier positif")
let options = Arg.align
[ "-#", Arg.String (set_positive copies), "N imprime N copies";
"-PageSize", Arg.Set_string papier, "FORMAT Format du papier";
"-MediaType", Arg.Set_string papertype, "TYPE Type du papier";
"-pdf-expand", Arg.Set expand, " Agrandir/Reduire en fonction du papier";
"-one-sided", Arg.Clear duplex, " Impression recto";
"-two-sided", Arg.Set duplex, " Impression recto/verso";
"-two-sided-short-edge", Arg.Clear binding_long_edge,
" Reliure sur le bord court";
"-Monochrom", Arg.Clear couleur, " Impression en noir et blanc";
"-Color", Arg.Set couleur, " Impression en couleurs";
"-Finition", Arg.Set_string finition, "FINITION Finition: none | Top | TopLeft ... | Book";
]
let usage = "Usage: wrapper_canon [OPTIONS] FILE"
let argv = ref 0
let () = Arg.parse options (fun s -> incr argv; filename := s) usage
let () =
if !argv <> 1 then raise (Arg.Bad "Wrong number of file")
(** {1 : Initialisations} *)
let printer = (** url de l'imprimante *)
ref "https://imprimante.adm.crans.org/"
let b =
(** On initialise le "browser" *)
let sv = Perl.call_class_method "WWW::Mechanize" "new" [] in
let browser = new Pl_WWW_Mechanize.www_mechanize sv in
(* On a besoin d'un user_agent connu *)
browser#agent_alias (List.nth browser#known_agent_aliases 1);
(* On récupère un cookie, parce que les cookies c'est bon *)
browser#get !printer;
browser#get (!printer ^ "ppdf.cgi?Type=PDF&Dummy=%s" % timestamp);
browser
(* On balance la sauce *)
let resp = b#submit_form ~form_name:"PDF_SEND_FORM" ~fields:(fields ()) ();;
print_string resp#as_string;;