Index: /pykota/trunk/conf/pykota.conf.sample
===================================================================
--- /pykota/trunk/conf/pykota.conf.sample (revision 3242)
+++ /pykota/trunk/conf/pykota.conf.sample (revision 3252)
@@ -986,5 +986,4 @@
 # PYKOTAFILENAME : The name of the file which contains the job's datas or 
 #                  empty if datas come from stdin
-# PYKOTACONTROLFILE : The name of the IPP message file
 # PYKOTAMD5SUM : Contains an hexadecimal digest of the md5 sum of the job's datas
 # PYKOTAPHASE : BEFORE or AFTER the job is sent to the printer
Index: /pykota/trunk/pykota/cups.py
===================================================================
--- /pykota/trunk/pykota/cups.py (revision 3249)
+++ /pykota/trunk/pykota/cups.py (revision 3252)
@@ -30,13 +30,17 @@
     raise RuntimeError, "The python-pkipplib module is now mandatory. You can download pkipplib from http://www.pykota.com/"
 
-class Job :    
+class JobTicket :    
     """A class to hold CUPS print job informations."""
-    def __init__(self, jobid=None, copies=1, filename=None) :
+    def __init__(self, jobid=None, printername=None, copies=1, filename=None, \
+                       options=None) :
         """Initializes a print job's information."""
         self.JobId = jobid
+        self.PrinterName = printername
         self.Copies = copies
         self.FileName = filename
+        self.Options = options
         self.Charset = None
-        self.UserName = None
+        self.OriginatingUserName = None
+        self.OriginalUserName = None
         self.Title = None
         self.BillingCode = None
@@ -61,4 +65,8 @@
     def retrieveAttributesFromCUPS(self) :
         """Retrieve attribute's values from CUPS."""
+        import os
+        f = open("/tmp/debug", "w")
+        f.write("%s\n" % os.environ.get("CUPS_SERVER", ""))
+        f.close()
         server = pkipplib.CUPS() # TODO : username and password and/or encryption
         answer = server.getJobAttributes(self.JobId)
@@ -66,6 +74,6 @@
             raise PyKotaToolError, "Network error while querying the CUPS server : %s" \
                                       % server.lastErrorMessage
-        (dummy, self.Charset) = self.getAttributeTypeAndValue(answer, "attributes-charset", "operation")                              
-        (dummy, self.UserName) = self.getAttributeTypeAndValue(answer, "job-originating-user-name")
+        (dummy, self.Charset) = self.getAttributeTypeAndValue(answer, "attributes-charset", "operation")
+        (dummy, self.OriginatingUserName) = self.getAttributeTypeAndValue(answer, "job-originating-user-name")
         (dummy, self.Title) = self.getAttributeTypeAndValue(answer, "job-name")
         (dummy, self.BillingCode) = self.getAttributeTypeAndValue(answer, "job-billing")
@@ -75,4 +83,5 @@
         (dummy, self.TimeAtProcessing) = self.getAttributeTypeAndValue(answer, "time-at-processing")
         (dummy, self.MimeType) = self.getAttributeTypeAndValue(answer, "document-format")
+        self.OriginalUserName = self.OriginatingUserName[:]
     
 if __name__ == "__main__" :    
@@ -81,6 +90,6 @@
         sys.stderr.write("usage : python cups.py jobid\n")
     else :    
-        job = Job(int(sys.argv[1]))
-        for attribute in ("Charset", "JobId", "Copies", "FileName", "UserName", 
+        job = JobTicket(int(sys.argv[1]))
+        for attribute in ("Charset", "JobId", "Copies", "FileName", "OriginatingUserName", 
                           "Title", "BillingCode", "OriginatingHostName", 
                           "TimeAtCreation", "TimeAtProcessing", "UUID",
Index: /pykota/trunk/pykota/accounters/software.py
===================================================================
--- /pykota/trunk/pykota/accounters/software.py (revision 3245)
+++ /pykota/trunk/pykota/accounters/software.py (revision 3252)
@@ -67,8 +67,8 @@
                 else :    
                     try :
-                        if self.filter.InputFile is not None :
+                        if self.filter.Ticket.FileName is not None :
                             # when a filename is passed as an argument, the backend 
                             # must generate the correct number of copies.
-                            jobsize *= self.filter.Copies
+                            jobsize *= self.filter.Ticket.Copies
                     except AttributeError : # When not run from the cupspykota backend        
                         pass
@@ -128,8 +128,8 @@
             
         pagecounter = pagecounter or 0    
-        if self.filter.InputFile is not None :
+        if self.filter.Ticket.FileName is not None :
             # when a filename is passed as an argument, the backend 
             # must generate the correct number of copies.
-            pagecounter *= self.filter.Copies
+            pagecounter *= self.filter.Ticket.Copies
                         
         return pagecounter
Index: /pykota/trunk/pykota/accounters/ink.py
===================================================================
--- /pykota/trunk/pykota/accounters/ink.py (revision 3245)
+++ /pykota/trunk/pykota/accounters/ink.py (revision 3252)
@@ -88,9 +88,9 @@
                     jobsize = len(pages)
                     try :
-                        if self.filter.InputFile is not None :
+                        if self.filter.Ticket.FileName is not None :
                             # when a filename is passed as an argument, the backend 
                             # must generate the correct number of copies.
-                            jobsize *= self.filter.Copies
-                            self.inkUsage *= self.filter.Copies
+                            jobsize *= self.filter.Ticket.Copies
+                            self.inkUsage *= self.filter.Ticket.Copies
                     except AttributeError : # When not run from the cupspykota backend 
                         pass
Index: /pykota/trunk/bin/cupspykota
===================================================================
--- /pykota/trunk/bin/cupspykota (revision 3248)
+++ /pykota/trunk/bin/cupspykota (revision 3252)
@@ -4,5 +4,5 @@
 # CUPSPyKota accounting backend
 #
-# PyKota - Print Quotas for CUPS and LPRng
+# PyKota - Print Quotas for CUPS
 #
 # (c) 2003, 2004, 2005, 2006, 2007 Jerome Alet <alet@librelogiciel.com>
@@ -48,15 +48,5 @@
 from pykota.tool import PyKotaTool, PyKotaToolError, crashed
 from pykota.accounter import openAccounter
-# TODO : remove the three lines below and the code which handles
-# TODO : them in a future release.
-from pykota.ipp import IPPRequest as oldIPPRequest
-from pykota.ipp import IPPError as oldIPPError
-
-try :
-    from pkipplib import pkipplib
-except ImportError :        
-    haspkipplib = False
-else :    
-    haspkipplib = True
+from pykota import cups
     
 class FakeObject :        
@@ -105,5 +95,5 @@
         """Sets an attribute whenever SIGTERM is received."""
         self.gotSigTerm = 1
-        self.printInfo(_("SIGTERM received, job %s cancelled.") % self.JobId)
+        self.printInfo(_("SIGTERM received, job %s cancelled.") % self.Ticket.JobId)
         os.environ["PYKOTASTATUS"] = "CANCELLED"
         
@@ -260,17 +250,22 @@
         self.Action = "ALLOW"   # job allowed by default
         self.Reason = None
-        self.JobId = sys.argv[1].strip()
-        # use CUPS' user when printing test pages from CUPS' web interface
-        self.UserName = sys.argv[2].strip() or self.originalUserName or pwd.getpwuid(os.geteuid())[0]
-        self.OriginalUserName = self.UserName[:]
-        self.Title = sys.argv[3].strip()
-        self.Copies = int(sys.argv[4].strip())
-        self.Options = sys.argv[5].strip()
+        try :
+            copies = int(sys.argv[4].strip())
+            if copies < 1 :
+                raise ValueError
+        except (ValueError, TypeError) :    
+            self.logdebug("Invalid number of copies '%s', using 1 instead." % sys.argv[4])
+            copies = 1
         if len(sys.argv) == 7 :
-            self.InputFile = sys.argv[6] # read job's datas from file
+            fname = sys.argv[6] # read job's datas from file
         else :    
-            self.InputFile = None        # read job's datas from stdin
+            fname = None        # read job's datas from stdin            
+            
+        self.Ticket = cups.JobTicket(sys.argv[1].strip(), self.PrinterName, \
+                                     copies, fname, sys.argv[5].strip())
+        self.UserName = self.Ticket.OriginatingUserName                             
+                                     
         self.DataFile = os.path.join(self.Directory, "%s-%s-%s-%s" % \
-                   (self.myname, self.PrinterName, self.UserName, self.JobId))
+                   (self.myname, self.PrinterName, self.UserName, self.Ticket.JobId))
         
         muststartwith = "%s:" % self.myname
@@ -310,47 +305,9 @@
         self.DeviceURI = device_uri
         
-        connerror = False
-        if haspkipplib :
-            self.ControlFile = "NotUsedAnymore"
-            self.logdebug("Querying CUPS server...")
-            cupsserver = pkipplib.CUPS() # TODO : username and password and/or encryption
-            answer = cupsserver.getJobAttributes(self.JobId)
-            if answer is None :
-                self.printInfo(_("Network error while querying the CUPS server : %s") \
-                                          % cupsserver.lastErrorMessage, "error")
-                connerror = True                        
-            else :    
-                self.logdebug("CUPS server answered without error.")
-                try :
-                    john = answer.job["job-originating-host-name"]
-                except KeyError :    
-                    try :
-                        john = answer.operation["job-originating-host-name"]
-                    except KeyError :    
-                        john = (None, None)
-                try :        
-                    jbing = answer.job["job-billing"]
-                except KeyError :    
-                    jbing = (None, None)
-                    
-        if connerror or not haspkipplib :        
-            (ippfilename, ippmessage) = self.parseIPPRequestFile()
-            self.ControlFile = ippfilename
-            john = ippmessage.operation_attributes.get("job-originating-host-name", \
-                   ippmessage.job_attributes.get("job-originating-host-name", \
-                   (None, None)))
-            jbing = ippmessage.job_attributes.get("job-billing", (None, None))
-                
-        if type(john) == type([]) : 
-            john = john[-1]
-        (chtype, self.ClientHost) = john 
-        if type(jbing) == type([]) : 
-            jbing = jbing[-1]
-        (jbtype, self.JobBillingCode) = jbing
-        if self.JobBillingCode is None :
+        if self.Ticket.BillingCode is None :
             self.OriginalJobBillingCode = None
         else :    
-            self.JobBillingCode = self.UTF8ToUserCharset(self.JobBillingCode)
-            self.OriginalJobBillingCode = self.JobBillingCode[:]
+            self.Ticket.BillingCode = self.UTF8ToUserCharset(self.Ticket.BillingCode)
+            self.OriginalJobBillingCode = self.Ticket.BillingCode[:]
             
         baselockfilename = self.DeviceURI.replace("/", ".")
@@ -365,14 +322,13 @@
         self.logdebug("Printername : %s" % self.PrinterName)
         self.logdebug("Username : %s" % self.UserName)
-        self.logdebug("JobId : %s" % self.JobId)
-        self.logdebug("Title : %s" % self.Title)
-        self.logdebug("Filename : %s" % self.InputFile)
-        self.logdebug("Copies : %s" % self.Copies)
-        self.logdebug("Options : %s" % self.Options)
+        self.logdebug("JobId : %s" % self.Ticket.JobId)
+        self.logdebug("Title : %s" % self.Ticket.Title)
+        self.logdebug("Filename : %s" % self.Ticket.FileName)
+        self.logdebug("Copies : %s" % self.Ticket.Copies)
+        self.logdebug("Options : %s" % self.Ticket.Options)
         self.logdebug("Directory : %s" % self.Directory) 
         self.logdebug("DataFile : %s" % self.DataFile)
-        self.logdebug("ControlFile : %s" % self.ControlFile)
-        self.logdebug("JobBillingCode : %s" % self.JobBillingCode)
-        self.logdebug("JobOriginatingHostName : %s" % self.ClientHost)
+        self.logdebug("JobBillingCode : %s" % self.Ticket.BillingCode)
+        self.logdebug("JobOriginatingHostName : %s" % self.Ticket.OriginatingHostName)
         
         # fakes some entries to allow for external mailto
@@ -413,12 +369,12 @@
         stripprefix = self.config.getStripTitle(self.PrinterName)
         if stripprefix :
-            if fnmatch.fnmatch(self.Title[:len(stripprefix)], stripprefix) :
+            if fnmatch.fnmatch(self.Ticket.Title[:len(stripprefix)], stripprefix) :
                 self.logdebug("Prefix [%s] removed from job's title [%s]." \
-                                      % (stripprefix, self.Title))
-                self.Title = self.Title[len(stripprefix):]
+                                      % (stripprefix, self.Ticket.Title))
+                self.Ticket.Title = self.Ticket.Title[len(stripprefix):]
                 
         self.logdebug("Username : %s" % self.UserName)
-        self.logdebug("BillingCode : %s" % self.JobBillingCode)
-        self.logdebug("Title : %s" % self.Title)
+        self.logdebug("BillingCode : %s" % self.Ticket.BillingCode)
+        self.logdebug("Title : %s" % self.Ticket.Title)
         self.logdebug("Job's attributes sanitizing done.")
                 
@@ -495,5 +451,5 @@
                     self.UserName = username
                 if billingcode is not None :
-                    self.JobBillingCode = billingcode 
+                    self.Ticket.BillingCode = billingcode 
         self.logdebug("Job ticket overwriting done.")
             
@@ -503,8 +459,8 @@
         mustclose = 0
         outfile = open(self.DataFile, "wb")    
-        if self.InputFile is not None :
+        if self.Ticket.FileName is not None :
             self.regainPriv()
-            infile = open(self.InputFile, "rb")
-            self.logdebug("Reading input datas from %s" % self.InputFile)
+            infile = open(self.Ticket.FileName, "rb")
+            self.logdebug("Reading input datas from %s" % self.Ticket.FileName)
             mustclose = 1
         else :    
@@ -584,72 +540,4 @@
                                    % self.softwareJobPrice)
         
-    def getCupsConfigDirectives(self, directives=[]) :
-        """Retrieves some CUPS directives from its configuration file.
-        
-           Returns a mapping with lowercased directives as keys and 
-           their setting as values.
-        """
-        self.logdebug("Parsing CUPS' configuration file...")
-        dirvalues = {} 
-        cupsroot = os.environ.get("CUPS_SERVERROOT", "/etc/cups")
-        cupsdconf = os.path.join(cupsroot, "cupsd.conf")
-        try :
-            conffile = open(cupsdconf, "r")
-        except IOError :    
-            raise PyKotaToolError, "Unable to open %s" % cupsdconf
-        else :    
-            for line in conffile.readlines() :
-                linecopy = line.strip().lower()
-                for di in [d.lower() for d in directives] :
-                    if linecopy.startswith("%s " % di) :
-                        try :
-                            val = line.split()[1]
-                        except :    
-                            pass # ignore errors, we take the last value in any case.
-                        else :    
-                            dirvalues[di] = val
-            conffile.close()            
-        self.logdebug("CUPS' configuration file parsed successfully.")
-        return dirvalues       
-            
-    def parseIPPRequestFile(self) :        
-        """Parses the IPP message file and returns a tuple (filename, parsedvalue)."""
-        self.logdebug("Parsing IPP request file...")
-        
-        class DummyClass :
-            """Class used to avoid errors."""
-            operation_attributes = {}
-            job_attributes = {}
-            
-        ippmessage = DummyClass() # in case the code below fails
-        
-        self.regainPriv()
-        cupsdconf = self.getCupsConfigDirectives(["RequestRoot"])
-        requestroot = cupsdconf.get("requestroot", "/var/spool/cups")
-        if (len(self.JobId) < 5) and self.JobId.isdigit() :
-            ippmessagefile = "c%05i" % int(self.JobId)
-        else :    
-            ippmessagefile = "c%s" % self.JobId
-        ippmessagefile = os.path.join(requestroot, ippmessagefile)
-        try :
-            ippdatafile = open(ippmessagefile)
-        except :    
-            self.logdebug("Unable to open IPP request file %s" % ippmessagefile)
-        else :    
-            self.logdebug("Parsing of IPP request file %s begins." % ippmessagefile)
-            try :
-                ippmessage = oldIPPRequest(ippdatafile.read())
-                ippmessage.parse()
-            except oldIPPError, msg :    
-                self.printInfo("Error while parsing %s : %s" \
-                                      % (ippmessagefile, msg), "warn")
-            else :    
-                self.logdebug("Parsing of IPP request file %s ends." \
-                                       % ippmessagefile)
-            ippdatafile.close()
-        self.dropPriv()
-        self.logdebug("IPP request file parsed successfully.")
-        return (ippmessagefile, ippmessage)
-                
     def exportJobInfo(self) :    
         """Exports the actual job's attributes to the environment."""
@@ -661,15 +549,14 @@
         os.environ["PYKOTAJOBSIZEBYTES"] = str(self.JobSizeBytes)
         os.environ["PYKOTAMD5SUM"] = self.JobMD5Sum
-        os.environ["PYKOTAJOBORIGINATINGHOSTNAME"] = self.ClientHost or ""
-        os.environ["PYKOTAJOBID"] = self.JobId
+        os.environ["PYKOTAJOBORIGINATINGHOSTNAME"] = self.Ticket.OriginatingHostName or ""
+        os.environ["PYKOTAJOBID"] = self.Ticket.JobId
         os.environ["PYKOTAUSERNAME"] = self.UserName
-        os.environ["PYKOTAORIGINALUSERNAME"] = self.OriginalUserName
-        os.environ["PYKOTATITLE"] = self.Title
-        os.environ["PYKOTACOPIES"] = str(self.Copies)
-        os.environ["PYKOTAOPTIONS"] = self.Options
-        os.environ["PYKOTAFILENAME"] = self.InputFile or ""
-        os.environ["PYKOTAJOBBILLING"] = self.JobBillingCode or ""
+        os.environ["PYKOTAORIGINALUSERNAME"] = self.Ticket.OriginalUserName
+        os.environ["PYKOTATITLE"] = self.Ticket.Title
+        os.environ["PYKOTACOPIES"] = str(self.Ticket.Copies)
+        os.environ["PYKOTAOPTIONS"] = self.Ticket.Options
+        os.environ["PYKOTAFILENAME"] = self.Ticket.FileName or ""
+        os.environ["PYKOTAJOBBILLING"] = self.Ticket.BillingCode or ""
         os.environ["PYKOTAORIGINALJOBBILLING"] = self.OriginalJobBillingCode or ""
-        os.environ["PYKOTACONTROLFILE"] = self.ControlFile
         os.environ["PYKOTAPRINTERHOSTNAME"] = self.PrinterHostName
         os.environ["PYKOTAPRECOMPUTEDJOBSIZE"] = str(self.softwareJobSize)
@@ -763,5 +650,5 @@
             return "%s@%s(%s) => %s" % (self.UserName, \
                                         self.PrinterName, \
-                                        self.JobId, \
+                                        self.Ticket.JobId, \
                                         message)
         except :                                               
@@ -970,15 +857,15 @@
         self.logdebug("Retrieving billing code information from the database...")
         self.BillingCode = None
-        if self.JobBillingCode :
-            self.BillingCode = self.storage.getBillingCode(self.JobBillingCode)
+        if self.Ticket.BillingCode :
+            self.BillingCode = self.storage.getBillingCode(self.Ticket.BillingCode)
             if self.BillingCode.Exists :
-                self.logdebug("Billing code [%s] found in database." % self.JobBillingCode)
+                self.logdebug("Billing code [%s] found in database." % self.Ticket.BillingCode)
             else :
-                msg = "Unknown billing code [%s] : " % self.JobBillingCode
+                msg = "Unknown billing code [%s] : " % self.Ticket.BillingCode
                 (newaction, script) = self.config.getUnknownBillingCode(self.PrinterName)
                 if newaction == "CREATE" :
                     self.logdebug(msg + "will be created.")
                     self.storage.addBillingCode(self.BillingCode)
-                    self.BillingCode = self.storage.getBillingCode(self.JobBillingCode)
+                    self.BillingCode = self.storage.getBillingCode(self.Ticket.BillingCode)
                     if self.BillingCode.Exists :
                         self.logdebug(msg + "has been created.")
@@ -1311,8 +1198,8 @@
             
             # adds the current job to history    
-            self.Printer.addJobToHistory(self.JobId, self.User, self.accounter.getLastPageCounter(), \
-                                    self.Action, self.JobSize, self.JobPrice, self.InputFile, \
-                                    self.Title, self.Copies, self.Options, self.ClientHost, \
-                                    self.JobSizeBytes, self.JobMD5Sum, None, self.JobBillingCode, \
+            self.Printer.addJobToHistory(self.Ticket.JobId, self.User, self.accounter.getLastPageCounter(), \
+                                    self.Action, self.JobSize, self.JobPrice, self.Ticket.FileName, \
+                                    self.Ticket.Title, self.Ticket.Copies, self.Ticket.Options, self.Ticket.OriginatingHostName, \
+                                    self.JobSizeBytes, self.JobMD5Sum, None, self.Ticket.BillingCode, \
                                     self.softwareJobSize, self.softwareJobPrice)
             self.printInfo(_("Job added to history."))
@@ -1363,10 +1250,10 @@
         loopcnt = 1 
         while True :            
-            if self.InputFile is None :
+            if self.Ticket.FileName is None :
                 infile = open(self.DataFile, "rb")
             else :    
                 infile = None
             retcode = self.runOriginalBackend(infile)
-            if self.InputFile is None :
+            if self.Ticket.FileName is None :
                 infile.close()
             if not retcode :
@@ -1474,5 +1361,5 @@
                 retcode = wrapper.mainWork()
             except KeyboardInterrupt :    
-                wrapper.printInfo(_("Job %s interrupted by the administrator !") % wrapper.JobId, "warn")
+                wrapper.printInfo(_("Job %s interrupted by the administrator !") % wrapper.Ticket.JobId, "warn")
                 retcode = 0
             except SystemExit, err :    
