#! /usr/bin/python # -*- coding: ISO-8859-15 -*- # PyKota Print Quota Reports generator # # PyKota - Print Quotas for CUPS and LPRng # # (c) 2003, 2004, 2005, 2006, 2007 Jerome Alet # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. # # $Id$ # # import sys import os import cgi import urllib from mx import DateTime from pykota import version from pykota.tool import PyKotaTool, PyKotaToolError from pykota.reporter import PyKotaReporterError, openReporter from pykota.cgifuncs import getLanguagePreference, getCharsetPreference header = """Content-type: text/html;charset=%s %s

PyKota's Logo
PyKota v%s

%s

""" footer = """


%s © %s %s

%s
        

""" class PyKotaReportGUI(PyKotaTool) : """PyKota Administrative GUI""" def guiDisplay(self) : """Displays the administrative interface.""" global header, footer print header % (self.charset, _("PyKota Reports"), \ self.language, self.charset, \ self.config.getLogoLink(), \ self.config.getLogoURL(), version.__version__, \ self.config.getLogoLink(), \ version.__version__, _("PyKota Reports"), \ _("Report")) print self.body print footer % (_("Report"), version.__doc__, version.__years__, version.__author__, version.__gplblurb__) def error(self, message) : """Adds an error message to the GUI's body.""" if message : self.body = '

%s

\n%s' % (message, self.body) def htmlListPrinters(self, selected=[], mask="*") : """Displays the printers multiple selection list.""" printers = self.storage.getMatchingPrinters(mask) selectednames = [p.Name for p in selected] message = '
%s :
' return message def htmlUGNamesInput(self, value="*") : """Input field for user/group names wildcard.""" return _("User / Group names mask") + (' : e.g. jo*' % (value or "*")) def htmlGroupsCheckbox(self, isgroup=0) : """Groups checkbox.""" if isgroup : return _("Groups report") + ' : ' else : return _("Groups report") + ' : ' def guiAction(self) : """Main function""" printers = ugmask = isgroup = None remuser = os.environ.get("REMOTE_USER", "root") # special hack to accomodate mod_auth_ldap Apache module try : remuser = remuser.split("=")[1].split(",")[0] except IndexError : pass self.body = "

%s

\n" % _("Please click on the above button") if self.form.has_key("report") : if self.form.has_key("printers") : printersfield = self.form["printers"] if type(printersfield) != type([]) : printersfield = [ printersfield ] printers = [self.storage.getPrinter(p.value) for p in printersfield] else : printers = self.storage.getMatchingPrinters("*") if remuser == "root" : if self.form.has_key("ugmask") : ugmask = self.form["ugmask"].value else : ugmask = "*" else : if self.form.has_key("isgroup") : user = self.storage.getUser(remuser) if user.Exists : ugmask = " ".join([ g.Name for g in self.storage.getUserGroups(user) ]) else : ugmask = remuser # result will probably be empty, we don't care else : ugmask = remuser if self.form.has_key("isgroup") : isgroup = 1 else : isgroup = 0 self.body += self.htmlListPrinters(printers or []) self.body += "
" self.body += self.htmlUGNamesInput(ugmask) self.body += "
" self.body += self.htmlGroupsCheckbox(isgroup) try : if not self.form.has_key("history") : if printers and ugmask : self.reportingtool = openReporter(admin, "html", printers, ugmask.split(), isgroup) self.body += "%s" % self.reportingtool.generateReport() else : if remuser != "root" : username = remuser elif self.form.has_key("username") : username = self.form["username"].value else : username = None if username is not None : user = self.storage.getUser(username) else : user = None if self.form.has_key("printername") : printer = self.storage.getPrinter(self.form["printername"].value) else : printer = None if self.form.has_key("datelimit") : datelimit = self.form["datelimit"].value else : datelimit = None if self.form.has_key("hostname") : hostname = self.form["hostname"].value else : hostname = None if self.form.has_key("billingcode") : billingcode = self.form["billingcode"].value else : billingcode = None self.report = ["

%s

" % _("History")] history = self.storage.retrieveHistory(user=user, printer=printer, hostname=hostname, billingcode=billingcode, end=datelimit) if not history : self.report.append("

%s

" % _("Empty")) else : self.report.append('') headers = [_("Date"), _("Action"), _("User"), _("Printer"), \ _("Hostname"), _("JobId"), _("Number of pages"), \ _("Cost"), _("Copies"), _("Number of bytes"), \ _("Printer's internal counter"), _("Title"), _("Filename"), \ _("Options"), _("MD5Sum"), _("Billing code"), \ _("Precomputed number of pages"), _("Precomputed cost"), _("Pages details") + " " + _("(not supported yet)")] self.report.append('%s' % "".join(["" % h for h in headers])) oddeven = 0 for job in history : oddeven += 1 if job.JobAction == "ALLOW" : if oddeven % 2 : oddevenclass = "odd" else : oddevenclass = "even" else : oddevenclass = (job.JobAction or "UNKNOWN").lower() username_url = '%s' % (os.environ.get("SCRIPT_NAME", ""), urllib.urlencode({"history" : 1, "username" : job.UserName}), job.UserName) printername_url = '%s' % (os.environ.get("SCRIPT_NAME", ""), urllib.urlencode({"history" : 1, "printername" : job.PrinterName}), job.PrinterName) if job.JobHostName : hostname_url = '%s' % (os.environ.get("SCRIPT_NAME", ""), urllib.urlencode({"history" : 1, "hostname" : job.JobHostName}), job.JobHostName) else : hostname_url = None if job.JobBillingCode : billingcode_url = '%s' % (os.environ.get("SCRIPT_NAME", ""), urllib.urlencode({"history" : 1, "billingcode" : job.JobBillingCode}), job.JobBillingCode) else : billingcode_url = None curdate = DateTime.ISO.ParseDateTime(str(job.JobDate)[:19]) self.report.append('%s' % \ (oddevenclass, \ "".join(["" % (h or " ") \ for h in (str(curdate)[: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, \ job.JobMD5Sum, \ billingcode_url, \ job.PrecomputedJobSize, \ job.PrecomputedJobPrice, \ job.JobPages)]))) self.report.append('
%s
%s
') dico = { "history" : 1, "datelimit" : "%04i-%02i-%02i %02i:%02i:%02i" \ % (curdate.year, \ curdate.month, \ curdate.day, \ curdate.hour, \ curdate.minute, \ curdate.second), } if user and user.Exists : dico.update({ "username" : user.Name }) if printer and printer.Exists : dico.update({ "printername" : printer.Name }) if hostname : dico.update({ "hostname" : hostname }) prevurl = "%s?%s" % (os.environ.get("SCRIPT_NAME", ""), urllib.urlencode(dico)) self.report.append('%s' % (prevurl, _("Previous page"))) self.body = "\n".join(self.report) except : self.body += '

%s

' % self.crashed("CGI Error").replace("\n", "
") if __name__ == "__main__" : admin = PyKotaReportGUI(lang=getLanguagePreference(), charset=getCharsetPreference()) admin.deferredInit() admin.form = cgi.FieldStorage() admin.guiAction() admin.guiDisplay() try : admin.storage.close() except (TypeError, NameError, AttributeError) : pass sys.exit(0)