Index: tea4cups/trunk/tea4cups
===================================================================
--- tea4cups/trunk/tea4cups (revision 630)
+++ tea4cups/trunk/tea4cups (revision 631)
@@ -91,9 +91,11 @@
 class IPPMessage :
     """A class for IPP message files."""
-    def __init__(self, data) :
+    def __init__(self, data, debug=0) :
         """Initializes an IPP Message object."""
+        self.debug = debug
         self.data = data
-        self._attributes = {}
-        self.curname = None
+        self.operation_attributes = {}
+        self.job_attributes = {}
+        self.printer_attributes = {}
         self.tags = [ None ] * 256      # by default all tags reserved
         
@@ -141,54 +143,49 @@
         self.parse()
         
-    def __getattr__(self, attrname) :    
-        """Allows self.attributes to return the attributes names."""
-        if attrname == "attributes" :
-            keys = self._attributes.keys()
-            keys.sort()
-            return keys
-        raise AttributeError, attrname
-            
-    def __getitem__(self, ippattrname) :    
-        """Fakes a dictionnary d['key'] notation."""
-        value = self._attributes.get(ippattrname)
-        if value is not None :
-            if len(value) == 1 :
-                value = value[0]
-        return value        
-    get = __getitem__    
-        
     def parseTag(self) :    
         """Extracts information from an IPP tag."""
         pos = self.position
         valuetag = self.tags[ord(self.data[pos])]
-        # print valuetag.get("name")
         pos += 1
         posend = pos2 = pos + 2
         namelength = unpack(">H", self.data[pos:pos2])[0]
         if not namelength :
-            name = self.curname
+            name = self._curname
         else :    
             posend += namelength
-            self.curname = name = self.data[pos2:posend]
+            self._curname = name = self.data[pos2:posend]
         pos2 = posend + 2
         valuelength = unpack(">H", self.data[posend:pos2])[0]
         posend = pos2 + valuelength
         value = self.data[pos2:posend]
-        oldval = self._attributes.setdefault(name, [])
-        oldval.append(value)
+        oldval = self._curdict.setdefault(name, [])
+        oldval.append((valuetag, value))
+        self.printInfo("%s(%s) %s" % (name, valuetag, value))
         return posend - self.position
         
     def operation_attributes_tag(self) : 
         """Indicates that the parser enters into an operation-attributes-tag group."""
+        self.printInfo("Start of operation_attributes_tag")
+        self._curdict = self.operation_attributes
         return self.parseTag()
         
     def job_attributes_tag(self) : 
-        """Indicates that the parser enters into a job-attributes-tag group."""
+        """Indicates that the parser enters into an operation-attributes-tag group."""
+        self.printInfo("Start of job_attributes_tag")
+        self._curdict = self.job_attributes
         return self.parseTag()
         
     def printer_attributes_tag(self) : 
-        """Indicates that the parser enters into a printer-attributes-tag group."""
+        """Indicates that the parser enters into an operation-attributes-tag group."""
+        self.printInfo("Start of printer_attributes_tag")
+        self._curdict = self.printer_attributes
         return self.parseTag()
         
+    def printInfo(self, msg) :    
+        """Prints a debug message."""
+        if self.debug :
+            sys.stderr.write("%s\n" % msg)
+            sys.stderr.flush()
+            
     def parse(self) :
         """Parses an IPP Message.
@@ -197,4 +194,6 @@
            We are only interested in textual informations for now anyway.
         """
+        self._curname = None
+        self._curdict = None
         self.version = "%s.%s" % (ord(self.data[0]), ord(self.data[1]))
         self.operation_id = "0x%04x" % unpack(">H", self.data[2:4])[0]
@@ -216,4 +215,11 @@
         except IndexError :
             raise IPPError, "Unexpected end of IPP message."
+            
+        # Now transform all one-element lists into single values
+        for attrtype in ("operation", "job", "printer") :
+            attrdict = getattr(self, "%s_attributes" % attrtype)
+            for (key, value) in attrdict.items() :
+                if len(value) == 1 :
+                    attrdict[key] = value[0]
             
 class FakeConfig :    
@@ -423,6 +429,7 @@
         (ippfilename, ippmessage) = self.parseIPPMessageFile()
         self.ControlFile = ippfilename
-        self.ClientHost = ippmessage.get("job-originating-host-name")
-        self.JobBilling = ippmessage.get("job-billing")
+        (chtype, self.ClientHost) = ippmessage.operation_attributes.get("job-originating-host-name", \
+                                          ippmessage.job_attributes.get("job-originating-host-name", (None, None)))
+        (jbtype, self.JobBilling) = ippmessage.job_attributes.get("job-billing", (None, None))
             
     def getCupsConfigDirectives(self, directives=[]) :
Index: tea4cups/trunk/NEWS
===================================================================
--- tea4cups/trunk/NEWS (revision 630)
+++ tea4cups/trunk/NEWS (revision 631)
@@ -24,4 +24,6 @@
   * 2.12alpha :
   
+    - Greatly improved the IPP parser.
+    
     - When printing test pages from CUPS' web interface, the empty username
       is now overwritten with the username CUPS is running as.
