Index: /pykota/trunk/conf/pykota.conf.sample
===================================================================
--- /pykota/trunk/conf/pykota.conf.sample (revision 1149)
+++ /pykota/trunk/conf/pykota.conf.sample (revision 1152)
@@ -300,5 +300,5 @@
 
 # Default policy for inexistant users (e.g. root)
-# either allow or deny
+# either allow or deny or external(some command here)
 # This value can be set either globally or per printer or both.
 # If both are defined, the printer option has priority.
@@ -309,4 +309,18 @@
 #     charged to the next person who prints on the same printer.
 # There's no policy wrt inexistant groups, they are ignored.
+#
+# external policy can be used to launch any external command of your choice,
+# for example to automatically add the user to the quota storage 
+# if he is unknown. Example :
+# 
+#       policy: external(/usr/bin/edpykota --add --printer %(printer)s --softlimit 50 --hardlimit 60 %(user)s) 
+#
+#       NB : '%(user)s' and '%(printer)s' will be automatically replaced 
+#            by the user and printer names. 
+#
+# Of course you can launch any command of your choice with this, e.g. :
+#
+#       policy: external(/usr/local/bin/myadminscript.sh %(user)s)
+#
 policy: deny
 
Index: /pykota/trunk/pykota/tool.py
===================================================================
--- /pykota/trunk/pykota/tool.py (revision 1144)
+++ /pykota/trunk/pykota/tool.py (revision 1152)
@@ -22,4 +22,8 @@
 #
 # $Log$
+# Revision 1.53  2003/10/08 21:41:38  jalet
+# External policies for printers works !
+# We can now auto-add users on first print, and do other useful things if needed.
+#
 # Revision 1.52  2003/10/07 09:07:28  jalet
 # Character encoding added to please latest version of Python
@@ -435,5 +439,6 @@
                 
         # then we check the user's own quota
-        policy = self.config.getPrinterPolicy(printer.Name)
+        # if we get there we are sure that policy is not EXTERNAL
+        (policy, dummy) = self.config.getPrinterPolicy(printer.Name)
         if user.LimitBy and (user.LimitBy.lower() == "balance") : 
             if user.AccountBalance is None :
Index: /pykota/trunk/pykota/config.py
===================================================================
--- /pykota/trunk/pykota/config.py (revision 1148)
+++ /pykota/trunk/pykota/config.py (revision 1152)
@@ -22,4 +22,8 @@
 #
 # $Log$
+# Revision 1.39  2003/10/08 21:41:38  jalet
+# External policies for printers works !
+# We can now auto-add users on first print, and do other useful things if needed.
+#
 # Revision 1.38  2003/10/07 22:06:05  jalet
 # Preliminary code to disable job history
@@ -320,12 +324,25 @@
     def getPrinterPolicy(self, printer) :    
         """Returns the default policy for the current printer."""
-        validpolicies = [ "ALLOW", "DENY" ]     
-        try :
-            policy = self.getPrinterOption(printer, "policy").upper()
-        except PyKotaConfigError :    
-            policy = "DENY"
-        if policy not in validpolicies :
-            raise PyKotaConfigError, _("Option policy in section %s only supports values in %s") % (printer, str(validpolicies))
-        return policy
+        validpolicies = [ "ALLOW", "DENY", "EXTERNAL" ]     
+        try :
+            fullpolicy = self.getPrinterOption(printer, "policy")
+        except PyKotaConfigError :    
+            return ("DENY", None)
+        else :    
+            try :
+                policy = [x.strip() for x in fullpolicy.split('(', 1)]
+            except ValueError :    
+                raise PyKotaConfigError, _("Invalid policy %s for printer %s") % (fullpolicy, printer)
+            if len(policy) == 1 :    
+                policy.append("")
+            (policy, args) = policy    
+            if args.endswith(')') :
+                args = args[:-1]
+            policy = policy.upper()    
+            if (policy == "EXTERNAL") and not args :
+                raise PyKotaConfigError, _("Invalid policy %s for printer %s") % (fullpolicy, printer)
+            if policy not in validpolicies :
+                raise PyKotaConfigError, _("Option policy in section %s only supports values in %s") % (printer, str(validpolicies))
+            return (policy, args)
         
     def getSMTPServer(self) :    
Index: /pykota/trunk/pykota/version.py
===================================================================
--- /pykota/trunk/pykota/version.py (revision 1149)
+++ /pykota/trunk/pykota/version.py (revision 1152)
@@ -22,5 +22,5 @@
 #
 
-__version__ = "1.15alpha8_unofficial"
+__version__ = "1.15alpha9_unofficial"
 
 __doc__ = """PyKota : a complete Printing Quota Solution for CUPS and LPRng."""
Index: /pykota/trunk/bin/pykota
===================================================================
--- /pykota/trunk/bin/pykota (revision 1144)
+++ /pykota/trunk/bin/pykota (revision 1152)
@@ -24,4 +24,8 @@
 #
 # $Log$
+# Revision 1.42  2003/10/08 21:41:38  jalet
+# External policies for printers works !
+# We can now auto-add users on first print, and do other useful things if needed.
+#
 # Revision 1.41  2003/10/07 09:07:27  jalet
 # Character encoding added to please latest version of Python
@@ -252,4 +256,13 @@
             return -1
             
+def format_commandline(prt, usr, cmdline) :            
+    """Passes printer and user names on the command line."""
+    printer = prt.Name
+    user = usr.Name
+    # we don't want the external command's standard 
+    # output to break the print job's data, but we
+    # want to keep its standard error
+    return "%s >/dev/null" % (cmdline % locals())
+
 def main(thefilter) :    
     """Do it, and do it right !"""
@@ -268,26 +281,47 @@
         thefilter.logger.log_message(_("Printer %s not registered in the PyKota system") % thefilter.printername, "warn")
     else :    
-        user = thefilter.storage.getUser(thefilter.username)
-        if not user.Exists :
-            # The user is unknown from the Quota Storage perspective
-            # Depending on the default policy for this printer, we
-            # either let the job pass through or reject it, but we
-            # log a message in any case.
-            policy = thefilter.config.getPrinterPolicy(thefilter.printername)
-            if policy == "ALLOW" :
-                action = "POLICY_ALLOW"
+        for compteur in range(2) :
+            user = thefilter.storage.getUser(thefilter.username)
+            if user.Exists :
+                break
             else :    
-                action = "POLICY_DENY"
-            thefilter.logger.log_message(_("User %s not registered in the PyKota system, applying default policy (%s) for printer %s") % (thefilter.username, action, thefilter.printername), "warn")
-            if action == "POLICY_DENY" :
-                return thefilter.removeJob()
-        else :
+                # The user is unknown from the Quota Storage perspective
+                # Depending on the default policy for this printer, we
+                # either let the job pass through or reject it, but we
+                # log a message in any case.
+                (policy, args) = thefilter.config.getPrinterPolicy(thefilter.printername)
+                if policy == "ALLOW" :
+                    action = "POLICY_ALLOW"
+                elif policy == "EXTERNAL" :    
+                    commandline = format_commandline(printer, user, args)
+                    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")
+                    if os.system(commandline) :
+                        thefilter.logger.log_message(_("External policy %s for printer %s produced an error. Job rejected. Please check PyKota's configuration files.") % (commandline, thefilter.printername), "error")
+                        return thefilter.removeJob()
+                    else :    
+                        # here we try a second time, because the goal
+                        # of the external action was to add the user
+                        # in the database.
+                        continue 
+                else :    
+                    action = "POLICY_DENY"
+                thefilter.logger.log_message(_("User %s not registered in the PyKota system, applying default policy (%s) for printer %s") % (thefilter.username, action, thefilter.printername), "warn")
+                if action == "POLICY_DENY" :
+                    return thefilter.removeJob()
+                # when we get there, the printer policy allows the job to pass 
+                break    
+                    
+        # if user exists, do accounting
+        if user.Exists :
             # Now does the accounting and act depending on the result
             action = thefilter.accounter.doAccounting(printer, user)
-            
+        
             # if not allowed to print then die, else proceed.
             if action == "DENY" :
                 # No, just die cleanly
                 return thefilter.removeJob()
+        elif policy == "EXTERNAL" :                
+            thefilter.logger.log_message(_("External policy %s for printer %s couldn't add user %s. Job rejected.") % (commandline, thefilter.printername, thefilter.username), "error")
+            return thefilter.removeJob()
         
     # pass the job untouched to the underlying layer
Index: /pykota/trunk/NEWS
===================================================================
--- /pykota/trunk/NEWS (revision 1149)
+++ /pykota/trunk/NEWS (revision 1152)
@@ -22,4 +22,12 @@
 PyKota NEWS :
 
+    - 1.15alpha9 :
+    
+        - External policy can be used to auto-add unknown users 
+          and any other interesting things you may want to do. 
+          WARNING : You can't auto-add printers for now. 
+          They have to be created manually before.
+          Look at sample configuration file for examples.
+          
     - 1.15alpha8 :
     
Index: /pykota/trunk/po/en/pykota.po
===================================================================
--- /pykota/trunk/po/en/pykota.po (revision 1116)
+++ /pykota/trunk/po/en/pykota.po (revision 1152)
@@ -21,4 +21,8 @@
 #
 # $Log$
+# Revision 1.35  2003/10/08 21:41:38  jalet
+# External policies for printers works !
+# We can now auto-add users on first print, and do other useful things if needed.
+#
 # Revision 1.34  2003/08/18 16:20:59  jalet
 # Improvement of the printing system detection code.
@@ -427,2 +431,14 @@
 msgstr ""
 
+msgid "Invalid policy %s for printer %s"
+msgstr ""
+
+msgid "User %s not registered in the PyKota system, applying external policy (%s) for printer %s"
+msgstr ""
+
+msgid "External policy %s for printer %s produced an error. Job rejected. Please check PyKota's configuration files."
+msgstr ""
+
+msgid "External policy %s for printer %s couldn't add user %s. Job rejected."
+msgstr ""
+
Index: /pykota/trunk/po/fr/pykota.po
===================================================================
--- /pykota/trunk/po/fr/pykota.po (revision 1116)
+++ /pykota/trunk/po/fr/pykota.po (revision 1152)
@@ -21,4 +21,8 @@
 #
 # $Log$
+# Revision 1.34  2003/10/08 21:41:38  jalet
+# External policies for printers works !
+# We can now auto-add users on first print, and do other useful things if needed.
+#
 # Revision 1.33  2003/08/18 16:20:59  jalet
 # Improvement of the printing system detection code.
@@ -437,2 +441,14 @@
 msgstr "Syst� d'impression inconnu, args=%s"
 
+msgid "Invalid policy %s for printer %s"
+msgstr "Option policy %s invalide pour l'imprimante %s"
+
+msgid "User %s not registered in the PyKota system, applying external policy (%s) for printer %s"
+msgstr "Utilisateur %s non enregistr�ans le syst� PyKota, action externe (%s) appliqu�sur l'imprimante %s"
+
+msgid "External policy %s for printer %s produced an error. Job rejected. Please check PyKota's configuration files."
+msgstr "L'action externe %s sur l'imprimante %s a produit une erreur. Job rejet�Merci de v�fier les fichiers de configuration de PyKota."
+
+msgid "External policy %s for printer %s couldn't add user %s. Job rejected."
+msgstr "L'action externe %s sur l'imprimante %s n'a pas pu ajouter l'utilisateur %s. Job rejet�
+
Index: /pykota/trunk/po/pykota.pot
===================================================================
--- /pykota/trunk/po/pykota.pot (revision 1116)
+++ /pykota/trunk/po/pykota.pot (revision 1152)
@@ -21,4 +21,8 @@
 #
 # $Log$
+# Revision 1.35  2003/10/08 21:41:38  jalet
+# External policies for printers works !
+# We can now auto-add users on first print, and do other useful things if needed.
+#
 # Revision 1.34  2003/08/18 16:20:59  jalet
 # Improvement of the printing system detection code.
@@ -427,2 +431,14 @@
 msgstr ""
 
+msgid "Invalid policy %s for printer %s"
+msgstr ""
+
+msgid "User %s not registered in the PyKota system, applying external policy (%s) for printer %s"
+msgstr ""
+
+msgid "External policy %s for printer %s produced an error. Job rejected. Please check PyKota's configuration files."
+msgstr ""
+
+msgid "External policy %s for printer %s couldn't add user %s. Job rejected."
+msgstr ""
+
