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

Revision 2054, 26.2 kB (checked in by jalet, 19 years ago)

Big database structure changes. Upgrade script is now included as well as
the new LDAP schema.
Introduction of the -o | --overcharge command line option to edpykota.
The output of repykota is more complete, but doesn't fit in 80 columns anymore.
Introduction of the new 'maxdenybanners' directive.

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