Changeset 1196 for pykota/trunk
- Timestamp:
- 11/20/03 00:19:38 (21 years ago)
- Location:
- pykota/trunk
- Files:
-
- 5 modified
Legend:
- Unmodified
- Added
- Removed
-
pykota/trunk/bin/cupspykota
r1191 r1196 24 24 # 25 25 # $Log$ 26 # Revision 1.11 2003/11/19 23:19:35 jalet 27 # Code refactoring work. 28 # Explicit redirection to /dev/null has to be set in external policy now, just 29 # like in external mailto. 30 # 26 31 # Revision 1.10 2003/11/18 17:54:24 jalet 27 32 # SIGTERMs are now transmitted to original backends. … … 69 74 import signal 70 75 71 from pykota.tool import PyKota Tool, PyKotaToolError76 from pykota.tool import PyKotaFilterOrBackend, PyKotaToolError 72 77 from pykota.config import PyKotaConfigError 73 78 from pykota.storage import PyKotaStorageError 74 from pykota.accounter import openAccounter,PyKotaAccounterError75 from pykota.requester import openRequester,PyKotaRequesterError79 from pykota.accounter import PyKotaAccounterError 80 from pykota.requester import PyKotaRequesterError 76 81 77 82 class PyKotaPopen3(popen2.Popen3) : … … 96 101 os._exit(1) 97 102 98 class PyKotaBackend(PyKotaTool) :99 """Class for the PyKota backend."""100 def __init__(self) :101 PyKotaTool.__init__(self)102 (self.printingsystem, \103 self.printerhostname, \104 self.printername, \105 self.username, \106 self.jobid, \107 self.inputfile, \108 self.copies, \109 self.title, \110 self.options, \111 self.originalbackend) = self.extractCUPSInfo()112 self.accounter = openAccounter(self)113 114 def extractCUPSInfo(self) :115 """Returns a tuple (printingsystem, printerhostname, printername, username, jobid, filename, title, options, backend).116 117 Returns (None, None, None, None, None, None, None, None, None, None) if no printing system is recognized.118 """119 # Try to detect CUPS120 if os.environ.has_key("CUPS_SERVERROOT") and os.path.isdir(os.environ.get("CUPS_SERVERROOT", "")) :121 if len(sys.argv) == 7 :122 inputfile = sys.argv[6]123 else :124 inputfile = None125 126 # the DEVICE_URI environment variable's value is127 # prefixed with "cupspykota:" otherwise we wouldn't128 # be called. We have to remove this from the environment129 # before launching the real backend.130 fulldevice_uri = os.environ.get("DEVICE_URI", "")131 device_uri = fulldevice_uri[len("cupspykota:"):]132 if device_uri.startswith("//") : # lpd (at least)133 device_uri = device_uri[2:]134 os.environ["DEVICE_URI"] = device_uri135 # TODO : check this for more complex urls than ipp://myprinter.dot.com:631/printers/lp136 try :137 (backend, destination) = device_uri.split(":", 1)138 except ValueError :139 raise PyKotaToolError, "Invalid DEVICE_URI : %s\n" % device_uri140 while destination.startswith("/") :141 destination = destination[1:]142 printerhostname = destination.split("/")[0].split(":")[0]143 return ("CUPS", \144 printerhostname, \145 os.environ.get("PRINTER"), \146 sys.argv[2].strip(), \147 sys.argv[1].strip(), \148 inputfile, \149 int(sys.argv[4].strip()), \150 sys.argv[3], \151 sys.argv[5], \152 backend)153 else :154 self.logger.log_message(_("Printing system unknown, args=%s") % " ".join(sys.argv), "warn")155 return (None, None, None, None, None, None, None, None, None, None) # Unknown printing system156 157 def format_commandline(prt, usr, cmdline) :158 """Passes printer and user names on the command line."""159 printer = prt.Name160 user = usr.Name161 # we don't want the external command's standard162 # output to break the print job's data, but we163 # want to keep its standard error164 return "%s >/dev/null" % (cmdline % locals())165 166 103 gotSigTerm = 0 167 104 def sigterm_handler(signum, frame) : … … 208 145 action = "POLICY_ALLOW" 209 146 elif policy == "EXTERNAL" : 210 commandline = format_commandline(printer, user, args)147 commandline = thebackend.formatCommandLine(args, user, printer) 211 148 thebackend.logger.log_message(_("User %s not registered in the PyKota system, applying external policy (%s) for printer %s") % (thebackend.username, commandline, thebackend.printername), "info") 212 149 if os.system(commandline) : … … 472 409 try : 473 410 # Initializes the backend 474 kotabackend = PyKota Backend()411 kotabackend = PyKotaFilterOrBackend() 475 412 retcode = main(kotabackend) 476 except (PyKotaToolError, PyKotaConfigError, PyKotaStorageError, PyKotaAccounterError, AttributeError, KeyError, IndexError, ValueError, TypeError, IOError), msg :413 except (PyKotaToolError, PyKotaConfigError, PyKotaStorageError, PyKotaAccounterError, PyKotaRequesterError, AttributeError, KeyError, IndexError, ValueError, TypeError, IOError), msg : 477 414 sys.stderr.write("ERROR : cupspykota backend failed (%s)\n" % msg) 478 415 sys.stderr.flush() -
pykota/trunk/bin/pykota
r1177 r1196 24 24 # 25 25 # $Log$ 26 # Revision 1.45 2003/11/19 23:19:37 jalet 27 # Code refactoring work. 28 # Explicit redirection to /dev/null has to be set in external policy now, just 29 # like in external mailto. 30 # 26 31 # Revision 1.44 2003/11/08 16:05:31 jalet 27 32 # CUPS backend added for people to experiment. … … 186 191 from pykota.config import PyKotaConfigError 187 192 from pykota.storage import PyKotaStorageError 188 from pykota.accounter import openAccounter, PyKotaAccounterError 189 190 class PyKotaFilter(PyKotaTool) : 191 """Class for the PyKota filter.""" 192 def __init__(self) : 193 PyKotaTool.__init__(self) 194 (self.printingsystem, self.printerhostname, self.printername, self.username, self.jobid, self.inputfile, self.copies) = self.extractInfoFromCupsOrLprng() 195 self.accounter = openAccounter(self) 196 197 def extractInfoFromCupsOrLprng(self) : 198 """Returns a tuple (printingsystem, printerhostname, printername, username, jobid, filename) depending on the printing system in use (as seen by the print filter). 199 200 Returns (None, None, None, None, None, None, None) if no printing system is recognized. 201 """ 202 # Try to detect CUPS 203 if os.environ.has_key("CUPS_SERVERROOT") and os.path.isdir(os.environ.get("CUPS_SERVERROOT", "")) : 204 if len(sys.argv) == 7 : 205 inputfile = sys.argv[6] 206 else : 207 inputfile = None 208 209 device_uri = os.environ.get("DEVICE_URI", "") 210 # TODO : check this for more complex urls than ipp://myprinter.dot.com:631/printers/lp 211 try : 212 (backend, destination) = device_uri.split(":", 1) 213 except ValueError : 214 raise PyKotaToolError, "Invalid DEVICE_URI : %s\n" % device_uri 215 while destination.startswith("/") : 216 destination = destination[1:] 217 printerhostname = destination.split("/")[0].split(":")[0] 218 return ("CUPS", printerhostname, os.environ.get("PRINTER"), sys.argv[2].strip(), sys.argv[1].strip(), inputfile, int(sys.argv[4].strip())) 219 else : 220 # Try to detect LPRng 221 jseen = Pseen = nseen = rseen = Kseen = None 222 for arg in sys.argv : 223 if arg.startswith("-j") : 224 jseen = arg[2:].strip() 225 elif arg.startswith("-n") : 226 nseen = arg[2:].strip() 227 elif arg.startswith("-P") : 228 Pseen = arg[2:].strip() 229 elif arg.startswith("-r") : 230 rseen = arg[2:].strip() 231 elif arg.startswith("-K") or arg.startswith("-#") : 232 Kseen = int(arg[2:].strip()) 233 if Kseen is None : 234 Kseen = 1 # we assume the user wants at least one copy... 235 if (rseen is None) and jseen and Pseen and nseen : 236 self.logger.log_message(_("Printer hostname undefined, set to 'localhost'"), "warn") 237 rseen = "localhost" 238 if jseen and Pseen and nseen and rseen : 239 # job is always in stdin (None) 240 return ("LPRNG", rseen, Pseen, nseen, jseen, None, Kseen) 241 self.logger.log_message(_("Printing system unknown, args=%s") % " ".join(sys.argv), "warn") 242 return (None, None, None, None, None, None, None) # Unknown printing system 243 193 from pykota.accounter import PyKotaAccounterError 194 from pykota.requester import PyKotaRequesterError 195 196 class PyKotaFilter(PyKotaFilterOrBackend) : 197 """A class for the pykota filter.""" 244 198 def acceptJob(self) : 245 199 """Returns the exit code needed by the printing backend to accept the job and print it.""" … … 262 216 return -1 263 217 264 def format_commandline(prt, usr, cmdline) :265 """Passes printer and user names on the command line."""266 printer = prt.Name267 user = usr.Name268 # we don't want the external command's standard269 # output to break the print job's data, but we270 # want to keep its standard error271 return "%s >/dev/null" % (cmdline % locals())272 273 218 def main(thefilter) : 274 219 """Do it, and do it right !""" … … 300 245 action = "POLICY_ALLOW" 301 246 elif policy == "EXTERNAL" : 302 commandline = format_commandline(printer, user, args)247 commandline = thefilter.formatCommandLine(args, user, printer) 303 248 thefilter.logger.log_message(_("User %s not registered in the PyKota system, applying external policy (%s) for printer %s") % (thefilter.username, commandline, thefilter.printername), "info") 304 249 if os.system(commandline) : … … 342 287 kotafilter = PyKotaFilter() 343 288 retcode = main(kotafilter) 344 except (PyKotaToolError, PyKotaConfigError, PyKotaStorageError, PyKotaAccounterError, AttributeError, KeyError, IndexError, ValueError, TypeError, IOError), msg :289 except (PyKotaToolError, PyKotaConfigError, PyKotaStorageError, PyKotaAccounterError, PyKotaRequesterError, AttributeError, KeyError, IndexError, ValueError, TypeError, IOError), msg : 345 290 sys.stderr.write("ERROR : PyKota filter failed (%s)\n" % msg) 346 291 sys.stderr.flush() -
pykota/trunk/conf/pykota.conf.sample
r1193 r1196 340 340 # if he is unknown. Example : 341 341 # 342 # policy: external(/usr/bin/edpykota --add --printer %(printer)s --softlimit 50 --hardlimit 60 %(user)s) 343 # 344 # NB : '%(user)s' and '%(printer)s' will be automatically replaced 345 # by the user and printer names. 342 # policy: external(/usr/bin/edpykota --add --printer %(printer)s --softlimit 50 --hardlimit 60 %(user)s >/dev/null) 346 343 # 347 344 # Of course you can launch any command of your choice with this, e.g. : 348 345 # 349 # policy: external(/usr/local/bin/myadminscript.sh %(user)s) 346 # policy: external(/usr/local/bin/myadminscript.sh %(user)s >/dev/null) 347 348 # You can use : 349 # 350 # '%(username)s' will contain the user's name 351 # '%(printername)s' will contain the printer's name 352 # 353 # On your command line, to pass arguments to your command. 354 # 355 # NB : Don't forget to redirect your command's standard output somewhere 356 # (e.g. >/dev/null) so that there's no perturbation to the underlying 357 # layer (filter or backend) 358 # 359 # If the user still doesn't exist after external policy command was 360 # launched (the external command didn't add it), or if an error occured 361 # during the execution of the external policy command, the job is rejected. 350 362 # 351 363 policy: deny -
pykota/trunk/NEWS
r1194 r1196 23 23 24 24 - 1.16alpha10 : 25 26 - Some modifications done to external policy handling. 27 See sample configuration file for details. 25 28 26 29 - Spanish translation added. -
pykota/trunk/pykota/tool.py
r1193 r1196 22 22 # 23 23 # $Log$ 24 # Revision 1.57 2003/11/19 23:19:38 jalet 25 # Code refactoring work. 26 # Explicit redirection to /dev/null has to be set in external policy now, just 27 # like in external mailto. 28 # 24 29 # Revision 1.56 2003/11/19 07:40:20 jalet 25 30 # Missing import statement. … … 234 239 235 240 from pykota import version, config, storage, logger 241 from pykota.accounter import openAccounter 236 242 237 243 class PyKotaToolError(Exception): … … 514 520 return action 515 521 516 def externalMailTo(self, cmd, action, user, printer name, message) :522 def externalMailTo(self, cmd, action, user, printer, message) : 517 523 """Warns the user with an external command.""" 518 524 username = user.Name 525 printername = printer.Name 519 526 email = user.Email or user.Name 520 527 if "@" not in email : … … 522 529 os.system(cmd % locals()) 523 530 531 def formatCommandLine(self, cmd, user, printer) : 532 """Executes an external command.""" 533 username = user.Name 534 printername = printer.Name 535 return cmd % locals() 536 524 537 def warnGroupPQuota(self, grouppquota) : 525 538 """Checks a group quota and send messages if quota is exceeded on current printer.""" … … 542 555 self.sendMessageToUser(admin, adminmail, user, _("Print Quota Exceeded"), self.config.getHardWarn(printer.Name)) 543 556 else : 544 self.externalMailTo(arguments, action, user, printer .Name, message)557 self.externalMailTo(arguments, action, user, printer, message) 545 558 elif action == "WARN" : 546 559 adminmessage = _("Print Quota low for group %s on printer %s") % (group.Name, printer.Name) … … 557 570 self.sendMessageToUser(admin, adminmail, user, _("Print Quota Exceeded"), message) 558 571 else : 559 self.externalMailTo(arguments, action, user, printer .Name, message)572 self.externalMailTo(arguments, action, user, printer, message) 560 573 return action 561 574 … … 578 591 self.sendMessageToUser(admin, adminmail, user, _("Print Quota Exceeded"), message) 579 592 else : 580 self.externalMailTo(arguments, action, user, printer .Name, message)593 self.externalMailTo(arguments, action, user, printer, message) 581 594 if mailto in [ "BOTH", "ADMIN" ] : 582 595 self.sendMessageToAdmin(adminmail, _("Print Quota"), adminmessage) … … 592 605 self.sendMessageToUser(admin, adminmail, user, _("Print Quota Low"), message) 593 606 else : 594 self.externalMailTo(arguments, action, user, printer .Name, message)607 self.externalMailTo(arguments, action, user, printer, message) 595 608 if mailto in [ "BOTH", "ADMIN" ] : 596 609 self.sendMessageToAdmin(adminmail, _("Print Quota"), adminmessage) 597 610 return action 611 612 class PyKotaFilterOrBackend(PyKotaTool) : 613 """Class for the PyKota filter or backend.""" 614 def __init__(self) : 615 PyKotaTool.__init__(self) 616 (self.printingsystem, \ 617 self.printerhostname, \ 618 self.printername, \ 619 self.username, \ 620 self.jobid, \ 621 self.inputfile, \ 622 self.copies, \ 623 self.title, \ 624 self.options, \ 625 self.originalbackend) = self.extractInfoFromCupsOrLprng() 626 self.accounter = openAccounter(self) 627 628 def extractInfoFromCupsOrLprng(self) : 629 """Returns a tuple (printingsystem, printerhostname, printername, username, jobid, filename, title, options, backend). 630 631 Returns (None, None, None, None, None, None, None, None, None, None) if no printing system is recognized. 632 """ 633 # Try to detect CUPS 634 if os.environ.has_key("CUPS_SERVERROOT") and os.path.isdir(os.environ.get("CUPS_SERVERROOT", "")) : 635 if len(sys.argv) == 7 : 636 inputfile = sys.argv[6] 637 else : 638 inputfile = None 639 640 # check that the DEVICE_URI environment variable's value is 641 # prefixed with "cupspykota:" otherwise don't touch it. 642 # If this is the case, we have to remove the prefix from 643 # the environment before launching the real backend in cupspykota 644 device_uri = os.environ.get("DEVICE_URI", "") 645 if device_uri.startswith("cupspykota:") : 646 fulldevice_uri = device_uri[:] 647 device_uri = fulldevice_uri[len("cupspykota:"):] 648 if device_uri.startswith("//") : # lpd (at least) 649 device_uri = device_uri[2:] 650 os.environ["DEVICE_URI"] = device_uri # TODO : side effect ! 651 # TODO : check this for more complex urls than ipp://myprinter.dot.com:631/printers/lp 652 try : 653 (backend, destination) = device_uri.split(":", 1) 654 except ValueError : 655 raise PyKotaToolError, "Invalid DEVICE_URI : %s\n" % device_uri 656 while destination.startswith("/") : 657 destination = destination[1:] 658 printerhostname = destination.split("/")[0].split(":")[0] 659 return ("CUPS", \ 660 printerhostname, \ 661 os.environ.get("PRINTER"), \ 662 sys.argv[2].strip(), \ 663 sys.argv[1].strip(), \ 664 inputfile, \ 665 int(sys.argv[4].strip()), \ 666 sys.argv[3], \ 667 sys.argv[5], \ 668 backend) 669 else : 670 # Try to detect LPRng 671 jseen = Pseen = nseen = rseen = Kseen = None 672 for arg in sys.argv : 673 if arg.startswith("-j") : 674 jseen = arg[2:].strip() 675 elif arg.startswith("-n") : 676 nseen = arg[2:].strip() 677 elif arg.startswith("-P") : 678 Pseen = arg[2:].strip() 679 elif arg.startswith("-r") : 680 rseen = arg[2:].strip() 681 elif arg.startswith("-K") or arg.startswith("-#") : 682 Kseen = int(arg[2:].strip()) 683 if Kseen is None : 684 Kseen = 1 # we assume the user wants at least one copy... 685 if (rseen is None) and jseen and Pseen and nseen : 686 self.logger.log_message(_("Printer hostname undefined, set to 'localhost'"), "warn") 687 rseen = "localhost" 688 if jseen and Pseen and nseen and rseen : 689 # job is always in stdin (None) 690 return ("LPRNG", rseen, Pseen, nseen, jseen, None, Kseen, None, None, None) 691 self.logger.log_message(_("Printing system unknown, args=%s") % " ".join(sys.argv), "warn") 692 return (None, None, None, None, None, None, None, None, None, None) # Unknown printing system