root / pykota / trunk / bin / pykota @ 900

Revision 900, 8.1 kB (checked in by jalet, 21 years ago)

Job history added. Upgrade script neutralized for now !

  • 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# This program is free software; you can redistribute it and/or modify
9# it under the terms of the GNU General Public License as published by
10# the Free Software Foundation; either version 2 of the License, or
11# (at your option) any later version.
12#
13# This program is distributed in the hope that it will be useful,
14# but WITHOUT ANY WARRANTY; without even the implied warranty of
15# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16# GNU General Public License for more details.
17#
18# You should have received a copy of the GNU General Public License
19# along with this program; if not, write to the Free Software
20# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
21#
22# $Id$
23#
24# $Log$
25# Revision 1.17  2003/04/10 21:47:20  jalet
26# Job history added. Upgrade script neutralized for now !
27#
28# Revision 1.16  2003/04/08 20:38:08  jalet
29# The last job Id is saved now for each printer, this will probably
30# allow other accounting methods in the future.
31#
32# Revision 1.15  2003/03/29 13:45:27  jalet
33# GPL paragraphs were incorrectly (from memory) copied into the sources.
34# Two README files were added.
35# Upgrade script for PostgreSQL pre 1.01 schema was added.
36#
37# Revision 1.14  2003/03/07 22:16:57  jalet
38# Algorithmically incorrect : last user quota wasn't updated if current
39# user wasn't allowed to print.
40#
41# Revision 1.13  2003/02/27 23:59:28  jalet
42# Stupid bug wrt exception handlingand value conversion
43#
44# Revision 1.12  2003/02/27 23:48:41  jalet
45# Correctly maps PyKota's log levels to syslog log levels
46#
47# Revision 1.11  2003/02/27 22:55:20  jalet
48# WARN log priority doesn't exist.
49#
50# Revision 1.10  2003/02/27 22:43:21  jalet
51# Missing import
52#
53# Revision 1.9  2003/02/27 22:40:26  jalet
54# Correctly handles cases where the printer is off.
55#
56# Revision 1.8  2003/02/09 12:56:53  jalet
57# Internationalization begins...
58#
59# Revision 1.7  2003/02/07 10:23:48  jalet
60# Avoid a possible future name clash
61#
62# Revision 1.6  2003/02/06 22:54:33  jalet
63# warnpykota should be ok
64#
65# Revision 1.5  2003/02/05 22:45:25  jalet
66# Forgotten import
67#
68# Revision 1.4  2003/02/05 22:42:51  jalet
69# Typo
70#
71# Revision 1.3  2003/02/05 22:38:39  jalet
72# Typo
73#
74# Revision 1.2  2003/02/05 22:16:20  jalet
75# DEVICE_URI is undefined outside of CUPS, i.e. for normal command line tools
76#
77# Revision 1.1  2003/02/05 21:28:17  jalet
78# Initial import into CVS
79#
80#
81#
82
83import sys
84import os
85
86from pykota.tool import PyKotaTool, PyKotaToolError
87from pykota.requester import openRequester, PyKotaRequesterError
88
89class PyKotaFilter(PyKotaTool) :   
90    """Class for the PyKota filter."""
91    def __init__(self, username) :
92        PyKotaTool.__init__(self, isfilter=1)
93        self.username = username
94        self.requester = openRequester(self.config, self.printername)
95        self.printerhostname = self.getPrinterHostname()
96   
97    def getPrinterHostname(self) :
98        """Returns the printer hostname."""
99        device_uri = os.environ.get("DEVICE_URI", "")
100        # TODO : check this for more complex urls than ipp://myprinter.dot.com:631/printers/lp
101        try :
102            (backend, destination) = device_uri.split(":", 1) 
103        except ValueError :   
104            raise PyKotaToolError, "Invalid DEVICE_URI : %s\n" % device_uri
105        while destination.startswith("/") :
106            destination = destination[1:]
107        return destination.split("/")[0].split(":")[0]
108       
109    def filterInput(self, inputfile) :
110        """Transparent filter."""
111        mustclose = 0   
112        if inputfile is not None :   
113            infile = open(inputfile, "rb")
114            mustclose = 1
115        else :   
116            infile = sys.stdin
117        data = infile.read(256*1024)   
118        while data :
119            sys.stdout.write(data)
120            data = infile.read(256*1024)
121        if mustclose :   
122            infile.close()
123           
124def main() :   
125    """Do it, and do it right !"""
126    #
127    # This is a CUPS filter, so we should act and die like a CUPS filter when needed
128    narg = len(sys.argv)
129    if narg not in (6, 7) :   
130        sys.stderr.write("ERROR: %s job-id user title copies options [file]\n" % sys.argv[0])
131        return 1
132    elif narg == 7 :   
133        # input file
134        inputfile = sys.argv[6]
135    else :   
136        # stdin
137        inputfile = None
138       
139    #   
140    # According to CUPS documentation, the job id is the second command line argument
141    jobid = sys.argv[1].strip()
142   
143    #   
144    # According to CUPS documentation, the username is the third command line argument
145    username = sys.argv[2].strip()   
146   
147    # Initializes the current tool
148    kotafilter = PyKotaFilter(username)   
149   
150    # Get the page counter directly from the printer itself
151    try :
152        counterbeforejob = kotafilter.requester.getPrinterPageCounter(kotafilter.printerhostname) # TODO use printername instead, make them match from CUPS' config files
153    except PyKotaRequesterError, msg :
154        # can't get actual page counter, assume printer is off, but warns in log
155        kotafilter.logger.log_message("%s" % msg, "warn")
156        counterbeforejob = None
157        printerIsOff = 1
158    else :   
159        printerIsOff = 0
160       
161    # Get the last page counter and last username from the Quota Storage backend
162    printerid = kotafilter.storage.getPrinterId(kotafilter.printername)
163    if printerid is None :
164        # The printer is unknown from the Quota Storage perspective
165        # we let the job pass through, but log a warning message
166        kotafilter.logger.log_message(_("Printer %s not registered in the PyKota system") % kotafilter.printername, "warn")
167    else :   
168        userid = kotafilter.storage.getUserId(username)
169        if userid is None :
170            # The user is unknown from the Quota Storage perspective
171            # we let the job pass through, but log a warning message
172            kotafilter.logger.log_message(_("User %s not registered in the PyKota system") % username, "warn")
173        else :
174            pgc = kotafilter.storage.getPrinterPageCounter(printerid)   
175            if pgc is None :
176                # The printer hasn't been used yet, from PyKota's point of view
177                lasthistoryid = None
178                lastjobid = jobid
179                lastuserid = userid
180                lastusername = username
181                lastpagecounter = counterbeforejob
182            else :   
183                # get last values from Quota Storage
184                (lasthistoryid, lastjobid, lastuserid, lastusername, lastpagecounter) = (pgc["id"], pgc["jobid"], pgc["userid"], pgc["username"], pgc["pagecounter"])
185               
186            # if printer is off then we assume the correct counter value is the last one
187            if printerIsOff :
188                counterbeforejob = lastpagecounter
189               
190            # Update the quota for the previous user on this printer according
191            # to the job size (difference between actual counter and latest one from storage)
192            jobsize = (counterbeforejob - lastpagecounter)   
193            if jobsize >= 0 :
194                kotafilter.storage.updateUserPQuota(lastuserid, printerid, jobsize)
195                kotafilter.storage.updateJobSizeInHistory(lasthistoryid, jobsize)
196                kotafilter.warnUserPQuota(lastusername)
197            else :   
198                kotafilter.logger.log_message(_("Error in page count value %i for user %s on printer %s") % (jobsize, lastusername, kotafilter.printername), "error")
199               
200            # Is the current user allowed to print at all ?
201            action = kotafilter.warnUserPQuota(username)
202           
203            # adds the current job to history   
204            kotafilter.storage.addJobToHistory(jobid, kotafilter.storage.getUserId(username), printerid, counterbeforejob, action)
205           
206            # if not allowed to print then die, else proceed.
207            if action == "DENY" :
208                # No, just die cleanly
209                return 1
210       
211    # pass the job untouched to the underlying layer
212    kotafilter.filterInput(inputfile)     
213   
214    return 0
215
216if __name__ == "__main__" :   
217    sys.exit(main() or 0)
Note: See TracBrowser for help on using the browser.