Index: tea4cups/trunk/TODO
===================================================================
--- tea4cups/trunk/TODO (revision 654)
+++ tea4cups/trunk/TODO (revision 659)
@@ -23,8 +23,5 @@
 TODO, in no particular order :
         
-        - Add an 'onfail' directive, to launch some script whenever
-          the real backend failed.
-          
-        - Add filters.  
+        - Nothing yet !
         
 ============================================================
Index: tea4cups/trunk/tea4cups
===================================================================
--- tea4cups/trunk/tea4cups (revision 655)
+++ tea4cups/trunk/tea4cups (revision 659)
@@ -34,7 +34,8 @@
 import ConfigParser
 import signal
+import popen2
 from struct import pack, unpack
 
-version = "3.02_unofficial"
+version = "3.10_unofficial"
 
 class TeeError(Exception):
@@ -623,4 +624,21 @@
         else :
             infile = sys.stdin
+            
+        filtercommand = self.getPrintQueueOption(self.PrinterName, "filter", \
+                                                 ignore=1)
+        if filtercommand :                                                 
+            self.logDebug("Data stream will be filtered through [%s]" % filtercommand)
+            filteroutput = "%s.filteroutput" % self.DataFile
+            outf = open(filteroutput, "wb")
+            filterstatus = self.stdioRedirSystem(filtercommand, infile.fileno(), outf.fileno())
+            outf.close()
+            self.logDebug("Filter's output status : %s" % repr(filterstatus))
+            if mustclose :
+                infile.close()
+            infile = open(filteroutput, "rb")
+            mustclose = 1
+        else :    
+            self.logDebug("Data stream will be used as-is (no filter defined)")
+            
         CHUNK = 64*1024         # read 64 Kb at a time
         dummy = 0
@@ -639,6 +657,16 @@
             dummy += 1
         outfile.close()
+        
+        if filtercommand :
+            self.logDebug("Removing filter's output file %s" % filteroutput)
+            try :
+                os.remove(filteroutput)
+            except :    
+                pass
+                
         if mustclose :
             infile.close()
+            
+        self.logDebug("%s bytes saved..." % sizeread)
         self.JobSize = sizeread
         self.JobMD5Sum = checksum.hexdigest()
@@ -672,4 +700,10 @@
             if self.RealBackend :
                 retcode = self.runOriginalBackend()
+                if retcode :
+                    onfail = self.getPrintQueueOption(self.PrinterName, \
+                                                      "onfail", ignore=1)
+                    if onfail :
+                        self.logDebug("Launching onfail script %s" % onfail)
+                        os.system(onfail)
             if not self.gotSigTerm :
                 os.environ["TEASTATUS"] = str(retcode)
Index: tea4cups/trunk/NEWS
===================================================================
--- tea4cups/trunk/NEWS (revision 653)
+++ tea4cups/trunk/NEWS (revision 659)
@@ -23,4 +23,8 @@
 Tea4CUPS News :
 
+  * 3.03 :
+  
+    - Added filters.
+    
   * 3.02 :
   
Index: tea4cups/trunk/tea4cups.conf
===================================================================
--- tea4cups/trunk/tea4cups.conf (revision 648)
+++ tea4cups/trunk/tea4cups.conf (revision 659)
@@ -24,7 +24,9 @@
 [global]
 
+
 # Should we log debugging information to CUPS' error_log file ?
 # defaults to No if unset.
 debug : yes
+
 
 # In which directory will we create our files ? It must already exist !
@@ -36,4 +38,5 @@
 directory : /var/spool/cups/
 
+
 # Should Tea4CUPS keep the files it creates once all hooks have ended ?
 # Defaults to No if unset, meaning that files are automatically deleted
@@ -44,4 +47,27 @@
 # BEWARE : this may use huge amounts of disk space !
 # keepfiles : yes
+
+
+# Should we launch some command when the real CUPS backend fails ?
+# Can be set either in the [global] section or any print queue section.
+# The value defined in a print queue section takes precedence over the
+# value defined in the [global] section.
+# onfail : echo "Original Backend failed" | /usr/bin/mail -s Tea4CUPS root
+
+
+# Should we pass incoming datas through a filter command 
+# BEFORE doing anything else ?
+# NB : obvisouly the filter command doesn't have any access to
+#      the environment variables defined below.
+# Can be set either in the [global] section or any print queue section.
+# The value defined in a print queue section takes precedence over the
+# value defined in the [global] section.
+# 
+# The sample filter below can remove the print job creation date
+# from PostScript jobs, in order to more accurately detect duplicate
+# jobs (so the MD5SUM would be identical from launch to launch)
+#
+# filter : /bin/grep -v "%%CreationDate:"
+
 
 # Should we serialize the launch of all hooks : launch one after
@@ -59,22 +85,23 @@
 # serialize : yes
 
-# When executing the contents of a prehook or posthook directive,
-# tea4cups makes the following environment variables available to your
-# own commands :
+
+# When executing the contents of a prehook or posthook directive, as
+# defined below, tea4cups makes the following environment variables 
+# available to your own commands :
 #
-# TEAPRINTERNAME : The print queue name.
-# TEADIRECTORY : Tea4CUPS output directory.
-# TEADATAFILE : Full name of Tea4CUPS work file (in $TEADIRECTORY).
-# TEAJOBSIZE : Job's size in bytes.
-# TEAMD5SUM : MD5 sum of the job's datas.
-# TEACLIENTHOST : Client's hostname or IP address.
-# TEAJOBID : Job's Id.
-# TEAUSERNAME : Name of the user who launched the print job.
-# TEATITLE : Job's title.
-# TEACOPIES : Number of copies requested.
-# TEAOPTIONS : Options of the print job.
-# TEAINPUTFILE : Job's data file or empty when job read from stdin.
-# TEABILLING : Job's billing code (lp -o job-billing=SomeCode file.ps)
-# TEACONTROLFILE : Job's IPP message file (usually /var/spool/cups/c?????)
+#      TEAPRINTERNAME : The print queue name.
+#      TEADIRECTORY : Tea4CUPS output directory.
+#      TEADATAFILE : Full name of Tea4CUPS work file (in $TEADIRECTORY).
+#      TEAJOBSIZE : Job's size in bytes.
+#      TEAMD5SUM : MD5 sum of the job's datas.
+#      TEACLIENTHOST : Client's hostname or IP address.
+#      TEAJOBID : Job's Id.
+#      TEAUSERNAME : Name of the user who launched the print job.
+#      TEATITLE : Job's title.
+#      TEACOPIES : Number of copies requested.
+#      TEAOPTIONS : Options of the print job.
+#      TEAINPUTFILE : Job's data file or empty when job read from stdin.
+#      TEABILLING : Job's billing code (lp -o job-billing=SomeCode file.ps)
+#      TEACONTROLFILE : Job's IPP message file (usually /var/spool/cups/c?????)
 #
 # Your own commands will mostly be interested in TEADATAFILE which is
@@ -82,4 +109,5 @@
 # job's datas. Don't rely on TEAINPUTFILE, use TEADATAFILE instead
 # since the first one may be empty depending on your printer driver.
+
 
 # Some prehooks and posthooks
@@ -121,13 +149,17 @@
 #posthook_0 : cat $TEADATAFILE >~$TEAUSERNAME/savejobs/$TEAJOBID.prn
 
+
 # An empty value deletes a value defined in the [global] section
 # so this particular hook doesn't get executed on this printer.
 #prehook_pdf :
 
+
 # A reflector which produces 4 copies each time :
 #posthook_4copies : lp -dotherprinter -n4 $CUPSDATAFILE
 
+
 # A simple accounting mechanism
 #prehook_accounting : echo $TEAPRINTERNAME $TEAJOBID $TEAUSERNAME $TEABILLING `pkpgcounter $TEADATAFILE` >/var/log/printaccounting.log
+
 
 # Some additionnal hooks to forbid duplicate jobs :
@@ -143,4 +175,5 @@
 #posthook_to_filter_duplicates : echo "$TEAJOBID : $TEAMD5SUM" >>/tmp/jobmd5sums
 
+
 # A particular prehook can send datas to the posthook
 # of the same name automatically through pipes :
Index: tea4cups/trunk/README
===================================================================
--- tea4cups/trunk/README (revision 645)
+++ tea4cups/trunk/README (revision 659)
@@ -24,6 +24,6 @@
 
 Tea4CUPS behaves just like any other CUPS backend, but allows you to
-transparently send print jobs' datas to any number of outputs : other
-CUPS backends, files or pipes.
+modify print jobs' datas as they pass through it and to transparently 
+send them to any number of outputs : other CUPS backends, files or pipes.
 
 This for example allows you to output the same print job on several
@@ -37,19 +37,27 @@
 commands into the very last stage of CUPS' filtering chain.
 
-Tea4CUPS provides two ways to launch commands :
+Tea4CUPS provides three ways to launch commands :
+
+        - filters : A filter can modify the input datas before they
+                    are sent to the printer or made available to
+                    the pre and post hooks defined below.
+                    Currently a single filter can be defined
+                    per print queue.
 
         - prehooks : these are guaranteed to be launched before the
                      print job is sent to the real printer.
                      Any prehook which exits -1 can cancel the
-                     print job.
+                     print job. Any number of prehooks can be
+                     defined for a particular print queue.
 
         - posthooks : these are guaranteed to be launched after the
                       print job has been sent to the real printer,
                       unless the job was previously cancelled by a
-                      prehook.
+                      prehook. Any number of posthooks can be 
+                      defined for a particular print queue.
 
 To help your own commands, Tea4CUPS makes available as part of the
 environment several variables which can be used from the
-commands you use :
+commands you use in pre and post hooks :
 
         TEAPRINTERNAME : The print queue name.
@@ -70,7 +78,6 @@
                     posthooks, obviously.
 
-In the case you want to use both Tea4CUPS and PyKota, you MUST install
-PyKota v1.22alpha2 or higher to avoid a race condition.
-
+        None of these environment variables is available to filters.
+  
 NB : Tea4CUPS requires a version of Python >= 2.1
 
