#! /usr/bin/python # -*- coding: UTF-8 -*- # PyKota Print Quota Reports generator # # PyKota - Print Quotas for CUPS # # (c) 2003, 2004, 2005, 2006, 2007, 2008 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 3 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, see . # # $Id$ # # import sys import os import cgi import urllib from xml.sax import saxutils from mx import DateTime import pykota.appinit from pykota import version, utils from pykota.tool import PyKotaTool from pykota.errors import PyKotaToolError, PyKotaReporterError from pykota.reporter import openReporter 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 content = [ header % (self.charset, _("PyKota Reports"), \ self.config.getLogoLink(), \ self.config.getLogoURL(), version.__version__, \ self.config.getLogoLink(), \ version.__version__, _("PyKota Reports"), \ _("Report")) ] content.append(self.body) content.append(footer % (_("Report"), version.__doc__, version.__years__, version.__author__, saxutils.escape(version.__gplblurb__))) for c in content : sys.stdout.write(c.encode(self.charset, "replace")) sys.stdout.flush() 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__" : utils.reinitcgilocale() admin = PyKotaReportGUI() admin.deferredInit() admin.form = cgi.FieldStorage() admin.guiAction() admin.guiDisplay() try : admin.storage.close() except (TypeError, NameError, AttributeError) : pass sys.exit(0)