Index: pykota/trunk/conf/pykota.conf.sample
===================================================================
--- pykota/trunk/conf/pykota.conf.sample (revision 2884)
+++ pykota/trunk/conf/pykota.conf.sample (revision 2895)
@@ -459,6 +459,6 @@
 #    CANCEL
 #
-# NB : the output is entirely read, and the latest value
-# seen is used, so you command can output several usernames
+# NB : the output of your command is entirely read, and the latest 
+# value seen is used, so you command can output several usernames
 # or billing codes and only the latest ones will be used.
 # If only USERNAME= lines are printed, the billing code,
@@ -475,4 +475,22 @@
 # overwrite_jobticket : /usr/bin/pknotify --destination $PYKOTAJOBORIGINATINGHOSTNAME:7654 --timeout 180 --denyafter 3 --checkauth --ask "Username:username:$PYKOTAUSERNAME" "Password:password:"
 # overwrite_jobticket : /path/to/some/script/or/command
+
+
+
+# Should we ask the end user for a confirmation about their print job ?
+#
+# Any script can be launched here. If your script prints CANCEL on
+# its standard output, the job is cancelled, else processing of the
+# job continues to next step.
+#
+# NB : the output of your command is read until CANCEL is found
+# or all lines have been read.
+#
+# This value can be set either globally or on a per printer basis
+# If both are defined, the printer option has priority.
+#
+# examples :
+#
+# askconfirmation : /usr/bin/pknotify --destination $PYKOTAJOBORIGINATINGHOSTNAME:7654 --timeout 120 --confirm "Hello $PYKOTAUSERNAME.\nPrint job $PYKOTAJOBID send to printer $PYKOTAPRINTERNAME is $PYKOTAPRECOMPUTEDJOBSIZE pages long\nand will cost you $PYKOTAPRECOMPUTEDJOBPRICE credits.\n\nYou currently have $PYKOTABALANCE credits.\n\nDo you really want to print ?"
 
 
Index: pykota/trunk/pykota/config.py
===================================================================
--- pykota/trunk/pykota/config.py (revision 2759)
+++ pykota/trunk/pykota/config.py (revision 2895)
@@ -249,4 +249,11 @@
             return      # No prefix to strip off
             
+    def getAskConfirmation(self, printername) :        
+        """Returns the askconfirmation directive's content, or None if unset."""
+        try :
+            return self.getPrinterOption(printername, "askconfirmation").strip()
+        except PyKotaConfigError :    
+            return      # No overwriting will be done
+            
     def getOverwriteJobTicket(self, printername) :        
         """Returns the overwrite_jobticket directive's content, or None if unset."""
Index: pykota/trunk/bin/cupspykota
===================================================================
--- pykota/trunk/bin/cupspykota (revision 2891)
+++ pykota/trunk/bin/cupspykota (revision 2895)
@@ -371,9 +371,34 @@
         self.logdebug("Job's attributes sanitizing done.")
                 
+    def didUserConfirm(self) :
+        """Asks for user confirmation through an external script.
+        
+           returns False if the end user wants to cancel the job, else True.
+        """
+        self.logdebug("Checking if we have to ask for user's confirmation...")
+        answer = None                         
+        confirmationcommand = self.config.getAskConfirmation(self.PrinterName)
+        if confirmationcommand :
+            self.logdebug("Launching subprocess [%s] to ask for user confirmation." \
+                                     % confirmationcommand)
+            inputfile = os.popen(confirmationcommand, "r")
+            try :
+                for answer in inputfile.xreadlines() :
+                    answer = answer.strip().upper()
+                    if answer == "CANCEL" :
+                        break
+            except IOError, msg :            
+                self.logdebug("IOError while reading subprocess' output : %s" % msg)
+            inputfile.close()    
+            self.logdebug("User's confirmation received : %s" % (((answer == "CANCEL") and "CANCEL") or "CONTINUE"))
+        else :    
+            self.logdebug("No need to ask for user's confirmation, job processing will continue.")
+        return (answer != "CANCEL")    
+        
     def overwriteJobTicket(self) :    
         """Should we overwrite the job's ticket (username and billingcode) ?"""
         self.logdebug("Checking if we need to overwrite the job ticket...")
         jobticketcommand = self.config.getOverwriteJobTicket(self.PrinterName)
-        if jobticketcommand is not None :
+        if jobticketcommand :
             username = billingcode = action = None
             self.logdebug("Launching subprocess [%s] to overwrite the job ticket." \
@@ -1020,4 +1045,10 @@
         
         if self.Action not in ("DENY", "CANCEL") : 
+            if not self.didUserConfirm() :
+                self.Action = "CANCEL"
+                self.Reason = _("Print job cancelled.")
+                os.environ["PYKOTASTATUS"] = "CANCELLED"
+                
+        if self.Action not in ("DENY", "CANCEL") : 
             if self.Printer.MaxJobSize and (self.softwareJobSize > self.Printer.MaxJobSize) :
                 # This printer was set to refuse jobs this large.
Index: pykota/trunk/NEWS
===================================================================
--- pykota/trunk/NEWS (revision 2891)
+++ pykota/trunk/NEWS (revision 2895)
@@ -24,4 +24,9 @@
     - 1.25alpha4 (2006-05-22) :
     
+        - Introduced the 'askconfirmation' directive to interact with
+          the end user through any script (pknotify is recommended)
+          and see if he really wants to print when knowing the cost
+          of the job.
+          
         - Now uses pkipplib if present to directly retrieve the job
           information from the CUPS server over IPP.
