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

Revision 3295, 13.9 kB (checked in by jerome, 16 years ago)

Made the CGI scripts work again.
Moved even more functions to the utils module.
Removed the cgifuncs module, moved (and changed) content into utils.
If no output encoding defined, use UTF-8 : when wget is used to try
the CGI scripts, it doesn't set by default the accepted charset and
language headers.

  • 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: UTF-8 -*-
3
4# PyKota Print Quota Reports generator
5#
6# PyKota - Print Quotas for CUPS
7#
8# (c) 2003, 2004, 2005, 2006, 2007, 2008 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 3 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, see <http://www.gnu.org/licenses/>.
21#
22# $Id$
23#
24#
25
26import sys
27import os
28import cgi
29import urllib
30
31from mx import DateTime
32
33import pykota.appinit
34
35from pykota import version, utils
36from pykota.tool import PyKotaTool
37from pykota.errors import PyKotaToolError, PyKotaReporterError
38from pykota.reporter import openReporter
39
40header = """Content-type: text/html;charset=%s
41
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.pykota.com/">%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        content = [ header % (self.charset, _("PyKota Reports"), \
100                              self.config.getLogoLink(), \
101                              self.config.getLogoURL(), version.__version__, \
102                              self.config.getLogoLink(), \
103                              version.__version__, _("PyKota Reports"), \
104                              _("Report")) ]
105        content.append(self.body)                     
106        content.append(footer % (_("Report"), version.__doc__, version.__years__, version.__author__, version.__gplblurb__))
107        for c in content :
108            sys.stdout.write(c.encode(self.charset, "replace"))
109        sys.stdout.flush()
110       
111    def error(self, message) :
112        """Adds an error message to the GUI's body."""
113        if message :
114            self.body = '<p><font color="red">%s</font></p>\n%s' % (message, self.body)
115       
116    def htmlListPrinters(self, selected=[], mask="*") :   
117        """Displays the printers multiple selection list."""
118        printers = self.storage.getMatchingPrinters(mask)
119        selectednames = [p.Name for p in selected]
120        message = '<table><tr><td valign="top">%s :</td><td valign="top"><select name="printers" multiple="multiple">' % _("Printer")
121        for printer in printers :
122            if printer.Name in selectednames :
123                message += '<option value="%s" selected="selected">%s (%s)</option>' % (printer.Name, printer.Name, printer.Description)
124            else :
125                message += '<option value="%s">%s (%s)</option>' % (printer.Name, printer.Name, printer.Description)
126        message += '</select></td></tr></table>'
127        return message
128       
129    def htmlUGNamesInput(self, value="*") :   
130        """Input field for user/group names wildcard."""
131        return _("User / Group names mask") + (' : <input type="text" name="ugmask" size="20" value="%s" /> <em>e.g. <strong>jo*</strong></em>' % (value or "*"))
132       
133    def htmlGroupsCheckbox(self, isgroup=0) :
134        """Groups checkbox."""
135        if isgroup :
136            return _("Groups report") + ' : <input type="checkbox" checked="checked" name="isgroup" />'
137        else :   
138            return _("Groups report") + ' : <input type="checkbox" name="isgroup" />'
139           
140    def guiAction(self) :
141        """Main function"""
142        printers = ugmask = isgroup = None
143        remuser = os.environ.get("REMOTE_USER", "root")   
144        # special hack to accomodate mod_auth_ldap Apache module
145        try :
146            remuser = remuser.split("=")[1].split(",")[0]
147        except IndexError :   
148            pass
149        self.body = "<p>%s</p>\n" % _("Please click on the above button")
150        if self.form.has_key("report") :
151            if self.form.has_key("printers") :
152                printersfield = self.form["printers"]
153                if type(printersfield) != type([]) :
154                    printersfield = [ printersfield ]
155                printers = [self.storage.getPrinter(p.value) for p in printersfield]
156            else :   
157                printers = self.storage.getMatchingPrinters("*")
158            if remuser == "root" :
159                if self.form.has_key("ugmask") :     
160                    ugmask = self.form["ugmask"].value
161                else :     
162                    ugmask = "*"
163            else :       
164                if self.form.has_key("isgroup") :   
165                    user = self.storage.getUser(remuser)
166                    if user.Exists :
167                        ugmask = " ".join([ g.Name for g in self.storage.getUserGroups(user) ])
168                    else :   
169                        ugmask = remuser # result will probably be empty, we don't care
170                else :   
171                    ugmask = remuser
172            if self.form.has_key("isgroup") :   
173                isgroup = 1
174            else :   
175                isgroup = 0
176        self.body += self.htmlListPrinters(printers or [])           
177        self.body += "<br />"
178        self.body += self.htmlUGNamesInput(ugmask)
179        self.body += "<br />"
180        self.body += self.htmlGroupsCheckbox(isgroup)
181        try :
182            if not self.form.has_key("history") :
183                if printers and ugmask :
184                    self.reportingtool = openReporter(admin, "html", printers, ugmask.split(), isgroup)
185                    self.body += "%s" % self.reportingtool.generateReport()
186            else :       
187                if remuser != "root" :
188                    username = remuser
189                elif self.form.has_key("username") :   
190                    username = self.form["username"].value
191                else :   
192                    username = None
193                if username is not None :   
194                    user = self.storage.getUser(username)
195                else :   
196                    user = None
197                if self.form.has_key("printername") :
198                    printer = self.storage.getPrinter(self.form["printername"].value)
199                else :   
200                    printer = None
201                if self.form.has_key("datelimit") :   
202                    datelimit = self.form["datelimit"].value
203                else :   
204                    datelimit = None
205                if self.form.has_key("hostname") :   
206                    hostname = self.form["hostname"].value
207                else :   
208                    hostname = None
209                if self.form.has_key("billingcode") :   
210                    billingcode = self.form["billingcode"].value
211                else :   
212                    billingcode = None
213                self.report = ["<h2>%s</h2>" % _("History")]   
214                history = self.storage.retrieveHistory(user=user, printer=printer, hostname=hostname, billingcode=billingcode, end=datelimit)
215                if not history :
216                    self.report.append("<h3>%s</h3>" % _("Empty"))
217                else :
218                    self.report.append('<table class="pykotatable" border="1">')
219                    headers = [_("Date"), _("Action"), _("User"), _("Printer"), \
220                               _("Hostname"), _("JobId"), _("Number of pages"), \
221                               _("Cost"), _("Copies"), _("Number of bytes"), \
222                               _("Printer's internal counter"), _("Title"), _("Filename"), \
223                               _("Options"), _("MD5Sum"), _("Billing code"), \
224                               _("Precomputed number of pages"), _("Precomputed cost"), _("Pages details") + " " + _("(not supported yet)")]
225                    self.report.append('<tr class="pykotacolsheader">%s</tr>' % "".join(["<th>%s</th>" % h for h in headers]))
226                    oddeven = 0
227                    for job in history :
228                        oddeven += 1
229                        if job.JobAction == "ALLOW" :   
230                            if oddeven % 2 :
231                                oddevenclass = "odd"
232                            else :   
233                                oddevenclass = "even"
234                        else :
235                            oddevenclass = (job.JobAction or "UNKNOWN").lower()
236                        username_url = '<a href="%s?%s">%s</a>' % (os.environ.get("SCRIPT_NAME", ""), urllib.urlencode({"history" : 1, "username" : job.UserName}), job.UserName)
237                        printername_url = '<a href="%s?%s">%s</a>' % (os.environ.get("SCRIPT_NAME", ""), urllib.urlencode({"history" : 1, "printername" : job.PrinterName}), job.PrinterName)
238                        if job.JobHostName :
239                            hostname_url = '<a href="%s?%s">%s</a>' % (os.environ.get("SCRIPT_NAME", ""), urllib.urlencode({"history" : 1, "hostname" : job.JobHostName}), job.JobHostName)
240                        else :   
241                            hostname_url = None
242                        if job.JobBillingCode :
243                            billingcode_url = '<a href="%s?%s">%s</a>' % (os.environ.get("SCRIPT_NAME", ""), urllib.urlencode({"history" : 1, "billingcode" : job.JobBillingCode}), job.JobBillingCode)
244                        else :   
245                            billingcode_url = None
246                        curdate = DateTime.ISO.ParseDateTime(str(job.JobDate)[:19])
247                        self.report.append('<tr class="%s">%s</tr>' % \
248                                              (oddevenclass, \
249                                               "".join(["<td>%s</td>" % (h or "&nbsp;") \
250                                                  for h in (str(curdate)[:19], \
251                                                            _(job.JobAction), \
252                                                            username_url, \
253                                                            printername_url, \
254                                                            hostname_url, \
255                                                            job.JobId, \
256                                                            job.JobSize, \
257                                                            job.JobPrice, \
258                                                            job.JobCopies, \
259                                                            job.JobSizeBytes, \
260                                                            job.PrinterPageCounter, \
261                                                            job.JobTitle, \
262                                                            job.JobFileName, \
263                                                            job.JobOptions, \
264                                                            job.JobMD5Sum, \
265                                                            billingcode_url, \
266                                                            job.PrecomputedJobSize, \
267                                                            job.PrecomputedJobPrice, \
268                                                            job.JobPages)])))
269                    self.report.append('</table>')
270                    dico = { "history" : 1,
271                             "datelimit" : "%04i-%02i-%02i %02i:%02i:%02i" \
272                                                         % (curdate.year, \
273                                                            curdate.month, \
274                                                            curdate.day, \
275                                                            curdate.hour, \
276                                                            curdate.minute, \
277                                                            curdate.second),
278                           }
279                    if user and user.Exists :
280                        dico.update({ "username" : user.Name })
281                    if printer and printer.Exists :
282                        dico.update({ "printername" : printer.Name })
283                    if hostname :   
284                        dico.update({ "hostname" : hostname })
285                    prevurl = "%s?%s" % (os.environ.get("SCRIPT_NAME", ""), urllib.urlencode(dico))
286                    self.report.append('<a href="%s">%s</a>' % (prevurl, _("Previous page")))
287                self.body = "\n".join(self.report)   
288        except :
289                self.body += '<p><font color="red">%s</font></p>' % self.crashed("CGI Error").replace("\n", "<br />")
290           
291if __name__ == "__main__" :
292    utils.reinitcgilocale()
293    admin = PyKotaReportGUI()
294    admin.deferredInit()
295    admin.form = cgi.FieldStorage()
296    admin.guiAction()
297    admin.guiDisplay()
298    try :
299        admin.storage.close()
300    except (TypeError, NameError, AttributeError) :   
301        pass
302       
303    sys.exit(0)
Note: See TracBrowser for help on using the browser.