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

Revision 3025, 29.0 kB (checked in by jerome, 18 years ago)

Added the 'noprintingmaxdelay' directive to workaround printers
which don't conform to RFC3805.
Improved the reliability of SNMP and PJL hardware accounting.
PJL still needs some work though...

  • 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, 2005, 2006 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
20#
21# $Id$
22#
23#
24
25import os
26import tempfile
27import ConfigParser
28
29class PyKotaConfigError(Exception):
30    """An exception for PyKota config related stuff."""
31    def __init__(self, message = ""):
32        self.message = message
33        Exception.__init__(self, message)
34    def __repr__(self):
35        return self.message
36    __str__ = __repr__
37   
38class PyKotaConfig :
39    """A class to deal with PyKota's configuration."""
40    def __init__(self, directory) :
41        """Reads and checks the configuration file."""
42        self.isAdmin = 0
43        self.directory = directory
44        self.filename = os.path.join(directory, "pykota.conf")
45        self.adminfilename = os.path.join(directory, "pykotadmin.conf")
46        if not os.access(self.filename, os.R_OK) :
47            raise PyKotaConfigError, _("Configuration file %s can't be read. Please check that the file exists and that your permissions are sufficient.") % self.filename
48        if not os.path.isfile(self.adminfilename) :
49            raise PyKotaConfigError, _("Configuration file %s not found.") % self.adminfilename
50        if os.access(self.adminfilename, os.R_OK) :   
51            self.isAdmin = 1
52        self.config = ConfigParser.ConfigParser()
53        self.config.read([self.filename])
54           
55    def isTrue(self, option) :       
56        """Returns 1 if option is set to true, else 0."""
57        if (option is not None) and (option.strip().upper() in ['Y', 'YES', '1', 'ON', 'T', 'TRUE']) :
58            return 1
59        else :   
60            return 0
61                       
62    def isFalse(self, option) :       
63        """Returns 1 if option is set to false, else 0."""
64        if (option is not None) and (option.strip().upper() in ['N', 'NO', '0', 'OFF', 'F', 'FALSE']) :
65            return 1
66        else :   
67            return 0
68                       
69    def getPrinterNames(self) :   
70        """Returns the list of configured printers, i.e. all sections names minus 'global'."""
71        return [pname for pname in self.config.sections() if pname != "global"]
72       
73    def getGlobalOption(self, option, ignore=0) :   
74        """Returns an option from the global section, or raises a PyKotaConfigError if ignore is not set, else returns None."""
75        try :
76            return self.config.get("global", option, raw=1)
77        except (ConfigParser.NoSectionError, ConfigParser.NoOptionError) :   
78            if ignore :
79                return
80            else :
81                raise PyKotaConfigError, _("Option %s not found in section global of %s") % (option, self.filename)
82               
83    def getPrinterOption(self, printername, option) :   
84        """Returns an option from the printer section, or the global section, or raises a PyKotaConfigError."""
85        globaloption = self.getGlobalOption(option, ignore=1)
86        try :
87            return self.config.get(printername, option, raw=1)
88        except (ConfigParser.NoSectionError, ConfigParser.NoOptionError) :   
89            if globaloption is not None :
90                return globaloption
91            else :
92                raise PyKotaConfigError, _("Option %s not found in section %s of %s") % (option, printername, self.filename)
93       
94    def getStorageBackend(self) :   
95        """Returns the storage backend information as a Python mapping."""       
96        backendinfo = {}
97        backend = self.getGlobalOption("storagebackend").lower()
98        backendinfo["storagebackend"] = backend
99        if backend == "sqlitestorage" :
100            issqlite = 1
101            backendinfo["storagename"] = self.getGlobalOption("storagename")
102            for option in ["storageserver", "storageuser", "storageuserpw"] :
103                backendinfo[option] = None         
104        else :
105            issqlite = 0
106            for option in ["storageserver", "storagename", "storageuser"] :
107                backendinfo[option] = self.getGlobalOption(option)
108            backendinfo["storageuserpw"] = self.getGlobalOption("storageuserpw", ignore=1)  # password is optional
109           
110        backendinfo["storageadmin"] = None
111        backendinfo["storageadminpw"] = None
112        if self.isAdmin :
113            adminconf = ConfigParser.ConfigParser()
114            adminconf.read([self.adminfilename])
115            if adminconf.sections() : # were we able to read the file ?
116                try :
117                    backendinfo["storageadmin"] = adminconf.get("global", "storageadmin", raw=1)
118                except (ConfigParser.NoSectionError, ConfigParser.NoOptionError) :   
119                    if not issqlite :
120                        raise PyKotaConfigError, _("Option %s not found in section global of %s") % ("storageadmin", self.adminfilename)
121                try :
122                    backendinfo["storageadminpw"] = adminconf.get("global", "storageadminpw", raw=1)
123                except (ConfigParser.NoSectionError, ConfigParser.NoOptionError) :   
124                    pass # Password is optional
125                # Now try to overwrite the storagebackend, storageserver
126                # and storagename. This allows admins to use the master LDAP
127                # server directly and users to use the replicas transparently.
128                try :
129                    backendinfo["storagebackend"] = adminconf.get("global", "storagebackend", raw=1)
130                except ConfigParser.NoOptionError :
131                    pass
132                try :
133                    backendinfo["storageserver"] = adminconf.get("global", "storageserver", raw=1)
134                except ConfigParser.NoOptionError :
135                    pass
136                try :
137                    backendinfo["storagename"] = adminconf.get("global", "storagename", raw=1)
138                except ConfigParser.NoOptionError :
139                    pass
140        return backendinfo
141       
142    def getLDAPInfo(self) :   
143        """Returns some hints for the LDAP backend."""       
144        ldapinfo = {}
145        for option in [ "userbase", "userrdn", \
146                        "balancebase", "balancerdn", \
147                        "groupbase", "grouprdn", "groupmembers", \
148                        "printerbase", "printerrdn", \
149                        "userquotabase", "groupquotabase", \
150                        "jobbase", "lastjobbase", "billingcodebase", \
151                        "newuser", "newgroup", \
152                        "usermail", \
153                      ] :
154            ldapinfo[option] = self.getGlobalOption(option).strip()
155        for field in ["newuser", "newgroup"] :
156            if ldapinfo[field].lower().startswith('attach(') :
157                ldapinfo[field] = ldapinfo[field][7:-1]
158               
159        # should we use TLS, by default (if unset) value is NO       
160        ldapinfo["ldaptls"] = self.isTrue(self.getGlobalOption("ldaptls", ignore=1))
161        ldapinfo["cacert"] = self.getGlobalOption("cacert", ignore=1)
162        if ldapinfo["cacert"] :
163            ldapinfo["cacert"] = ldapinfo["cacert"].strip()
164        if ldapinfo["ldaptls"] :   
165            if not os.access(ldapinfo["cacert"] or "", os.R_OK) :
166                raise PyKotaConfigError, _("Option ldaptls is set, but certificate %s is not readable.") % str(ldapinfo["cacert"])
167        return ldapinfo
168       
169    def getLoggingBackend(self) :   
170        """Returns the logging backend information."""
171        validloggers = [ "stderr", "system" ] 
172        try :
173            logger = self.getGlobalOption("logger").lower()
174        except PyKotaConfigError :   
175            logger = "system"
176        if logger not in validloggers :             
177            raise PyKotaConfigError, _("Option logger only supports values in %s") % str(validloggers)
178        return logger   
179       
180    def getLogoURL(self) :
181        """Returns the URL to use for the logo in the CGI scripts."""
182        url = self.getGlobalOption("logourl", ignore=1) or \
183                   "http://www.pykota.com/pykota.png"
184        return url.strip()           
185       
186    def getLogoLink(self) :
187        """Returns the URL to go to when the user clicks on the logo in the CGI scripts."""
188        url = self.getGlobalOption("logolink", ignore=1) or \
189                   "http://www.pykota.com/"
190        return url.strip()           
191   
192    def getPreAccounterBackend(self, printername) :   
193        """Returns the preaccounter backend to use for a given printer."""
194        validaccounters = [ "software" ]     
195        try :
196            fullaccounter = self.getPrinterOption(printername, "preaccounter").strip()
197        except PyKotaConfigError :   
198            return ("software", "")
199        else :   
200            flower = fullaccounter.lower()
201            if flower.startswith("software") :   
202                try :
203                    (accounter, args) = [x.strip() for x in fullaccounter.split('(', 1)]
204                except ValueError :   
205                    raise PyKotaConfigError, _("Invalid preaccounter %s for printer %s") % (fullaccounter, printername)
206                if args.endswith(')') :
207                    args = args[:-1].strip()
208                return ("software", args)
209            else :
210                raise PyKotaConfigError, _("Option preaccounter in section %s only supports values in %s") % (printername, str(validaccounters))
211       
212    def getAccounterBackend(self, printername) :   
213        """Returns the accounter backend to use for a given printer."""
214        validaccounters = [ "hardware", "software" ]     
215        fullaccounter = self.getPrinterOption(printername, "accounter").strip()
216        flower = fullaccounter.lower()
217        if flower.startswith("software") or flower.startswith("hardware") :   
218            try :
219                (accounter, args) = [x.strip() for x in fullaccounter.split('(', 1)]
220            except ValueError :   
221                raise PyKotaConfigError, _("Invalid accounter %s for printer %s") % (fullaccounter, printername)
222            if args.endswith(')') :
223                args = args[:-1].strip()
224            if (accounter == "hardware") and not args :
225                raise PyKotaConfigError, _("Invalid accounter %s for printer %s") % (fullaccounter, printername)
226            return (accounter.lower(), args)
227        else :
228            raise PyKotaConfigError, _("Option accounter in section %s only supports values in %s") % (printername, str(validaccounters))
229       
230    def getPreHook(self, printername) :   
231        """Returns the prehook command line to launch, or None if unset."""
232        try :
233            return self.getPrinterOption(printername, "prehook").strip()
234        except PyKotaConfigError :   
235            return      # No command to launch in the pre-hook
236           
237    def getPostHook(self, printername) :   
238        """Returns the posthook command line to launch, or None if unset."""
239        try :
240            return self.getPrinterOption(printername, "posthook").strip()
241        except PyKotaConfigError :   
242            return      # No command to launch in the post-hook
243           
244    def getStripTitle(self, printername) :   
245        """Returns the striptitle directive's content, or None if unset."""
246        try :
247            return self.getPrinterOption(printername, "striptitle").strip()
248        except PyKotaConfigError :   
249            return      # No prefix to strip off
250           
251    def getAskConfirmation(self, printername) :       
252        """Returns the askconfirmation directive's content, or None if unset."""
253        try :
254            return self.getPrinterOption(printername, "askconfirmation").strip()
255        except PyKotaConfigError :   
256            return      # No overwriting will be done
257           
258    def getOverwriteJobTicket(self, printername) :       
259        """Returns the overwrite_jobticket directive's content, or None if unset."""
260        try :
261            return self.getPrinterOption(printername, "overwrite_jobticket").strip()
262        except PyKotaConfigError :   
263            return      # No overwriting will be done
264       
265    def getUnknownBillingCode(self, printername) :       
266        """Returns the unknown_billingcode directive's content, or the default value if unset."""
267        validvalues = [ "CREATE", "DENY" ]
268        try :
269            fullvalue = self.getPrinterOption(printername, "unknown_billingcode")
270        except PyKotaConfigError :   
271            return ("CREATE", None)
272        else :   
273            try :
274                value = [x.strip() for x in fullvalue.split('(', 1)]
275            except ValueError :   
276                raise PyKotaConfigError, _("Invalid unknown_billingcode directive %s for printer %s") % (fullvalue, printername)
277            if len(value) == 1 :   
278                value.append("")
279            (value, args) = value   
280            if args.endswith(')') :
281                args = args[:-1]
282            value = value.upper()   
283            if (value == "DENY") and not args :
284                return ("DENY", None)
285            if value not in validvalues :
286                raise PyKotaConfigError, _("Directive unknown_billingcode in section %s only supports values in %s") % (printername, str(validvalues))
287            return (value, args)
288       
289    def getPrinterEnforcement(self, printername) :   
290        """Returns if quota enforcement should be strict or laxist for the current printer."""
291        validenforcements = [ "STRICT", "LAXIST" ]     
292        try :
293            enforcement = self.getPrinterOption(printername, "enforcement")
294        except PyKotaConfigError :   
295            return "LAXIST"
296        else :   
297            enforcement = enforcement.upper()
298            if enforcement not in validenforcements :
299                raise PyKotaConfigError, _("Option enforcement in section %s only supports values in %s") % (printername, str(validenforcements))
300            return enforcement   
301           
302    def getPrinterOnBackendError(self, printername) :   
303        """Returns what must be done whenever the real CUPS backend fails."""
304        validactions = [ "CHARGE", "NOCHARGE" ]     
305        try :
306            action = self.getPrinterOption(printername, "onbackenderror")
307        except PyKotaConfigError :   
308            return ["NOCHARGE"]
309        else :   
310            action = action.upper().split(",")
311            error = False
312            for act in action :
313                if act not in validactions :
314                    if act.startswith("RETRY:") :
315                        try :
316                            (num, delay) = [int(p) for p in act[6:].split(":", 2)]
317                        except ValueError :   
318                            error = True
319                    else :       
320                        error = True
321            if error :
322                raise PyKotaConfigError, _("Option onbackenderror in section %s only supports values 'charge', 'nocharge', and 'retry:num:delay'") % printername
323            return action 
324           
325    def getPrinterOnAccounterError(self, printername) :   
326        """Returns what must be done whenever the accounter fails."""
327        validactions = [ "CONTINUE", "STOP" ]     
328        try :
329            action = self.getPrinterOption(printername, "onaccountererror")
330        except PyKotaConfigError :   
331            return "STOP"
332        else :   
333            action = action.upper()
334            if action not in validactions :
335                raise PyKotaConfigError, _("Option onaccountererror in section %s only supports values in %s") % (printername, str(validactions))
336            return action 
337           
338    def getPrinterPolicy(self, printername) :   
339        """Returns the default policy for the current printer."""
340        validpolicies = [ "ALLOW", "DENY", "EXTERNAL" ]     
341        try :
342            fullpolicy = self.getPrinterOption(printername, "policy")
343        except PyKotaConfigError :   
344            return ("DENY", None)
345        else :   
346            try :
347                policy = [x.strip() for x in fullpolicy.split('(', 1)]
348            except ValueError :   
349                raise PyKotaConfigError, _("Invalid policy %s for printer %s") % (fullpolicy, printername)
350            if len(policy) == 1 :   
351                policy.append("")
352            (policy, args) = policy   
353            if args.endswith(')') :
354                args = args[:-1]
355            policy = policy.upper()   
356            if (policy == "EXTERNAL") and not args :
357                raise PyKotaConfigError, _("Invalid policy %s for printer %s") % (fullpolicy, printername)
358            if policy not in validpolicies :
359                raise PyKotaConfigError, _("Option policy in section %s only supports values in %s") % (printername, str(validpolicies))
360            return (policy, args)
361       
362    def getCrashRecipient(self) :   
363        """Returns the email address of the software crash messages recipient."""
364        try :
365            return self.getGlobalOption("crashrecipient")
366        except :   
367            return
368           
369    def getSMTPServer(self) :   
370        """Returns the SMTP server to use to send messages to users."""
371        try :
372            return self.getGlobalOption("smtpserver")
373        except PyKotaConfigError :   
374            return "localhost"
375       
376    def getMailDomain(self) :   
377        """Returns the mail domain to use to send messages to users."""
378        try :
379            return self.getGlobalOption("maildomain")
380        except PyKotaConfigError :   
381            return 
382       
383    def getAdminMail(self, printername) :   
384        """Returns the Email address of the Print Quota Administrator."""
385        try :
386            return self.getPrinterOption(printername, "adminmail")
387        except PyKotaConfigError :   
388            return "root@localhost"
389       
390    def getAdmin(self, printername) :   
391        """Returns the full name of the Print Quota Administrator."""
392        try :
393            return self.getPrinterOption(printername, "admin")
394        except PyKotaConfigError :   
395            return "root"
396       
397    def getMailTo(self, printername) :   
398        """Returns the recipient of email messages."""
399        validmailtos = [ "EXTERNAL", "NOBODY", "NONE", "NOONE", "BITBUCKET", "DEVNULL", "BOTH", "USER", "ADMIN" ]
400        try :
401            fullmailto = self.getPrinterOption(printername, "mailto")
402        except PyKotaConfigError :   
403            return ("BOTH", None)
404        else :   
405            try :
406                mailto = [x.strip() for x in fullmailto.split('(', 1)]
407            except ValueError :   
408                raise PyKotaConfigError, _("Invalid option mailto %s for printer %s") % (fullmailto, printername)
409            if len(mailto) == 1 :   
410                mailto.append("")
411            (mailto, args) = mailto   
412            if args.endswith(')') :
413                args = args[:-1]
414            mailto = mailto.upper()   
415            if (mailto == "EXTERNAL") and not args :
416                raise PyKotaConfigError, _("Invalid option mailto %s for printer %s") % (fullmailto, printername)
417            if mailto not in validmailtos :
418                raise PyKotaConfigError, _("Option mailto in section %s only supports values in %s") % (printername, str(validmailtos))
419            return (mailto, args)
420       
421    def getMaxDenyBanners(self, printername) :   
422        """Returns the maximum number of deny banners to be printed for a particular user on a particular printer."""
423        try :
424            maxdb = self.getPrinterOption(printername, "maxdenybanners")
425        except PyKotaConfigError :   
426            return 0 # default value is to forbid printing a deny banner.
427        try :
428            value = int(maxdb.strip())
429            if value < 0 :
430                raise ValueError
431        except (TypeError, ValueError) :   
432            raise PyKotaConfigError, _("Invalid maximal deny banners counter %s") % maxdb
433        else :   
434            return value
435           
436    def getGraceDelay(self, printername) :   
437        """Returns the grace delay in days."""
438        try :
439            gd = self.getPrinterOption(printername, "gracedelay")
440        except PyKotaConfigError :   
441            gd = 7      # default value of 7 days
442        try :
443            return int(gd)
444        except (TypeError, ValueError) :   
445            raise PyKotaConfigError, _("Invalid grace delay %s") % gd
446           
447    def getPoorMan(self) :   
448        """Returns the poor man's threshold."""
449        try :
450            pm = self.getGlobalOption("poorman")
451        except PyKotaConfigError :   
452            pm = 1.0    # default value of 1 unit
453        try :
454            return float(pm)
455        except (TypeError, ValueError) :   
456            raise PyKotaConfigError, _("Invalid poor man's threshold %s") % pm
457           
458    def getBalanceZero(self) :   
459        """Returns the value of the zero for balance limitation."""
460        try :
461            bz = self.getGlobalOption("balancezero")
462        except PyKotaConfigError :   
463            bz = 0.0    # default value, zero is 0.0
464        try :
465            return float(bz)
466        except (TypeError, ValueError) :   
467            raise PyKotaConfigError, _("Invalid balancezero value %s") % bz
468           
469    def getPoorWarn(self) :   
470        """Returns the poor man's warning message."""
471        try :
472            return self.getGlobalOption("poorwarn")
473        except PyKotaConfigError :   
474            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.")
475           
476    def getHardWarn(self, printername) :   
477        """Returns the hard limit error message."""
478        try :
479            return self.getPrinterOption(printername, "hardwarn")
480        except PyKotaConfigError :   
481            return _("You are not allowed to print anymore because\nyour Print Quota is exceeded on printer %s.") % printername
482           
483    def getSoftWarn(self, printername) :   
484        """Returns the soft limit error message."""
485        try :
486            return self.getPrinterOption(printername, "softwarn")
487        except PyKotaConfigError :   
488            return _("You will soon be forbidden to print anymore because\nyour Print Quota is almost reached on printer %s.") % printername
489           
490    def getPrivacy(self) :       
491        """Returns 1 if privacy is activated, else 0."""
492        return self.isTrue(self.getGlobalOption("privacy", ignore=1))
493       
494    def getDebug(self) :         
495        """Returns 1 if debugging is activated, else 0."""
496        return self.isTrue(self.getGlobalOption("debug", ignore=1))
497           
498    def getCaching(self) :         
499        """Returns 1 if database caching is enabled, else 0."""
500        return self.isTrue(self.getGlobalOption("storagecaching", ignore=1))
501           
502    def getLDAPCache(self) :         
503        """Returns 1 if low-level LDAP caching is enabled, else 0."""
504        return self.isTrue(self.getGlobalOption("ldapcache", ignore=1))
505           
506    def getDisableHistory(self) :         
507        """Returns 1 if we want to disable history, else 0."""
508        return self.isTrue(self.getGlobalOption("disablehistory", ignore=1))
509           
510    def getUserNameToLower(self) :         
511        """Returns 1 if we want to convert usernames to lowercase when printing, else 0."""
512        return self.isTrue(self.getGlobalOption("utolower", ignore=1))
513       
514    def getRejectUnknown(self) :         
515        """Returns 1 if we want to reject the creation of unknown users or groups, else 0."""
516        return self.isTrue(self.getGlobalOption("reject_unknown", ignore=1))
517       
518    def getPrinterKeepFiles(self, printername) :         
519        """Returns 1 if files must be kept on disk, else 0."""
520        try : 
521            return self.isTrue(self.getPrinterOption(printername, "keepfiles"))
522        except PyKotaConfigError :   
523            return 0
524           
525    def getPrinterDirectory(self, printername) :         
526        """Returns the path to our working directory, else a directory suitable for temporary files."""
527        try : 
528            return self.getPrinterOption(printername, "directory").strip()
529        except PyKotaConfigError :   
530            return tempfile.gettempdir()
531           
532    def getDenyDuplicates(self, printername) :         
533        """Returns 1 or a command if we want to deny duplicate jobs, else 0."""
534        try : 
535            denyduplicates = self.getPrinterOption(printername, "denyduplicates")
536        except PyKotaConfigError :   
537            return 0
538        else :   
539            if self.isTrue(denyduplicates) :
540                return 1
541            elif self.isFalse(denyduplicates) :
542                return 0
543            else :   
544                # it's a command to run.
545                return denyduplicates
546               
547    def getDuplicatesDelay(self, printername) :         
548        """Returns the number of seconds after which two identical jobs are not considered a duplicate anymore."""
549        try : 
550            duplicatesdelay = self.getPrinterOption(printername, "duplicatesdelay")
551        except PyKotaConfigError :   
552            return 0
553        else :   
554            try :
555                return int(duplicatesdelay)
556            except (TypeError, ValueError) :
557                raise PyKotaConfigError, _("Incorrect value %s for the duplicatesdelay directive in section %s") % (str(duplicatesdelay), printername)
558       
559    def getNoPrintingMaxDelay(self, printername) :         
560        """Returns the max number of seconds to wait for the printer to be in 'printing' mode."""
561        try : 
562            maxdelay = self.getPrinterOption(printername, "noprintingmaxdelay")
563        except PyKotaConfigError :   
564            return None         # tells to use hardcoded value
565        else :   
566            try :
567                maxdelay = int(maxdelay)
568                if maxdelay < 0 :
569                    raise ValueError
570            except (TypeError, ValueError) :
571                raise PyKotaConfigError, _("Incorrect value %s for the noprintingmaxdelay directive in section %s") % (str(maxdelay), printername)
572            else :   
573                return maxdelay
574       
575    def getWinbindSeparator(self) :         
576        """Returns the winbind separator's value if it is set, else None."""
577        return self.getGlobalOption("winbind_separator", ignore=1)
578
579    def getAccountBanner(self, printername) :
580        """Returns which banner(s) to account for: NONE, BOTH, STARTING, ENDING."""
581        validvalues = [ "NONE", "BOTH", "STARTING", "ENDING" ]     
582        try :
583            value = self.getPrinterOption(printername, "accountbanner")
584        except PyKotaConfigError :   
585            return "BOTH"       # Default value of BOTH
586        else :   
587            value = value.strip().upper()
588            if value not in validvalues :
589                raise PyKotaConfigError, _("Option accountbanner in section %s only supports values in %s") % (printername, str(validvalues))
590            return value 
591
592    def getStartingBanner(self, printername) :
593        """Returns the startingbanner value if set, else None."""
594        try :
595            return self.getPrinterOption(printername, "startingbanner").strip()
596        except PyKotaConfigError :
597            return None
598
599    def getEndingBanner(self, printername) :
600        """Returns the endingbanner value if set, else None."""
601        try :
602            return self.getPrinterOption(printername, "endingbanner").strip()
603        except PyKotaConfigError :
604            return None
605           
606    def getTrustJobSize(self, printername) :
607        """Returns the normalized value of the trustjobsize's directive."""
608        try :
609            value = self.getPrinterOption(printername, "trustjobsize").strip().upper()
610        except PyKotaConfigError :
611            return (None, "YES")
612        else :   
613            if value == "YES" :
614                return (None, "YES")
615            try :   
616                (limit, replacement) = [p.strip() for p in value.split(">")[1].split(":")]
617                limit = int(limit)
618                try :
619                    replacement = int(replacement) 
620                except ValueError :   
621                    if replacement != "PRECOMPUTED" :
622                        raise
623                if limit < 0 :
624                    raise ValueError
625                if (replacement != "PRECOMPUTED") and (replacement < 0) :
626                    raise ValueError
627            except (IndexError, ValueError, TypeError) :
628                raise PyKotaConfigError, _("Option trustjobsize for printer %s is incorrect") % printername
629            return (limit, replacement)   
Note: See TracBrowser for help on using the browser.