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

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

Added special Python comment to remove warning at runtime

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