root / pykota / trunk / cgi-bin / printquota.cgi @ 1817

Revision 1817, 14.6 kB (checked in by jalet, 20 years ago)

Added a translatable message from the CGI script

  • 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/python
2# -*- coding: ISO-8859-15 -*-
3
4# PyKota Print Quota Reports generator
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.39  2004/10/13 09:38:25  jalet
27# Added a translatable message from the CGI script
28#
29# Revision 1.38  2004/10/02 13:47:46  jalet
30# The CGI script doesn't depend anymore on what is in the submit button
31# to display the print quota report.
32#
33# Revision 1.37  2004/10/02 05:48:56  jalet
34# Should now correctly deal with charsets both when storing into databases and when
35# retrieving datas. Works with both PostgreSQL and LDAP.
36#
37# Revision 1.36  2004/09/02 10:34:09  jalet
38# Fixed problem with mod_auth_ldap Apache module
39#
40# Revision 1.35  2004/07/24 20:10:10  jalet
41# Incorrect number of parameters in error method
42#
43# Revision 1.34  2004/07/24 20:07:13  jalet
44# Added special Python comment to remove warning at runtime
45#
46# Revision 1.33  2004/07/21 19:24:48  jalet
47# Inversion
48#
49# Revision 1.32  2004/07/21 19:20:05  jalet
50# Missing translation in CGI script
51#
52# Revision 1.31  2004/07/21 13:32:02  jalet
53# All messages should be translatable now.
54#
55# Revision 1.30  2004/07/01 17:45:48  jalet
56# Added code to handle the description field for printers
57#
58# Revision 1.29  2004/06/06 21:07:55  jalet
59# Improved CGI script to allow history on printers and hostnames.
60# Better (?) colors in stylesheet.
61#
62# Revision 1.28  2004/06/05 22:42:41  jalet
63# Improved web history reports
64#
65# Revision 1.27  2004/05/26 14:49:40  jalet
66# First try at saving the job-originating-hostname in the database
67#
68# Revision 1.26  2004/03/24 19:37:04  jalet
69# Doesn't retrieve users or printers objects to display the history,
70# this is not needed, and saves a lot of time (and database queries
71# if storagecahing is disabled)
72#
73# Revision 1.25  2004/01/12 15:28:45  jalet
74# Now can output the user's history on several printers at the same time.
75#
76# Revision 1.24  2004/01/12 14:52:03  jalet
77# Cuts the date string
78#
79# Revision 1.23  2004/01/12 14:35:01  jalet
80# Printing history added to CGI script.
81#
82# Revision 1.22  2004/01/09 07:58:53  jalet
83# Changed URL to PyKota's logo
84#
85# Revision 1.21  2004/01/08 14:10:32  jalet
86# Copyright year changed.
87#
88# Revision 1.20  2004/01/07 16:07:17  jalet
89# The stylesheet is again expected to be local, it was a bad idea to use
90# the one on my server.
91#
92# Revision 1.19  2004/01/06 16:05:45  jalet
93# Will now search the stylesheet on my own website.
94#
95# Revision 1.18  2003/12/27 16:49:25  uid67467
96# Should be ok now.
97#
98# Revision 1.16  2003/12/02 14:40:20  jalet
99# Some code refactoring.
100# New HTML reporter added, which is now used in the CGI script for web based
101# print quota reports. It will need some de-uglyfication though...
102#
103# Revision 1.15  2003/10/24 22:06:42  jalet
104# Initial support for browser's language preference added.
105#
106# Revision 1.14  2003/10/10 19:48:07  jalet
107# Now displays version number
108#
109# Revision 1.13  2003/08/25 11:23:05  jalet
110# More powerful CGI script for quota reports
111#
112# Revision 1.12  2003/07/29 20:55:17  jalet
113# 1.14 is out !
114#
115# Revision 1.11  2003/07/01 12:37:31  jalet
116# Nicer UI
117#
118# Revision 1.10  2003/07/01 07:30:32  jalet
119# Message changed.
120#
121# Revision 1.9  2003/06/30 13:47:26  jalet
122# Allows multiple user / group names masks in the input field
123#
124# Revision 1.8  2003/06/30 13:32:01  jalet
125# Much more powerful CGI script for quota reports
126#
127# Revision 1.7  2003/06/30 12:46:15  jalet
128# Extracted reporting code.
129#
130# Revision 1.6  2003/04/23 22:13:56  jalet
131# Preliminary support for LPRng added BUT STILL UNTESTED.
132#
133# Revision 1.5  2003/04/17 21:30:09  jalet
134# Now includes the logo
135#
136# Revision 1.4  2003/04/08 21:20:25  jalet
137# CGI Script now displays a link to PyKota's website.
138#
139# Revision 1.3  2003/03/29 13:45:27  jalet
140# GPL paragraphs were incorrectly (from memory) copied into the sources.
141# Two README files were added.
142# Upgrade script for PostgreSQL pre 1.01 schema was added.
143#
144# Revision 1.2  2003/02/12 11:31:51  jalet
145# doesn't use the jaxml module anymore
146#
147# Revision 1.1  2003/02/10 13:41:38  jalet
148# repykota cgi script added.
149# cleaner doc.
150#
151
152import sys
153import os
154import cgi
155import urllib
156
157from pykota import version
158from pykota.tool import PyKotaTool, PyKotaToolError
159from pykota.reporter import PyKotaReporterError, openReporter
160
161header = """Content-type: text/html
162
163<?xml version="1.0" encoding="%s"?>
164<html>
165  <head>
166    <title>%s</title>
167    <link rel="stylesheet" type="text/css" href="/pykota.css" />
168  </head>
169  <body>
170    <form action="printquota.cgi" method="POST">
171      <table>
172        <tr>
173          <td>
174            <p>
175              <a href="http://www.librelogiciel.com/software/"><img src="http://www.librelogiciel.com/software/PyKota/pykota.png" alt="PyKota's Logo" /></a>
176              <br />
177              <a href="http://www.librelogiciel.com/software/">PyKota v%s</a>
178            </p>
179          </td>
180          <td colspan="2">
181            <h1>%s</h1>
182          </td>
183        </tr>
184        <tr>
185          <td colspan="3" align="center">
186            <input type="submit" name="report" value="%s" />
187          </td>
188        </tr>
189      </table>"""
190   
191footer = """
192      <table>
193        <tr>
194          <td colspan="3" align="center">
195            <input type="submit" name="report" value="%s" />
196          </td>
197        </tr>
198      </table> 
199    </form>
200  </body>
201</html>""" 
202
203def getLanguagePreference() :
204    """Returns the preferred language."""
205    languages = os.environ.get("HTTP_ACCEPT_LANGUAGE", "")
206    langs = [l.strip().split(';')[0] for l in languages.split(",")]
207    return "%s_%s" % (langs[0], langs[0].upper())
208   
209def getCharsetPreference() :
210    """Returns the preferred charset."""
211    charsets = os.environ.get("HTTP_ACCEPT_CHARSET", "no charset defined")
212    charsets = [l.strip().split(';')[0] for l in charsets.split(",")]
213    return charsets[0]
214
215class PyKotaReportGUI(PyKotaTool) :
216    """PyKota Administrative GUI"""
217    def guiDisplay(self) :
218        """Displays the administrative interface."""
219        global header, footer
220        print header % (self.getCharset(), _("PyKota Reports"), version.__version__, _("PyKota Reports"), _("Report"))
221        print self.body
222        print footer % _("Report")
223       
224    def error(self, message) :
225        """Adds an error message to the GUI's body."""
226        if message :
227            self.body = '<p><font color="red">%s</font></p>\n%s' % (message, self.body)
228       
229    def htmlListPrinters(self, selected=[], mask="*") :   
230        """Displays the printers multiple selection list."""
231        printers = self.storage.getMatchingPrinters(mask)
232        selectednames = [p.Name for p in selected]
233        message = '<table><tr><td valign="top">%s :</td><td valign="top"><select name="printers" multiple="multiple">' % _("Printer")
234        for printer in printers :
235            if printer.Name in selectednames :
236                message += '<option value="%s" selected="selected">%s (%s)</option>' % (printer.Name, printer.Name, printer.Description)
237            else :
238                message += '<option value="%s">%s (%s)</option>' % (printer.Name, printer.Name, printer.Description)
239        message += '</select></td></tr></table>'
240        return message
241       
242    def htmlUGNamesInput(self, value="*") :   
243        """Input field for user/group names wildcard."""
244        return _("User / Group names mask") + (' : <input type="text" name="ugmask" size="20" value="%s" /> <em>e.g. <strong>jo*</strong></em>' % (value or "*"))
245       
246    def htmlGroupsCheckbox(self, isgroup=0) :
247        """Groups checkbox."""
248        if isgroup :
249            return _("Groups report") + ' : <input type="checkbox" checked="checked" name="isgroup" />'
250        else :   
251            return _("Groups report") + ' : <input type="checkbox" name="isgroup" />'
252           
253    def guiAction(self) :
254        """Main function"""
255        printers = ugmask = isgroup = None
256        self.body = "<p>%s</p>\n" % _("Please click on the above button")
257        if self.form.has_key("report") :
258            if self.form.has_key("printers") :
259                printersfield = self.form["printers"]
260                if type(printersfield) != type([]) :
261                    printersfield = [ printersfield ]
262                printers = [self.storage.getPrinter(p.value) for p in printersfield]
263            else :   
264                printers = self.storage.getMatchingPrinters("*")
265            remuser = os.environ.get("REMOTE_USER", "root")   
266           
267            # special hack to accomodate mod_auth_ldap Apache module
268            try :
269                remuser = remuser.split("=")[1].split(",")[0]
270            except IndexError :   
271                pass
272           
273            if remuser == "root" :
274                if self.form.has_key("ugmask") :     
275                    ugmask = self.form["ugmask"].value
276                else :     
277                    ugmask = "*"
278            else :       
279                if self.form.has_key("isgroup") :   
280                    user = self.storage.getUser(remuser)
281                    if user.Exists :
282                        ugmask = " ".join([ g.Name for g in self.storage.getUserGroups(user) ])
283                    else :   
284                        ugmask = remuser # result will probably be empty, we don't care
285                else :   
286                    ugmask = remuser
287            if self.form.has_key("isgroup") :   
288                isgroup = 1
289            else :   
290                isgroup = 0
291        self.body += self.htmlListPrinters(printers or [])           
292        self.body += "<br />"
293        self.body += self.htmlUGNamesInput(ugmask)
294        self.body += "<br />"
295        self.body += self.htmlGroupsCheckbox(isgroup)
296        if not self.form.has_key("history") :
297            if printers and ugmask :
298                self.reportingtool = openReporter(admin, "html", printers, ugmask.split(), isgroup)
299                self.body += "%s" % self.reportingtool.generateReport()
300        else :       
301            remuser = os.environ.get("REMOTE_USER", "root")   
302            if remuser != "root" :
303                username = remuser
304            elif self.form.has_key("username") :   
305                username = self.form["username"].value
306            else :   
307                username = None
308            if username is not None :   
309                user = self.storage.getUser(username)
310            else :   
311                user =None
312            if self.form.has_key("printername") :
313                printer = self.storage.getPrinter(self.form["printername"].value)
314            else :   
315                printer = None
316            if self.form.has_key("datelimit") :   
317                datelimit = self.form["datelimit"].value
318            else :   
319                datelimit = None
320            if self.form.has_key("hostname") :   
321                hostname = self.form["hostname"].value
322            else :   
323                hostname = None
324            self.report = ["<h2>%s</h2>" % _("History")]   
325            history = self.storage.retrieveHistory(user, printer, datelimit, hostname)
326            if not history :
327                self.report.append("<h3>%s</h3>" % _("Empty"))
328            else :
329                self.report.append('<table class="pykotatable" border="1">')
330                headers = [_("Date"), _("Action"), _("User"), _("Printer"), _("Hostname"), _("JobId"), _("JobSize"), _("JobPrice"), _("Copies"), _("JobBytes"), _("PageCounter"), _("Title"), _("Filename"), _("Options")]
331                self.report.append('<tr class="pykotacolsheader">%s</tr>' % "".join(["<th>%s</th>" % h for h in headers]))
332                oddeven = 0
333                for job in history :
334                    oddeven += 1
335                    if oddeven % 2 :
336                        oddevenclass = "odd"
337                    else :   
338                        oddevenclass = "even"
339                    if job.JobAction == "DENY" :
340                        oddevenclass = "deny"
341                    elif job.JobAction == "WARN" :   
342                        oddevenclass = "warn"
343                    username_url = '<a href="%s?%s">%s</a>' % (os.environ.get("SCRIPT_NAME", ""), urllib.urlencode({"history" : 1, "username" : job.UserName}), job.UserName)
344                    printername_url = '<a href="%s?%s">%s</a>' % (os.environ.get("SCRIPT_NAME", ""), urllib.urlencode({"history" : 1, "printername" : job.PrinterName}), job.PrinterName)
345                    if job.JobHostName :
346                        hostname_url = '<a href="%s?%s">%s</a>' % (os.environ.get("SCRIPT_NAME", ""), urllib.urlencode({"history" : 1, "hostname" : job.JobHostName}), job.JobHostName)
347                    else :   
348                        hostname_url = None
349                    self.report.append('<tr class="%s">%s</tr>' % (oddevenclass, "".join(["<td>%s</td>" % (h or "&nbsp;") for h in (job.JobDate[:19], job.JobAction, username_url, printername_url, hostname_url, job.JobId, job.JobSize, job.JobPrice, job.JobCopies, job.JobSizeBytes, job.PrinterPageCounter, job.JobTitle, job.JobFileName, job.JobOptions)])))
350                self.report.append('</table>')
351                dico = { "history" : 1,
352                         "datelimit" : job.JobDate,
353                       }
354                if user and user.Exists :
355                    dico.update({ "username" : user.Name })
356                if printer and printer.Exists :
357                    dico.update({ "printername" : printer.Name })
358                if hostname :   
359                    dico.update({ "hostname" : hostname })
360                prevurl = "%s?%s" % (os.environ.get("SCRIPT_NAME", ""), urllib.urlencode(dico))
361                self.report.append('<a href="%s">%s</a>' % (prevurl, _("Previous page")))
362            self.body = "\n".join(self.report)   
363           
364if __name__ == "__main__" :
365    os.environ["LC_ALL"] = getLanguagePreference()
366    admin = PyKotaReportGUI(lang=os.environ["LC_ALL"], charset=getCharsetPreference())
367    admin.form = cgi.FieldStorage()
368    admin.guiAction()
369    admin.guiDisplay()
370    try :
371        admin.storage.close()
372    except (TypeError, NameError, AttributeError) :   
373        pass
374       
375    sys.exit(0)
Note: See TracBrowser for help on using the browser.