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

Revision 2631, 13.7 kB (checked in by jerome, 19 years ago)

Added support for the CANCEL command in subprocesses launched from the
overwrite_jobticket directive : this will allow end users to be asked
if they really want to proceed to printing once the new version
of pykoticon will be ready.
Several minor fixes.

  • 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, 2005, 2006 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
22#
23# $Id$
24#
25#
26
27import sys
28import os
29import cgi
30import urllib
31
32from mx import DateTime
33
34from pykota import version
35from pykota.tool import PyKotaTool, PyKotaToolError
36from pykota.reporter import PyKotaReporterError, openReporter
37from pykota.cgifuncs import getLanguagePreference, getCharsetPreference
38
39header = """Content-type: text/html
40
41<?xml version="1.0" encoding="%s"?>
42<html>
43  <head>
44    <title>%s</title>
45    <link rel="stylesheet" type="text/css" href="/pykota.css" />
46  </head>
47  <body>
48    <p>
49      <form action="printquota.cgi" method="POST">
50        <table>
51          <tr>
52            <td>
53              <p>
54                <a href="%s"><img src="%s?version=%s" alt="PyKota's Logo" /></a>
55                <br />
56                <a href="%s">PyKota v%s</a>
57              </p>
58            </td>
59            <td colspan="2">
60              <h1>%s</h1>
61            </td>
62          </tr>
63          <tr>
64            <td colspan="3" align="center">
65              <input type="submit" name="report" value="%s" />
66            </td>
67          </tr>
68        </table>"""
69   
70footer = """
71        <table>
72          <tr>
73            <td colspan="3" align="center">
74              <input type="submit" name="report" value="%s" />
75            </td>
76          </tr>
77        </table> 
78      </form>
79    </p>
80    <hr width="25%%" />
81    <p>
82      <font size="-2">
83        <a href="http://www.librelogiciel.com/software/">%s</a>
84        &copy; %s %s
85        <br />
86        <pre>
87%s
88        </pre>
89      </font>
90    </p>
91  </body>
92</html>""" 
93
94class PyKotaReportGUI(PyKotaTool) :
95    """PyKota Administrative GUI"""
96    def guiDisplay(self) :
97        """Displays the administrative interface."""
98        global header, footer
99        print header % (self.getCharset(), _("PyKota Reports"), \
100                        self.config.getLogoLink(), \
101                        self.config.getLogoURL(), version.__version__, \
102                        self.config.getLogoLink(), \
103                        version.__version__, _("PyKota Reports"), \
104                        _("Report"))
105        print self.body
106        print footer % (_("Report"), version.__doc__, version.__years__, version.__author__, version.__gplblurb__)
107       
108    def error(self, message) :
109        """Adds an error message to the GUI's body."""
110        if message :
111            self.body = '<p><font color="red">%s</font></p>\n%s' % (message, self.body)
112       
113    def htmlListPrinters(self, selected=[], mask="*") :   
114        """Displays the printers multiple selection list."""
115        printers = self.storage.getMatchingPrinters(mask)
116        selectednames = [p.Name for p in selected]
117        message = '<table><tr><td valign="top">%s :</td><td valign="top"><select name="printers" multiple="multiple">' % _("Printer")
118        for printer in printers :
119            if printer.Name in selectednames :
120                message += '<option value="%s" selected="selected">%s (%s)</option>' % (printer.Name, printer.Name, printer.Description)
121            else :
122                message += '<option value="%s">%s (%s)</option>' % (printer.Name, printer.Name, printer.Description)
123        message += '</select></td></tr></table>'
124        return message
125       
126    def htmlUGNamesInput(self, value="*") :   
127        """Input field for user/group names wildcard."""
128        return _("User / Group names mask") + (' : <input type="text" name="ugmask" size="20" value="%s" /> <em>e.g. <strong>jo*</strong></em>' % (value or "*"))
129       
130    def htmlGroupsCheckbox(self, isgroup=0) :
131        """Groups checkbox."""
132        if isgroup :
133            return _("Groups report") + ' : <input type="checkbox" checked="checked" name="isgroup" />'
134        else :   
135            return _("Groups report") + ' : <input type="checkbox" name="isgroup" />'
136           
137    def guiAction(self) :
138        """Main function"""
139        printers = ugmask = isgroup = None
140        remuser = os.environ.get("REMOTE_USER", "root")   
141        # special hack to accomodate mod_auth_ldap Apache module
142        try :
143            remuser = remuser.split("=")[1].split(",")[0]
144        except IndexError :   
145            pass
146        self.body = "<p>%s</p>\n" % _("Please click on the above button")
147        if self.form.has_key("report") :
148            if self.form.has_key("printers") :
149                printersfield = self.form["printers"]
150                if type(printersfield) != type([]) :
151                    printersfield = [ printersfield ]
152                printers = [self.storage.getPrinter(p.value) for p in printersfield]
153            else :   
154                printers = self.storage.getMatchingPrinters("*")
155            if remuser == "root" :
156                if self.form.has_key("ugmask") :     
157                    ugmask = self.form["ugmask"].value
158                else :     
159                    ugmask = "*"
160            else :       
161                if self.form.has_key("isgroup") :   
162                    user = self.storage.getUser(remuser)
163                    if user.Exists :
164                        ugmask = " ".join([ g.Name for g in self.storage.getUserGroups(user) ])
165                    else :   
166                        ugmask = remuser # result will probably be empty, we don't care
167                else :   
168                    ugmask = remuser
169            if self.form.has_key("isgroup") :   
170                isgroup = 1
171            else :   
172                isgroup = 0
173        self.body += self.htmlListPrinters(printers or [])           
174        self.body += "<br />"
175        self.body += self.htmlUGNamesInput(ugmask)
176        self.body += "<br />"
177        self.body += self.htmlGroupsCheckbox(isgroup)
178        try :
179            if not self.form.has_key("history") :
180                if printers and ugmask :
181                    self.reportingtool = openReporter(admin, "html", printers, ugmask.split(), isgroup)
182                    self.body += "%s" % self.reportingtool.generateReport()
183            else :       
184                if remuser != "root" :
185                    username = remuser
186                elif self.form.has_key("username") :   
187                    username = self.form["username"].value
188                else :   
189                    username = None
190                if username is not None :   
191                    user = self.storage.getUser(username)
192                else :   
193                    user = None
194                if self.form.has_key("printername") :
195                    printer = self.storage.getPrinter(self.form["printername"].value)
196                else :   
197                    printer = None
198                if self.form.has_key("datelimit") :   
199                    datelimit = self.form["datelimit"].value
200                else :   
201                    datelimit = None
202                if self.form.has_key("hostname") :   
203                    hostname = self.form["hostname"].value
204                else :   
205                    hostname = None
206                if self.form.has_key("billingcode") :   
207                    billingcode = self.form["billingcode"].value
208                else :   
209                    billingcode = None
210                self.report = ["<h2>%s</h2>" % _("History")]   
211                history = self.storage.retrieveHistory(user, printer, hostname, billingcode, end=datelimit)
212                if not history :
213                    self.report.append("<h3>%s</h3>" % _("Empty"))
214                else :
215                    self.report.append('<table class="pykotatable" border="1">')
216                    headers = [_("Date"), _("Action"), _("User"), _("Printer"), \
217                               _("Hostname"), _("JobId"), _("Number of pages"), \
218                               _("Cost"), _("Copies"), _("Number of bytes"), \
219                               _("Printer's internal counter"), _("Title"), _("Filename"), \
220                               _("Options"), _("MD5Sum"), _("Billing code"), \
221                               _("Precomputed number of pages"), _("Precomputed cost"), _("Pages details") + " " + _("(not supported yet)")]
222                    self.report.append('<tr class="pykotacolsheader">%s</tr>' % "".join(["<th>%s</th>" % h for h in headers]))
223                    oddeven = 0
224                    for job in history :
225                        oddeven += 1
226                        if oddeven % 2 :
227                            oddevenclass = "odd"
228                        else :   
229                            oddevenclass = "even"
230                        if job.JobAction == "DENY" :
231                            oddevenclass = "deny"
232                        elif job.JobAction == "WARN" :   
233                            oddevenclass = "warn"
234                        elif job.JobAction == "PROBLEM" :
235                            oddevenclass = "problem"
236                        elif job.JobAction == "CANCEL" :
237                            oddevenclass = "cancel"
238                        username_url = '<a href="%s?%s">%s</a>' % (os.environ.get("SCRIPT_NAME", ""), urllib.urlencode({"history" : 1, "username" : job.UserName}), job.UserName)
239                        printername_url = '<a href="%s?%s">%s</a>' % (os.environ.get("SCRIPT_NAME", ""), urllib.urlencode({"history" : 1, "printername" : job.PrinterName}), job.PrinterName)
240                        if job.JobHostName :
241                            hostname_url = '<a href="%s?%s">%s</a>' % (os.environ.get("SCRIPT_NAME", ""), urllib.urlencode({"history" : 1, "hostname" : job.JobHostName}), job.JobHostName)
242                        else :   
243                            hostname_url = None
244                        if job.JobBillingCode :
245                            billingcode_url = '<a href="%s?%s">%s</a>' % (os.environ.get("SCRIPT_NAME", ""), urllib.urlencode({"history" : 1, "billingcode" : job.JobBillingCode}), job.JobBillingCode)
246                        else :   
247                            billingcode_url = None
248                        self.report.append('<tr class="%s">%s</tr>' % \
249                                              (oddevenclass, \
250                                               "".join(["<td>%s</td>" % (h or "&nbsp;") \
251                                                  for h in (job.JobDate[:19], \
252                                                            _(job.JobAction), \
253                                                            username_url, \
254                                                            printername_url, \
255                                                            hostname_url, \
256                                                            job.JobId, \
257                                                            job.JobSize, \
258                                                            job.JobPrice, \
259                                                            job.JobCopies, \
260                                                            job.JobSizeBytes, \
261                                                            job.PrinterPageCounter, \
262                                                            job.JobTitle, \
263                                                            job.JobFileName, \
264                                                            job.JobOptions, \
265                                                            job.JobMD5Sum, \
266                                                            billingcode_url, \
267                                                            job.PrecomputedJobSize, \
268                                                            job.PrecomputedJobPrice, \
269                                                            job.JobPages)])))
270                    self.report.append('</table>')
271                    d = DateTime.ISO.ParseDateTime(job.JobDate)       
272                    dico = { "history" : 1,
273                             "datelimit" : "%04i%02i%02i %02i:%02i:%02i" % (d.year, d.month, d.day, d.hour, d.minute, d.second),
274                           }
275                    if user and user.Exists :
276                        dico.update({ "username" : user.Name })
277                    if printer and printer.Exists :
278                        dico.update({ "printername" : printer.Name })
279                    if hostname :   
280                        dico.update({ "hostname" : hostname })
281                    prevurl = "%s?%s" % (os.environ.get("SCRIPT_NAME", ""), urllib.urlencode(dico))
282                    self.report.append('<a href="%s">%s</a>' % (prevurl, _("Previous page")))
283                self.body = "\n".join(self.report)   
284        except :
285                self.body += '<p><font color="red">%s</font></p>' % self.crashed("CGI Error").replace("\n", "<br />")
286           
287if __name__ == "__main__" :
288    os.environ["LC_ALL"] = getLanguagePreference()
289    admin = PyKotaReportGUI(lang=os.environ["LC_ALL"], charset=getCharsetPreference())
290    admin.deferredInit()
291    admin.form = cgi.FieldStorage()
292    admin.guiAction()
293    admin.guiDisplay()
294    try :
295        admin.storage.close()
296    except (TypeError, NameError, AttributeError) :   
297        pass
298       
299    sys.exit(0)
Note: See TracBrowser for help on using the browser.