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

Revision 2062, 27.5 kB (checked in by jalet, 19 years ago)

Introduces the new 'trustjobsize' directive to workaround some printers
generating unstable internal page counter values when queried through SNMP.

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