#! /usr/bin/python
# -*- coding: ISO-8859-15 -*-
# PyKota Print Quota Reports generator
#
# PyKota - Print Quotas for CUPS and LPRng
#
# (c) 2003, 2004, 2005, 2006 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
%s
%s
© %s %s
%s
"""
class PyKotaReportGUI(PyKotaTool) :
"""PyKota Administrative GUI"""
def guiDisplay(self) :
"""Displays the administrative interface."""
global header, footer
print header % (self.getCharset(), _("PyKota Reports"), \
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 : ' % _("Printer")
for printer in printers :
if printer.Name in selectednames :
message += '%s (%s) ' % (printer.Name, printer.Name, printer.Description)
else :
message += '%s (%s) ' % (printer.Name, printer.Name, printer.Description)
message += '
'
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, printer, hostname, 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('' % "".join(["%s " % 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
self.report.append('%s ' % \
(oddevenclass, \
"".join(["%s " % (h or " ") \
for h in (job.JobDate[: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('
')
d = DateTime.ISO.ParseDateTime(job.JobDate)
dico = { "history" : 1,
"datelimit" : "%04i%02i%02i %02i:%02i:%02i" % (d.year, d.month, d.day, d.hour, d.minute, d.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__" :
os.environ["LC_ALL"] = getLanguagePreference()
admin = PyKotaReportGUI(lang=os.environ["LC_ALL"], charset=getCharsetPreference())
admin.deferredInit()
admin.form = cgi.FieldStorage()
admin.guiAction()
admin.guiDisplay()
try :
admin.storage.close()
except (TypeError, NameError, AttributeError) :
pass
sys.exit(0)