root / pykota / trunk / bin / pykota @ 852

Revision 832, 6.4 kB (checked in by jalet, 21 years ago)

Algorithmically incorrect : last user quota wasn't updated if current
user wasn't allowed to print.

  • 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/env python
2
3# PyKota accounting filter
4#
5# PyKota - Print Quotas for CUPS
6#
7# (c) 2003 Jerome Alet <alet@librelogiciel.com>
8# You're welcome to redistribute this software under the
9# terms of the GNU General Public Licence version 2.0
10# or, at your option, any higher version.
11#
12# You can read the complete GNU GPL in the file COPYING
13# which should come along with this software, or visit
14# the Free Software Foundation's WEB site http://www.fsf.org
15#
16# $Id$
17#
18# $Log$
19# Revision 1.14  2003/03/07 22:16:57  jalet
20# Algorithmically incorrect : last user quota wasn't updated if current
21# user wasn't allowed to print.
22#
23# Revision 1.13  2003/02/27 23:59:28  jalet
24# Stupid bug wrt exception handlingand value conversion
25#
26# Revision 1.12  2003/02/27 23:48:41  jalet
27# Correctly maps PyKota's log levels to syslog log levels
28#
29# Revision 1.11  2003/02/27 22:55:20  jalet
30# WARN log priority doesn't exist.
31#
32# Revision 1.10  2003/02/27 22:43:21  jalet
33# Missing import
34#
35# Revision 1.9  2003/02/27 22:40:26  jalet
36# Correctly handles cases where the printer is off.
37#
38# Revision 1.8  2003/02/09 12:56:53  jalet
39# Internationalization begins...
40#
41# Revision 1.7  2003/02/07 10:23:48  jalet
42# Avoid a possible future name clash
43#
44# Revision 1.6  2003/02/06 22:54:33  jalet
45# warnpykota should be ok
46#
47# Revision 1.5  2003/02/05 22:45:25  jalet
48# Forgotten import
49#
50# Revision 1.4  2003/02/05 22:42:51  jalet
51# Typo
52#
53# Revision 1.3  2003/02/05 22:38:39  jalet
54# Typo
55#
56# Revision 1.2  2003/02/05 22:16:20  jalet
57# DEVICE_URI is undefined outside of CUPS, i.e. for normal command line tools
58#
59# Revision 1.1  2003/02/05 21:28:17  jalet
60# Initial import into CVS
61#
62#
63#
64
65import sys
66import os
67
68from pykota.tool import PyKotaTool, PyKotaToolError
69from pykota.requester import openRequester, PyKotaRequesterError
70
71class PyKotaFilter(PyKotaTool) :   
72    """Class for the PyKota filter."""
73    def __init__(self, username) :
74        PyKotaTool.__init__(self, isfilter=1)
75        self.username = username
76        self.requester = openRequester(self.config, self.printername)
77        self.printerhostname = self.getPrinterHostname()
78   
79    def getPrinterHostname(self) :
80        """Returns the printer hostname."""
81        device_uri = os.environ.get("DEVICE_URI", "")
82        # TODO : check this for more complex urls than ipp://myprinter.dot.com:631/printers/lp
83        try :
84            (backend, destination) = device_uri.split(":", 1) 
85        except ValueError :   
86            raise PyKotaToolError, "Invalid DEVICE_URI : %s\n" % device_uri
87        while destination.startswith("/") :
88            destination = destination[1:]
89        return destination.split("/")[0].split(":")[0]
90       
91    def filterInput(self, inputfile) :
92        """Transparent filter."""
93        mustclose = 0   
94        if inputfile is not None :   
95            infile = open(inputfile, "rb")
96            mustclose = 1
97        else :   
98            infile = sys.stdin
99        data = infile.read(256*1024)   
100        while data :
101            sys.stdout.write(data)
102            data = infile.read(256*1024)
103        if mustclose :   
104            infile.close()
105           
106def main() :   
107    """Do it, and do it right !"""
108    #
109    # This is a CUPS filter, so we should act and die like a CUPS filter when needed
110    narg = len(sys.argv)
111    if narg not in (6, 7) :   
112        sys.stderr.write("ERROR: %s job-id user title copies options [file]\n" % sys.argv[0])
113        return 1
114    elif narg == 7 :   
115        # input file
116        inputfile = sys.argv[6]
117    else :   
118        # stdin
119        inputfile = None
120       
121    #   
122    # According to CUPS documentation, the username is the third command line argument
123    username = sys.argv[2].strip()   
124   
125    # Initializes the current tool
126    kotafilter = PyKotaFilter(username)   
127   
128    # Get the page counter directly from the printer itself
129    try :
130        counterbeforejob = kotafilter.requester.getPrinterPageCounter(kotafilter.printerhostname) # TODO use printername instead, make them match from CUPS' config files
131    except PyKotaRequesterError, msg :
132        # can't get actual page counter, assume printer is off, but warns in log
133        kotafilter.logger.log_message("%s" % msg, "warn")
134        printerIsOff = 1
135    else :   
136        printerIsOff = 0
137       
138    # Get the last page counter and last username from the Quota Storage backend
139    pgc = kotafilter.storage.getPrinterPageCounter(kotafilter.printername)   
140    if pgc is None :
141        # The printer is unknown from the Quota Storage perspective
142        # we let the job pass through, but log a warning message
143        kotafilter.logger.log_message(_("Printer %s not registered in the PyKota system") % kotafilter.printername, "warn")
144    else :   
145        # get last values from Quota Storage
146        (lastpagecounter, lastusername) = (pgc["pagecounter"], pgc["lastusername"])
147       
148        # if printer is off then we assume the correct counter value is the last one
149        if printerIsOff :
150            counterbeforejob = lastpagecounter
151           
152        # Update the last page counter and last username in the Quota Storage backend
153        # set them to current user and
154        kotafilter.storage.updatePrinterPageCounter(kotafilter.printername, username, counterbeforejob)
155       
156        # Was the printer ever used ?
157        if (lastpagecounter is None) or (lastusername is None) :
158            lastusername = username
159            lastpagecounter = counterbeforejob
160           
161        # Update the quota for the previous user on this printer according
162        # to the job size (difference between actual counter and latest one from storage)
163        jobsize = (counterbeforejob - lastpagecounter)   
164        if jobsize >= 0 :
165            kotafilter.storage.updateUserPQuota(lastusername, kotafilter.printername, jobsize)
166            kotafilter.warnUserPQuota(lastusername)
167        else :   
168            kotafilter.logger.log_message(_("Error in page count value %i for user %s on printer %s") % (jobsize, kotafilter.printername, lastusername), "error")
169           
170        # Is the current user allowed to print at all ?
171        # if no then die, else proceed.
172        action = kotafilter.warnUserPQuota(username)
173        if action == "DENY" :
174            # No, just die cleanly
175            return 1
176       
177    # pass the job untouched to the underlying layer
178    kotafilter.filterInput(inputfile)     
179   
180    return 0
181
182if __name__ == "__main__" :   
183    sys.exit(main() or 0)
Note: See TracBrowser for help on using the browser.