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

Revision 1621, 13.6 kB (checked in by jalet, 20 years ago)

Inversion

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