root / pykota / trunk / pykota / config.py @ 2074

Revision 2074, 28.2 kB (checked in by jalet, 19 years ago)

Optimize print job parsing by avoiding to pass the job's datas through
PyKota's internal parser if the special construct "software()" is used
with no argument in the 'accounter' directive.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
RevLine 
[695]1# PyKota
[1144]2# -*- coding: ISO-8859-15 -*-
[695]3#
[952]4# PyKota : Print Quotas for CUPS and LPRng
[695]5#
[1257]6# (c) 2003-2004 Jerome Alet <alet@librelogiciel.com>
[873]7# This program is free software; you can redistribute it and/or modify
8# it under the terms of the GNU General Public License as published by
9# the Free Software Foundation; either version 2 of the License, or
10# (at your option) any later version.
[695]11#
[873]12# This program is distributed in the hope that it will be useful,
13# but WITHOUT ANY WARRANTY; without even the implied warranty of
14# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15# GNU General Public License for more details.
16#
17# You should have received a copy of the GNU General Public License
18# along with this program; if not, write to the Free Software
19# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
[695]20#
21# $Id$
22#
23# $Log$
[2074]24# Revision 1.62  2005/02/19 18:16:06  jalet
25# Optimize print job parsing by avoiding to pass the job's datas through
26# PyKota's internal parser if the special construct "software()" is used
27# with no argument in the 'accounter' directive.
28#
[2066]29# Revision 1.61  2005/02/16 00:29:33  jalet
30# Fixed the maxdenybanners directive.
31# Introduced the denyduplicates directive.
32# Fixed some database related glitches.
33#
[2062]34# Revision 1.60  2005/02/14 23:39:50  jalet
35# Introduces the new 'trustjobsize' directive to workaround some printers
36# generating unstable internal page counter values when queried through SNMP.
37#
[2054]38# Revision 1.59  2005/02/13 22:02:29  jalet
39# Big database structure changes. Upgrade script is now included as well as
40# the new LDAP schema.
41# Introduction of the -o | --overcharge command line option to edpykota.
42# The output of repykota is more complete, but doesn't fit in 80 columns anymore.
43# Introduction of the new 'maxdenybanners' directive.
44#
[1968]45# Revision 1.58  2004/12/02 22:01:58  jalet
46# TLS is now supported with the LDAP backend
47#
[1956]48# Revision 1.57  2004/11/22 21:53:38  jalet
49# Added the reject_unknown directive to pykota.conf to reject user/group
50# creation if user or group is unknown to the system
51#
[1916]52# Revision 1.56  2004/11/15 15:23:07  jalet
53# Strips spaces just in case
54#
[1914]55# Revision 1.55  2004/11/15 15:14:06  jalet
56# Preliminary integration of Matt's patch for banners.
57#
[1875]58# Revision 1.54  2004/10/25 14:12:25  jalet
59# For URGENT legal reasons (Italy), a new "privacy" directive was added to pykota.conf
60# to hide print jobs' title, filename, and options.
61#
[1785]62# Revision 1.53  2004/10/06 10:05:47  jalet
63# Minor changes to allow any PyKota administrator to launch enhanced versions
64# of the commands, and not only the root user.
65#
[1757]66# Revision 1.52  2004/09/29 20:20:52  jalet
67# Added the winbind_separator directive to pykota.conf to allow the admin to
68# strip out the Samba/Winbind domain name when users print.
69#
[1687]70# Revision 1.51  2004/08/31 23:29:53  jalet
71# Introduction of the new 'onaccountererror' configuration directive.
72# Small fix for software accounter's return code which can't be None anymore.
73# Make software and hardware accounting code look similar : will be factorized
74# later.
75#
[1646]76# Revision 1.50  2004/07/27 07:07:27  jalet
77# Typo : treshold ==> threshold
78#
[1518]79# Revision 1.49  2004/06/03 21:53:24  jalet
80# crashrecipient directive
81#
[1495]82# Revision 1.48  2004/05/24 22:45:49  jalet
83# New 'enforcement' directive added
84# Polling loop improvements
85#
[1483]86# Revision 1.47  2004/05/18 14:49:20  jalet
87# Big code changes to completely remove the need for "requester" directives,
88# jsut use "hardware(... your previous requester directive's content ...)"
89#
[1475]90# Revision 1.46  2004/05/13 13:59:28  jalet
91# Code simplifications
92#
[1371]93# Revision 1.45  2004/03/01 10:22:30  jalet
94# Can now extract per printer pre and post hooks from the configuration file
95#
[1356]96# Revision 1.44  2004/02/20 14:42:21  jalet
97# Experimental ldapcache directive added
98#
[1353]99# Revision 1.43  2004/02/19 14:20:21  jalet
100# maildomain pykota.conf directive added.
101# Small improvements on mail headers quality.
102#
[1257]103# Revision 1.42  2004/01/08 14:10:32  jalet
104# Copyright year changed.
105#
[1227]106# Revision 1.41  2003/11/29 20:06:20  jalet
107# Added 'utolower' configuration option to convert all usernames to
108# lowercase when printing. All database accesses are still and will
109# remain case sensitive though.
110#
[1192]111# Revision 1.40  2003/11/18 23:43:12  jalet
112# Mailto can be any external command now, as usual.
113#
[1152]114# Revision 1.39  2003/10/08 21:41:38  jalet
115# External policies for printers works !
116# We can now auto-add users on first print, and do other useful things if needed.
117#
[1148]118# Revision 1.38  2003/10/07 22:06:05  jalet
119# Preliminary code to disable job history
120#
[1144]121# Revision 1.37  2003/10/07 09:07:28  jalet
122# Character encoding added to please latest version of Python
123#
[1130]124# Revision 1.36  2003/10/02 20:23:18  jalet
125# Storage caching mechanism added.
126#
[1111]127# Revision 1.35  2003/07/29 09:54:03  jalet
128# Added configurable LDAP mail attribute support
129#
[1105]130# Revision 1.34  2003/07/28 09:11:12  jalet
131# PyKota now tries to add its attributes intelligently in existing LDAP
132# directories.
133#
[1087]134# Revision 1.33  2003/07/16 21:53:07  jalet
135# Really big modifications wrt new configuration file's location and content.
136#
[1077]137# Revision 1.32  2003/07/08 19:43:51  jalet
138# Configurable warning messages.
139# Poor man's treshold value added.
140#
[1068]141# Revision 1.31  2003/07/07 11:49:24  jalet
142# Lots of small fixes with the help of PyChecker
143#
[1041]144# Revision 1.30  2003/06/25 14:10:01  jalet
145# Hey, it may work (edpykota --reset excepted) !
146#
[1029]147# Revision 1.29  2003/06/14 22:44:21  jalet
148# More work on LDAP storage backend.
149#
[1021]150# Revision 1.28  2003/06/10 16:37:54  jalet
151# Deletion of the second user which is not needed anymore.
152# Added a debug configuration field in /etc/pykota.conf
153# All queries can now be sent to the logger in debug mode, this will
154# greatly help improve performance when time for this will come.
155#
[1000]156# Revision 1.27  2003/05/27 23:00:21  jalet
157# Big rewrite of external accounting methods.
158# Should work well now.
159#
[980]160# Revision 1.26  2003/04/30 19:53:58  jalet
161# 1.05
162#
[976]163# Revision 1.25  2003/04/30 13:36:40  jalet
164# Stupid accounting method was added.
165#
[973]166# Revision 1.24  2003/04/29 18:37:54  jalet
167# Pluggable accounting methods (actually doesn't support external scripts)
168#
[956]169# Revision 1.23  2003/04/24 11:53:48  jalet
170# Default policy for unknown users/groups is to DENY printing instead
171# of the previous default to ALLOW printing. This is to solve an accuracy
172# problem. If you set the policy to ALLOW, jobs printed by in nexistant user
173# (from PyKota's POV) will be charged to the next user who prints on the
174# same printer.
175#
[952]176# Revision 1.22  2003/04/23 22:13:57  jalet
177# Preliminary support for LPRng added BUT STILL UNTESTED.
178#
[873]179# Revision 1.21  2003/03/29 13:45:27  jalet
180# GPL paragraphs were incorrectly (from memory) copied into the sources.
181# Two README files were added.
182# Upgrade script for PostgreSQL pre 1.01 schema was added.
183#
[872]184# Revision 1.20  2003/03/29 13:08:28  jalet
185# Configuration is now expected to be found in /etc/pykota.conf instead of
186# in /etc/cups/pykota.conf
187# Installation script can move old config files to the new location if needed.
188# Better error handling if configuration file is absent.
189#
[854]190# Revision 1.19  2003/03/16 09:56:52  jalet
191# Mailto option now accepts some additional values which all mean that
192# nobody will receive any email message.
193# Mailto option now works. Version 1.01 is now officially out.
194#
[853]195# Revision 1.18  2003/03/16 08:00:50  jalet
196# Default hard coded options are now used if they are not set in the
197# configuration file.
198#
[852]199# Revision 1.17  2003/03/15 23:01:28  jalet
200# New mailto option in configuration file added.
201# No time to test this tonight (although it should work).
202#
[804]203# Revision 1.16  2003/02/17 23:01:56  jalet
204# Typos
205#
[802]206# Revision 1.15  2003/02/17 22:55:01  jalet
207# More options can now be set per printer or globally :
208#
[804]209#       admin
210#       adminmail
211#       gracedelay
212#       requester
[802]213#
214# the printer option has priority when both are defined.
215#
[800]216# Revision 1.14  2003/02/17 22:05:50  jalet
217# Storage backend now supports admin and user passwords (untested)
218#
[789]219# Revision 1.13  2003/02/10 11:47:39  jalet
220# Moved some code down into the requesters
221#
[786]222# Revision 1.12  2003/02/10 10:36:33  jalet
223# Small problem wrt external requester
224#
[785]225# Revision 1.11  2003/02/10 08:50:45  jalet
226# External requester seems to be finally ok now
227#
[783]228# Revision 1.10  2003/02/10 08:19:57  jalet
229# tell ConfigParser to return raw data, this allows our own strings
230# interpolations in the requester
231#
[781]232# Revision 1.9  2003/02/10 00:44:38  jalet
233# Typos
234#
[780]235# Revision 1.8  2003/02/10 00:42:17  jalet
236# External requester should be ok (untested)
237# New syntax for configuration file wrt requesters
238#
[773]239# Revision 1.7  2003/02/09 13:05:43  jalet
240# Internationalization continues...
241#
[747]242# Revision 1.6  2003/02/07 22:00:09  jalet
243# Bad cut&paste
244#
[731]245# Revision 1.5  2003/02/06 23:58:05  jalet
246# repykota should be ok
247#
[713]248# Revision 1.4  2003/02/06 09:19:02  jalet
249# More robust behavior (hopefully) when the user or printer is not managed
250# correctly by the Quota System : e.g. cupsFilter added in ppd file, but
251# printer and/or user not 'yet?' in storage.
252#
[708]253# Revision 1.3  2003/02/05 23:26:22  jalet
254# Incorrect handling of grace delay
255#
[707]256# Revision 1.2  2003/02/05 23:09:20  jalet
257# Name conflict
258#
[695]259# Revision 1.1  2003/02/05 21:28:17  jalet
260# Initial import into CVS
261#
262#
263#
264
265import os
266import ConfigParser
267
268class PyKotaConfigError(Exception):
269    """An exception for PyKota config related stuff."""
270    def __init__(self, message = ""):
271        self.message = message
272        Exception.__init__(self, message)
273    def __repr__(self):
274        return self.message
275    __str__ = __repr__
276   
277class PyKotaConfig :
278    """A class to deal with PyKota's configuration."""
279    def __init__(self, directory) :
280        """Reads and checks the configuration file."""
[1785]281        self.isAdmin = 0
282        self.directory = directory
[695]283        self.filename = os.path.join(directory, "pykota.conf")
[872]284        if not os.path.isfile(self.filename) :
285            raise PyKotaConfigError, _("Configuration file %s not found.") % self.filename
[695]286        self.config = ConfigParser.ConfigParser()
287        self.config.read([self.filename])
[1227]288           
289    def isTrue(self, option) :       
290        """Returns 1 if option is set to true, else 0."""
291        if (option is not None) and (option.upper().strip() in ['Y', 'YES', '1', 'ON', 'T', 'TRUE']) :
292            return 1
293        else :   
294            return 0
[695]295                       
296    def getPrinterNames(self) :   
297        """Returns the list of configured printers, i.e. all sections names minus 'global'."""
298        return [pname for pname in self.config.sections() if pname != "global"]
299       
[802]300    def getGlobalOption(self, option, ignore=0) :   
301        """Returns an option from the global section, or raises a PyKotaConfigError if ignore is not set, else returns None."""
302        try :
303            return self.config.get("global", option, raw=1)
304        except (ConfigParser.NoSectionError, ConfigParser.NoOptionError) :   
305            if ignore :
306                return
307            else :
308                raise PyKotaConfigError, _("Option %s not found in section global of %s") % (option, self.filename)
309               
[1192]310    def getPrinterOption(self, printername, option) :   
[802]311        """Returns an option from the printer section, or the global section, or raises a PyKotaConfigError."""
312        globaloption = self.getGlobalOption(option, ignore=1)
313        try :
[1192]314            return self.config.get(printername, option, raw=1)
[802]315        except (ConfigParser.NoSectionError, ConfigParser.NoOptionError) :   
316            if globaloption is not None :
317                return globaloption
318            else :
[1192]319                raise PyKotaConfigError, _("Option %s not found in section %s of %s") % (option, printername, self.filename)
[802]320       
[695]321    def getStorageBackend(self) :   
[800]322        """Returns the storage backend information as a Python mapping."""       
323        backendinfo = {}
[695]324        for option in [ "storagebackend", "storageserver", \
[1087]325                        "storagename", "storageuser", \
[695]326                      ] :
[804]327            backendinfo[option] = self.getGlobalOption(option)
[1087]328        backendinfo["storageuserpw"] = self.getGlobalOption("storageuserpw", ignore=1)  # password is optional
329        backendinfo["storageadmin"] = None
330        backendinfo["storageadminpw"] = None
331        adminconf = ConfigParser.ConfigParser()
[1785]332        filename = os.path.join(self.directory, "pykotadmin.conf")
333        adminconf.read([filename])
[1087]334        if adminconf.sections() : # were we able to read the file ?
335            try :
336                backendinfo["storageadmin"] = adminconf.get("global", "storageadmin", raw=1)
337            except (ConfigParser.NoSectionError, ConfigParser.NoOptionError) :   
[1785]338                raise PyKotaConfigError, _("Option %s not found in section global of %s") % ("storageadmin", filename)
339            else :   
340                self.isAdmin = 1 # We are a PyKota administrator
[1087]341            try :
342                backendinfo["storageadminpw"] = adminconf.get("global", "storageadminpw", raw=1)
343            except (ConfigParser.NoSectionError, ConfigParser.NoOptionError) :   
344                pass # Password is optional
[800]345        return backendinfo
[695]346       
[1029]347    def getLDAPInfo(self) :   
348        """Returns some hints for the LDAP backend."""       
349        ldapinfo = {}
350        for option in [ "userbase", "userrdn", \
[1041]351                        "balancebase", "balancerdn", \
[1029]352                        "groupbase", "grouprdn", "groupmembers", \
353                        "printerbase", "printerrdn", \
354                        "userquotabase", "groupquotabase", \
355                        "jobbase", "lastjobbase", \
[1105]356                        "newuser", "newgroup", \
[1111]357                        "usermail", \
[1029]358                      ] :
[1105]359            ldapinfo[option] = self.getGlobalOption(option).strip()
360        for field in ["newuser", "newgroup"] :
361            if ldapinfo[field].lower().startswith('attach(') :
362                ldapinfo[field] = ldapinfo[field][7:-1]
[1968]363               
364        # should we use TLS, by default (if unset) value is NO       
365        ldapinfo["ldaptls"] = self.isTrue(self.getGlobalOption("ldaptls", ignore=1))
366        ldapinfo["cacert"] = self.getGlobalOption("cacert", ignore=1)
367        if ldapinfo["cacert"] :
368            ldapinfo["cacert"] = ldapinfo["cacert"].strip()
369        if ldapinfo["ldaptls"] :   
370            if not os.access(ldapinfo["cacert"] or "", os.R_OK) :
371                raise PyKotaConfigError, _("Option ldaptls is set, but certificate %s is not readable.") % str(ldapinfo["cacert"])
[1029]372        return ldapinfo
373       
[695]374    def getLoggingBackend(self) :   
375        """Returns the logging backend information."""
[802]376        validloggers = [ "stderr", "system" ] 
[853]377        try :
378            logger = self.getGlobalOption("logger").lower()
379        except PyKotaConfigError :   
380            logger = "system"
[802]381        if logger not in validloggers :             
382            raise PyKotaConfigError, _("Option logger only supports values in %s") % str(validloggers)
383        return logger   
[695]384       
[1192]385    def getAccounterBackend(self, printername) :   
[973]386        """Returns the accounter backend to use for a given printer.
387       
[1475]388           if it is not set, it defaults to 'hardware' which means ask printer
[973]389           for its internal lifetime page counter.
390        """   
[1475]391        validaccounters = [ "hardware", "software" ]     
[1371]392        fullaccounter = self.getPrinterOption(printername, "accounter").strip()
[1483]393        flower = fullaccounter.lower()
394        if flower.startswith("software") or flower.startswith("hardware") :   
[980]395            try :
396                (accounter, args) = [x.strip() for x in fullaccounter.split('(', 1)]
397            except ValueError :   
[1483]398                raise PyKotaConfigError, _("Invalid accounter %s for printer %s") % (fullaccounter, printername)
[980]399            if args.endswith(')') :
[2074]400                args = args[:-1].strip()
401            if (accounter == "hardware") and not args :
[1483]402                raise PyKotaConfigError, _("Invalid accounter %s for printer %s") % (fullaccounter, printername)
[1000]403            return (accounter.lower(), args)   
[1483]404        else :
[1192]405            raise PyKotaConfigError, _("Option accounter in section %s only supports values in %s") % (printername, str(validaccounters))
[973]406       
[1371]407    def getPreHook(self, printername) :   
408        """Returns the prehook command line to launch, or None if unset."""
409        try :
410            return self.getPrinterOption(printername, "prehook").strip()
411        except PyKotaConfigError :   
412            return      # No command to launch in the pre-hook
413           
414    def getPostHook(self, printername) :   
415        """Returns the posthook command line to launch, or None if unset."""
416        try :
417            return self.getPrinterOption(printername, "posthook").strip()
418        except PyKotaConfigError :   
419            return      # No command to launch in the post-hook
420           
[1495]421    def getPrinterEnforcement(self, printername) :   
422        """Returns if quota enforcement should be strict or laxist for the current printer."""
423        validenforcements = [ "STRICT", "LAXIST" ]     
424        try :
425            enforcement = self.getPrinterOption(printername, "enforcement")
426        except PyKotaConfigError :   
427            return "LAXIST"
428        else :   
429            enforcement = enforcement.upper()
430            if enforcement not in validenforcements :
431                raise PyKotaConfigError, _("Option enforcement in section %s only supports values in %s") % (printername, str(validenforcements))
432            return enforcement   
433           
[1687]434    def getPrinterOnAccounterError(self, printername) :   
435        """Returns what must be done whenever the accounter fails."""
436        validactions = [ "CONTINUE", "STOP" ]     
437        try :
438            action = self.getPrinterOption(printername, "onaccountererror")
439        except PyKotaConfigError :   
440            return "STOP"
441        else :   
442            action = action.upper()
443            if action not in validactions :
444                raise PyKotaConfigError, _("Option onaccountererror in section %s only supports values in %s") % (printername, str(validactions))
445            return action 
446           
[1192]447    def getPrinterPolicy(self, printername) :   
[695]448        """Returns the default policy for the current printer."""
[1152]449        validpolicies = [ "ALLOW", "DENY", "EXTERNAL" ]     
[853]450        try :
[1192]451            fullpolicy = self.getPrinterOption(printername, "policy")
[853]452        except PyKotaConfigError :   
[1152]453            return ("DENY", None)
454        else :   
455            try :
456                policy = [x.strip() for x in fullpolicy.split('(', 1)]
457            except ValueError :   
[1192]458                raise PyKotaConfigError, _("Invalid policy %s for printer %s") % (fullpolicy, printername)
[1152]459            if len(policy) == 1 :   
460                policy.append("")
461            (policy, args) = policy   
462            if args.endswith(')') :
463                args = args[:-1]
464            policy = policy.upper()   
465            if (policy == "EXTERNAL") and not args :
[1192]466                raise PyKotaConfigError, _("Invalid policy %s for printer %s") % (fullpolicy, printername)
[1152]467            if policy not in validpolicies :
[1192]468                raise PyKotaConfigError, _("Option policy in section %s only supports values in %s") % (printername, str(validpolicies))
[1152]469            return (policy, args)
[695]470       
[1518]471    def getCrashRecipient(self) :   
472        """Returns the email address of the software crash messages recipient."""
473        try :
474            return self.getGlobalOption("crashrecipient")
475        except :   
476            return
477           
[695]478    def getSMTPServer(self) :   
479        """Returns the SMTP server to use to send messages to users."""
[853]480        try :
481            return self.getGlobalOption("smtpserver")
482        except PyKotaConfigError :   
483            return "localhost"
[695]484       
[1353]485    def getMailDomain(self) :   
486        """Returns the mail domain to use to send messages to users."""
487        try :
488            return self.getGlobalOption("maildomain")
489        except PyKotaConfigError :   
490            return 
491       
[1192]492    def getAdminMail(self, printername) :   
[695]493        """Returns the Email address of the Print Quota Administrator."""
[853]494        try :
[1192]495            return self.getPrinterOption(printername, "adminmail")
[853]496        except PyKotaConfigError :   
497            return "root@localhost"
[695]498       
[1192]499    def getAdmin(self, printername) :   
[695]500        """Returns the full name of the Print Quota Administrator."""
[853]501        try :
[1192]502            return self.getPrinterOption(printername, "admin")
[853]503        except PyKotaConfigError :   
504            return "root"
[708]505       
[1192]506    def getMailTo(self, printername) :   
[852]507        """Returns the recipient of email messages."""
[1192]508        validmailtos = [ "EXTERNAL", "NOBODY", "NONE", "NOONE", "BITBUCKET", "DEVNULL", "BOTH", "USER", "ADMIN" ]
[853]509        try :
[1192]510            fullmailto = self.getPrinterOption(printername, "mailto")
[853]511        except PyKotaConfigError :   
[1192]512            return ("BOTH", None)
513        else :   
514            try :
515                mailto = [x.strip() for x in fullmailto.split('(', 1)]
516            except ValueError :   
517                raise PyKotaConfigError, _("Invalid option mailto %s for printer %s") % (fullmailto, printername)
518            if len(mailto) == 1 :   
519                mailto.append("")
520            (mailto, args) = mailto   
521            if args.endswith(')') :
522                args = args[:-1]
523            mailto = mailto.upper()   
524            if (mailto == "EXTERNAL") and not args :
525                raise PyKotaConfigError, _("Invalid option mailto %s for printer %s") % (fullmailto, printername)
526            if mailto not in validmailtos :
527                raise PyKotaConfigError, _("Option mailto in section %s only supports values in %s") % (printername, str(validmailtos))
528            return (mailto, args)
[852]529       
[2054]530    def getMaxDenyBanners(self, printername) :   
531        """Returns the maximum number of deny banners to be printed for a particular user on a particular printer."""
532        try :
533            maxdb = self.getPrinterOption(printername, "maxdenybanners")
534        except PyKotaConfigError :   
535            return 0 # default value is to forbid printing a deny banner.
536        try :
537            value = int(maxdb.strip())
538            if value < 0 :
539                raise ValueError
540        except (TypeError, ValueError) :   
541            raise PyKotaConfigError, _("Invalid maximal deny banners counter %s") % maxdb
542        else :   
543            return value
544           
[1192]545    def getGraceDelay(self, printername) :   
[708]546        """Returns the grace delay in days."""
[731]547        try :
[1192]548            gd = self.getPrinterOption(printername, "gracedelay")
[853]549        except PyKotaConfigError :   
[1914]550            gd = 7      # default value of 7 days
[853]551        try :
[731]552            return int(gd)
[1077]553        except (TypeError, ValueError) :   
[773]554            raise PyKotaConfigError, _("Invalid grace delay %s") % gd
[1021]555           
[1077]556    def getPoorMan(self) :   
[1646]557        """Returns the poor man's threshold."""
[1077]558        try :
559            pm = self.getGlobalOption("poorman")
560        except PyKotaConfigError :   
[1914]561            pm = 1.0    # default value of 1 unit
[1077]562        try :
563            return float(pm)
564        except (TypeError, ValueError) :   
[1646]565            raise PyKotaConfigError, _("Invalid poor man's threshold %s") % pm
[1077]566           
567    def getPoorWarn(self) :   
568        """Returns the poor man's warning message."""
569        try :
570            return self.getGlobalOption("poorwarn")
571        except PyKotaConfigError :   
572            return _("Your Print Quota account balance is Low.\nSoon you'll not be allowed to print anymore.\nPlease contact the Print Quota Administrator to solve the problem.")
573           
[1192]574    def getHardWarn(self, printername) :   
[1077]575        """Returns the hard limit error message."""
576        try :
[1192]577            return self.getPrinterOption(printername, "hardwarn")
[1077]578        except PyKotaConfigError :   
[1192]579            return _("You are not allowed to print anymore because\nyour Print Quota is exceeded on printer %s.") % printername
[1077]580           
[1192]581    def getSoftWarn(self, printername) :   
[1077]582        """Returns the soft limit error message."""
583        try :
[1192]584            return self.getPrinterOption(printername, "softwarn")
[1077]585        except PyKotaConfigError :   
[1192]586            return _("You will soon be forbidden to print anymore because\nyour Print Quota is almost reached on printer %s.") % printername
[1077]587           
[1875]588    def getPrivacy(self) :       
589        """Returns 1 if privacy is activated, else 0."""
590        return self.isTrue(self.getGlobalOption("privacy", ignore=1))
591       
[1021]592    def getDebug(self) :         
593        """Returns 1 if debugging is activated, else 0."""
[1227]594        return self.isTrue(self.getGlobalOption("debug", ignore=1))
[1130]595           
596    def getCaching(self) :         
597        """Returns 1 if database caching is enabled, else 0."""
[1227]598        return self.isTrue(self.getGlobalOption("storagecaching", ignore=1))
[1148]599           
[1356]600    def getLDAPCache(self) :         
601        """Returns 1 if low-level LDAP caching is enabled, else 0."""
602        return self.isTrue(self.getGlobalOption("ldapcache", ignore=1))
603           
[1148]604    def getDisableHistory(self) :         
605        """Returns 1 if we want to disable history, else 0."""
[1227]606        return self.isTrue(self.getGlobalOption("disablehistory", ignore=1))
607           
608    def getUserNameToLower(self) :         
609        """Returns 1 if we want to convert usernames to lowercase when printing, else 0."""
610        return self.isTrue(self.getGlobalOption("utolower", ignore=1))
[1757]611       
[1956]612    def getRejectUnknown(self) :         
613        """Returns 1 if we want to reject the creation of unknown users or groups, else 0."""
614        return self.isTrue(self.getGlobalOption("reject_unknown", ignore=1))
615       
[2066]616    def getDenyDuplicates(self, printername) :         
617        """Returns 1 if we want to deny duplicate jobs, else 0."""
618        try : 
619            return self.isTrue(self.getPrinterOption(printername, "denyduplicates"))
620        except PyKotaConfigError :   
621            return 0
622       
[1757]623    def getWinbindSeparator(self) :         
624        """Returns the winbind separator's value if it is set, else None."""
625        return self.getGlobalOption("winbind_separator", ignore=1)
[1914]626
627    def getAccountBanner(self, printername) :
628        """Returns which banner(s) to account for: NONE, BOTH, STARTING, ENDING."""
629        validvalues = [ "NONE", "BOTH", "STARTING", "ENDING" ]     
630        try :
631            value = self.getPrinterOption(printername, "accountbanner")
632        except PyKotaConfigError :   
633            return "BOTH"       # Default value of BOTH
634        else :   
[1916]635            value = value.strip().upper()
[1914]636            if value not in validvalues :
[1916]637                raise PyKotaConfigError, _("Option accountbanner in section %s only supports values in %s") % (printername, str(validvalues))
[1914]638            return value 
639
640    def getStartingBanner(self, printername) :
641        """Returns the startingbanner value if set, else None."""
642        try :
[1916]643            return self.getPrinterOption(printername, "startingbanner").strip()
[1914]644        except PyKotaConfigError :
645            return None
646
647    def getEndingBanner(self, printername) :
648        """Returns the endingbanner value if set, else None."""
649        try :
[1916]650            return self.getPrinterOption(printername, "endingbanner").strip()
[1914]651        except PyKotaConfigError :
652            return None
[2062]653           
654    def getTrustJobSize(self, printername) :
655        """Returns the normalized value of the trustjobsize's directive."""
656        try :
657            value = self.getPrinterOption(printername, "trustjobsize").strip().upper()
658        except PyKotaConfigError :
659            return (None, "YES")
660        else :   
661            if value == "YES" :
662                return (None, "YES")
663            try :   
664                (limit, replacement) = [p.strip() for p in value.split(">")[1].split(":")]
665                limit = int(limit)
666                try :
667                    replacement = int(replacement) 
668                except ValueError :   
669                    if replacement != "PRECOMPUTED" :
670                        raise
671                if limit < 0 :
672                    raise ValueError
673                if (replacement != "PRECOMPUTED") and (replacement < 0) :
674                    raise ValueError
675            except (IndexError, ValueError, TypeError) :
676                raise PyKotaConfigError, _("Option trustjobsize for printer %s is incorrect") % printername
677            return (limit, replacement)   
Note: See TracBrowser for help on using the browser.