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

Revision 3411, 14.1 kB (checked in by jerome, 16 years ago)

Minor change to please emacs...

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