root / pykota / trunk / bin / pkbanner @ 1949

Revision 1938, 13.8 kB (checked in by jalet, 20 years ago)

Fixed some typo in the help

  • Property svn:eol-style set to native
  • Property svn:executable set to *
  • Property svn:keywords set to Author Date Id Revision
Line 
1#! /usr/bin/env python
2# -*- coding: ISO-8859-15 -*-
3
4# A banner generator for PyKota
5#
6# PyKota - Print Quotas for CUPS and LPRng
7#
8# (c) 2003-2004 Jerome Alet <alet@librelogiciel.com>
9# This program is free software; you can redistribute it and/or modify
10# it under the terms of the GNU General Public License as published by
11# the Free Software Foundation; either version 2 of the License, or
12# (at your option) any later version.
13#
14# This program is distributed in the hope that it will be useful,
15# but WITHOUT ANY WARRANTY; without even the implied warranty of
16# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17# GNU General Public License for more details.
18#
19# You should have received a copy of the GNU General Public License
20# along with this program; if not, write to the Free Software
21# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
22#
23# $Id$
24#
25# $Log$
26# Revision 1.10  2004/11/17 13:28:19  jalet
27# Fixed some typo in the help
28#
29# Revision 1.9  2004/11/17 13:24:05  jalet
30# Improved pkbanner's help
31#
32# Revision 1.8  2004/11/17 13:12:04  jalet
33# Implemented the --savetoner command line option
34#
35# Revision 1.7  2004/11/15 22:29:01  jalet
36# Moved title and filename to the left to free some space.
37#
38# Revision 1.6  2004/11/15 22:20:27  jalet
39# Now outputs strings as-is, and not title-ized
40#
41# Revision 1.5  2004/11/15 22:01:34  jalet
42# Improved banner handling.
43# Fix for raw printing and banners.
44#
45# Revision 1.4  2004/11/15 19:59:34  jalet
46# PyKota banners now basically work !
47#
48# Revision 1.3  2004/11/12 23:46:44  jalet
49# Heavy work on pkbanner. Not finished yet though, but mostly works.
50#
51# Revision 1.2  2004/11/11 14:25:48  jalet
52# Added some TODO comments
53#
54# Revision 1.1  2004/11/10 22:48:47  jalet
55# Banner generator's skeleton added
56#
57#
58#
59
60import sys
61import os
62import time
63import cStringIO
64import popen2
65
66try :
67    from reportlab.pdfgen import canvas
68    from reportlab.lib import pagesizes
69    from reportlab.lib.units import cm
70except ImportError :   
71    hasRL = 0
72else :   
73    hasRL = 1
74   
75try :
76    import PIL.Image 
77except ImportError :   
78    hasPIL = 0
79else :   
80    hasPIL = 1
81   
82from pykota.tool import Tool, PyKotaToolError, crashed, N_
83
84__doc__ = N_("""pkbanner v%s (c) 2003-2004 C@LL - Conseil Internet & Logiciels Libres
85
86Generates banners.
87
88command line usage :
89
90  pkbanner  [options]
91
92options :
93
94  -v | --version       Prints pkbanner's version number then exits.
95  -h | --help          Prints this message then exits.
96 
97  -l | --logo img      Use the image as the banner's logo. The logo will
98                       be drawn at the center top of the page. The default
99                       logo is /usr/share/pykota/logos/pykota.jpeg
100                       
101  -p | --pagesize sz   Sets sz as the page size. Most well known
102                       page sizes are recognized, like 'A4' or 'Letter'
103                       to name a few. The default size is A4.
104 
105  -s | --savetoner s   Sets the text luminosity factor to s%%. This can be
106                       used to save toner. The default value is 0, which
107                       means that no toner saving will be done.
108 
109  -u | --url u         Uses u as an url to be written at the bottom of
110                       the banner page. The default url is :
111                       http://www.librelogiciel.com/software/
112 
113examples :                             
114
115  Using pkbanner directly from the command line is not recommended,
116  excepted for testing purposes. You should use pkbanner in the
117  'startingbanner' or 'endingbanner' directives in pykota.conf
118 
119    startingbanner: /usr/bin/pkbanner --logo="" --savetoner=75
120 
121      With such a setting in pykota.conf, all print jobs will be
122      prefixed with an A4 banner with no logo, and text luminosity will
123      be increased by 75%%. The PostScript output will be directly sent
124      to your printer.
125     
126  You'll find more examples in the sample configuration file included   
127  in PyKota.
128     
129This program is free software; you can redistribute it and/or modify
130it under the terms of the GNU General Public License as published by
131the Free Software Foundation; either version 2 of the License, or
132(at your option) any later version.
133
134This program is distributed in the hope that it will be useful,
135but WITHOUT ANY WARRANTY; without even the implied warranty of
136MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
137GNU General Public License for more details.
138
139You should have received a copy of the GNU General Public License
140along with this program; if not, write to the Free Software
141Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
142
143Please e-mail bugs to: %s""")
144       
145class PyKotaBanner(Tool) :       
146    """A class for pkbanner."""
147    def getPageSize(self, pgsize) :
148        """Returns the correct page size or None if not found."""
149        try :
150            return getattr(pagesizes, pgsize.upper())
151        except AttributeError :   
152            try :
153                return getattr(pagesizes, pgsize.lower())
154            except AttributeError :
155                pass
156               
157    def getVar(self, varname) :           
158        """Extracts a variable from the environment and returns its value or 'Unknown' in the current locale."""
159        return os.environ.get(varname) or _("Unknown")
160       
161    def printVar(self, canvas, x, y, label, value, size, savetoner) :
162        """Outputs a variable onto the PDF canvas.
163       
164           Returns the number of points to substract to current Y coordinate.
165        """   
166        canvas.saveState()
167        canvas.setFont("Helvetica-Bold", size)
168        (r, g, b) =  [ color + (savetoner * (1.0 - color)) for color in (0, 0, 0) ] # Black * savetoner
169        canvas.setFillColorRGB(r, g, b)
170        message = "%s :" % _(label)
171        canvas.drawRightString(x, y, message)
172        canvas.setFont("Courier-Bold", size)
173        (r, g, b) =  [ color + (savetoner * (1.0 - color)) for color in (1, 0, 0) ] # Red * savetoner
174        canvas.setFillColorRGB(r, g, b)
175        canvas.drawString(x + 0.5*cm, y, value)
176        canvas.restoreState()
177        return (size + 4)
178   
179    def genPDF(self, pagesize, logo, url, savetoner) :
180        """Generates the banner in PDF format, return the PDF document as a string."""
181       
182        document = cStringIO.StringIO()
183        c = canvas.Canvas(document, pagesize=pagesize, pageCompression=1)
184       
185        c.setAuthor("Jerome Alet")
186        c.setTitle("PyKota generated Banner")
187        c.setSubject("This is a print banner generated with PyKota")
188       
189        xcenter = pagesize[0] / 2.0
190        ycenter = pagesize[1] / 2.0
191                   
192        ypos = pagesize[1] - (2 * cm)           
193       
194        if logo :
195            try :   
196                imglogo = PIL.Image.open(logo)
197            except :   
198                self.printInfo("Unable to open image %s" % logo, "warn")
199            else :
200                (width, height) = imglogo.size
201                multi = float(width) / (8 * cm) 
202                width = float(width) / multi
203                height = float(height) / multi
204                xpos = xcenter - (width / 2.0)
205                ypos -= height
206                c.drawImage(logo, xpos, ypos, width, height)
207       
208        # New top
209        xpos = pagesize[0] / 5.0
210        ypos -= (1 * cm) + 20
211       
212        printername = self.getVar("PYKOTAPRINTERNAME")
213        username = self.getVar("PYKOTAUSERNAME")
214        accountbanner = self.config.getAccountBanner(printername)
215       
216        # Outputs the username
217        ypos -= self.printVar(c, xcenter, ypos, _("Username"), username, 20, savetoner) 
218       
219        # Printer and Job Id
220        job = "%s - %s" % (printername, self.getVar("PYKOTAJOBID"))
221        ypos -= self.printVar(c, xcenter, ypos, _("Job"), job, 14, savetoner) 
222       
223        # Current date (TODO : at the time the banner was printed ! Change this to job's submission date)
224        datetime = time.strftime("%c", time.localtime())
225        ypos -= self.printVar(c, xcenter, ypos, _("Date"), datetime, 14, savetoner) 
226       
227        # Result of the print job
228        action = self.getVar("PYKOTAACTION")
229        if action == "ALLOW" :
230            action = _("Allowed")
231        elif action == "DENY" :   
232            action = _("Denied")
233        elif action == "WARN" :   
234            action = _("Allowed with Warning")
235        ypos -= self.printVar(c, xcenter, ypos, _("Result"), action, 14, savetoner) 
236       
237        # skip some space
238        ypos -= 20
239       
240        # Outputs title and filename
241        # We put them at x=0.25*pagewidth so that the line is long enough to hold them
242        title = self.getVar("PYKOTATITLE")
243        ypos -= self.printVar(c, xcenter / 2.0, ypos, _("Title"), title, 10, savetoner) 
244       
245        filename = self.getVar("PYKOTAFILENAME")
246        ypos -= self.printVar(c, xcenter / 2.0, ypos, _("Filename"), filename, 10, savetoner) 
247       
248        # skip some space
249        ypos -= 20
250       
251        # Now outputs the user's account balance or page counter
252        ypos -= self.printVar(c, xcenter, ypos, _("Pages printed so far on %s") % printername, self.getVar("PYKOTAPAGECOUNTER"), 14, savetoner) 
253        limitby = self.getVar("PYKOTALIMITBY")
254        if limitby == "balance" : 
255            ypos -= self.printVar(c, xcenter, ypos, _("Account balance"), self.getVar("PYKOTABALANCE"), 14, savetoner) 
256        else :
257            ypos -= self.printVar(c, xcenter, ypos, _("Soft Limit"), self.getVar("PYKOTASOFTLIMIT"), 14, savetoner) 
258            ypos -= self.printVar(c, xcenter, ypos, _("Hard Limit"), self.getVar("PYKOTAHARDLIMIT"), 14, savetoner) 
259            ypos -= self.printVar(c, xcenter, ypos, _("Date Limit"), self.getVar("PYKOTADATELIMIT"), 14, savetoner) 
260           
261        # URL
262        if url :
263            c.saveState()
264            c.setFont("Courier-Bold", 16)
265            (r, g, b) =  [ color + (savetoner * (1.0 - color)) for color in (0, 0, 1) ] # Blue * savetoner
266            c.setFillColorRGB(r, g, b)
267            c.drawCentredString(xcenter, 2 * cm, url)
268            c.restoreState()
269       
270        c.showPage()
271        c.save()
272        return document.getvalue()
273       
274    def main(self, files, options) :
275        """Generates a banner."""
276        if not hasRL :
277            raise PyKotaToolError, "The ReportLab module is missing. Download it from http://www.reportlab.org"
278        if not hasPIL :
279            raise PyKotaToolError, "The Python Imaging Library is missing. Download it from http://www.pythonware.com/downloads"
280           
281        try :
282            savetoner = int(options["savetoner"])
283            if (savetoner < 0) or (savetoner > 99) :
284                raise ValueError, _("Allowed range is (0..99)")
285            savetoner /= 100.0   
286        except (TypeError, ValueError), msg :
287            self.printInfo(_("Invalid 'savetoner' option %s : %s") % (options["savetoner"], msg), "warn")
288            savetoner = 0.0
289           
290        pagesize = self.getPageSize(options["pagesize"])
291        if pagesize is None :
292            pagesize = self.getPageSize("a4")
293            self.printInfo(_("Invalid 'pagesize' option %s, defaulting to A4.") % options["pagesize"], "warn")
294           
295        self.logdebug("Generating the banner in PDF format...")   
296        doc = self.genPDF(pagesize, options["logo"].strip(), options["url"].strip(), savetoner)
297       
298        self.logdebug("Converting the banner to PostScript...")   
299        os.environ["PATH"] = "%s:/bin:/usr/bin:/usr/local/bin:/opt/bin:/sbin:/usr/sbin" % os.environ.get("PATH", "")
300        child = popen2.Popen3("gs -q -dNOPAUSE -dBATCH -dPARANOIDSAFER -sDEVICE=pswrite -sOutputFile=- - 2>/tmp/errgs")
301        child.tochild.write(doc)
302        child.tochild.close()
303        sys.stdout.write(child.fromchild.read())
304        sys.stdout.flush()
305        child.fromchild.close()
306        status = child.wait()
307        if os.WIFEXITED(status) :
308            status = os.WEXITSTATUS(status)
309        self.logdebug("PDF to PostScript converter exit code is %s" % str(status))
310        self.logdebug("Banner completed.")
311        return status
312
313if __name__ == "__main__" :
314    # TODO : --papertray : to print banners on a different paper (colored for example)
315    retcode = 0
316    try :
317        defaults = { \
318                     "savetoner" : "100", \
319                     "pagesize" : "a4", \
320                     "logo" : "/usr/share/pykota/logos/pykota.jpeg",
321                     "url" : "http://www.librelogiciel.com/software/",
322                   }
323        short_options = "vhs:l:p:u:"
324        long_options = ["help", "version", "savetoner=", "pagesize=", "logo=", "url="]
325       
326        # Initializes the command line tool
327        banner = PyKotaBanner(doc=__doc__)
328       
329        # parse and checks the command line
330        (options, args) = banner.parseCommandline(sys.argv[1:], short_options, long_options, allownothing=1)
331       
332        # sets long options
333        options["help"] = options["h"] or options["help"]
334        options["version"] = options["v"] or options["version"]
335        options["savetoner"] = options["s"] or options["savetoner"] or defaults["savetoner"]
336        options["pagesize"] = options["p"] or options["pagesize"] or defaults["pagesize"]
337        options["url"] = options["u"] or options["url"] or defaults["url"]
338       
339        options["logo"] = options["l"] or options["logo"]
340        if options["logo"] is None : # Allows --logo="" to disable the logo entirely
341            options["logo"] = defaults["logo"] 
342       
343        if options["help"] :
344            banner.display_usage_and_quit()
345        elif options["version"] :
346            banner.display_version_and_quit()
347        else :
348            retcode = banner.main(args, options)
349    except SystemExit :       
350        pass
351    except :
352        try :
353            banner.crashed("pkbanner failed")
354        except :   
355            crashed("pkbanner failed")
356        retcode = -1
357       
358    sys.exit(retcode)   
Note: See TracBrowser for help on using the browser.