root / pykota / trunk / bin / pykota @ 873

Revision 873, 7.0 kB (checked in by jalet, 21 years ago)

GPL paragraphs were incorrectly (from memory) copied into the sources.
Two README files were added.
Upgrade script for PostgreSQL pre 1.01 schema was added.

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