Changeset 2311

Show
Ignore:
Timestamp:
06/13/05 15:22:02 (19 years ago)
Author:
jerome
Message:

Fixed bug : exception name was incorrect in an except statement in cupspykota.
Improved the IPP module : can now generate IPP messages as well as parsing them.

Location:
pykota/trunk
Files:
4 modified

Legend:

Unmodified
Added
Removed
  • pykota/trunk/bin/cupspykota

    r2308 r2311  
    209209                try : 
    210210                    ippmessage = IPPMessage(ippdatafile.read()) 
    211                 except PyKotaIPPError, msg :     
     211                    ippmessage.parse() 
     212                except IPPError, msg :     
    212213                    self.printInfo("Error while parsing %s : %s" % (ippmessagefile, msg), "warn") 
    213214                else :     
  • pykota/trunk/NEWS

    r2308 r2311  
    2222PyKota NEWS : 
    2323        
     24    - 1.23alpha10 : 
     25     
     26        - Fixed a bad exception name in cupspykota when parsing IPP messages. 
     27         
     28        - Improved the IPP messages module : it can now generate IPP messages 
     29          in addition to parsing them. 
     30         
    2431    - 1.23alpha9 :    
    2532     
  • pykota/trunk/pykota/ipp.py

    r2302 r2311  
    2626 
    2727import sys 
    28 from struct import unpack 
    29  
    30 OPERATION_ATTRIBUTES_TAG = 0x01 
    31 JOB_ATTRIBUTES_TAG = 0x02 
    32 END_OF_ATTRIBUTES_TAG = 0x03 
    33 PRINTER_ATTRIBUTES_TAG = 0x04 
    34 UNSUPPORTED_ATTRIBUTES_TAG = 0x05 
     28from struct import pack, unpack 
    3529 
    3630class IPPError(Exception): 
     
    5145         message = IPPMessage(fp.read()) 
    5246         fp.close() 
     47         message.parse() 
     48         # print str(message) 
     49         # print message.dump() 
    5350         print "IPP version : %s" % message.version 
    5451         print "IPP operation Id : %s" % message.operation_id 
     
    6259    """ 
    6360    attributes_types = ("operation", "job", "printer", "unsupported") 
    64     def __init__(self, data, debug=0) : 
    65         """Initializes and parses IPP Message object. 
     61    def __init__(self, data="", version=None, operation_id=None, request_id=None, debug=0) : 
     62        """Initializes an IPP Message object. 
    6663         
    6764           Parameters : 
     
    7269        self.debug = debug 
    7370        self.data = data 
     71        self.parsed = 0 
     72         
     73        self.version = version 
     74        self.operation_id = operation_id 
     75        self.request_id = request_id 
     76         
    7477        for attrtype in self.attributes_types : 
    7578            setattr(self, "%s_attributes" % attrtype, {}) 
     
    7780         
    7881        # Delimiter tags 
    79         self.tags[OPERATION_ATTRIBUTES_TAG] = "operation-attributes-tag" 
    80         self.tags[JOB_ATTRIBUTES_TAG] = "job-attributes-tag" 
    81         self.tags[END_OF_ATTRIBUTES_TAG] = "end-of-attributes-tag" 
    82         self.tags[PRINTER_ATTRIBUTES_TAG] = "printer-attributes-tag" 
    83         self.tags[UNSUPPORTED_ATTRIBUTES_TAG] = "unsupported-attributes-tag" 
     82        self.tags[0x01] = "operation-attributes-tag" 
     83        self.tags[0x02] = "job-attributes-tag" 
     84        self.tags[0x03] = "end-of-attributes-tag" 
     85        self.tags[0x04] = "printer-attributes-tag" 
     86        self.tags[0x05] = "unsupported-attributes-tag" 
    8487         
    8588        # out of band values 
     
    108111        self.tags[0x41] = "textWithoutLanguage" 
    109112        self.tags[0x42] = "nameWithoutLanguage" 
    110         # self.tags[0x43] = "reserved" 
     113        self.tags[0x43] = "reserved" 
    111114        self.tags[0x44] = "keyword" 
    112115        self.tags[0x45] = "uri" 
     
    116119        self.tags[0x49] = "mimeMediaType" 
    117120         
    118         # now parses the IPP message 
    119         self.parse() 
     121        # Reverse mapping to generate IPP messages 
     122        self.dictags = {} 
     123        for i in range(len(self.tags)) : 
     124            value = self.tags[i] 
     125            if value is not None : 
     126                self.dictags[value] = i 
    120127         
    121128    def printInfo(self, msg) :     
     
    125132            sys.stderr.flush() 
    126133             
     134    def __str__(self) :         
     135        """Returns the parsed IPP message in a readable form.""" 
     136        if not self.parsed : 
     137            return "" 
     138        else :     
     139            buffer = [] 
     140            buffer.append("IPP version : %s" % self.version) 
     141            buffer.append("IPP operation Id : %s" % self.operation_id) 
     142            buffer.append("IPP request Id : %s" % self.request_id) 
     143            for attrtype in self.attributes_types : 
     144                attrdict = getattr(self, "%s_attributes" % attrtype) 
     145                if attrdict : 
     146                    buffer.append("%s attributes :" % attrtype.title()) 
     147                    for key in attrdict.keys() : 
     148                        buffer.append("  %s : %s" % (key, attrdict[key])) 
     149            return "\n".join(buffer) 
     150         
     151    def dump(self) :     
     152        """Generates an IPP Message. 
     153         
     154           Returns the message as a string of text. 
     155        """     
     156        buffer = [] 
     157        if None not in (self.version, self.operation_id, self.request_id) : 
     158            version = [int(p) for p in self.version.split('.')] 
     159            buffer.append(chr(version[0]) + chr(version[1])) 
     160            buffer.append(pack(">H", int(self.operation_id, 16))) 
     161            buffer.append(pack(">I", int(self.request_id, 16))) 
     162            for attrtype in self.attributes_types : 
     163                tagprinted = 0 
     164                for (attrname, value) in getattr(self, "%s_attributes" % attrtype).items() : 
     165                    if not tagprinted : 
     166                        buffer.append(chr(self.dictags["%s-attributes-tag" % attrtype])) 
     167                        tagprinted = 1 
     168                    if type(value) != type([]) : 
     169                        value = [ value ] 
     170                    for (vtype, val) in value : 
     171                        buffer.append(chr(self.dictags[vtype])) 
     172                        buffer.append(pack(">H", len(attrname))) 
     173                        buffer.append(attrname) 
     174                        if vtype in ("integer", "enum") : 
     175                            buffer.append(pack(">H", 4)) 
     176                            buffer.append(pack(">I", val)) 
     177                        elif vtype == "boolean" : 
     178                            buffer.append(pack(">H", 1)) 
     179                            buffer.append(chr(val)) 
     180                        else :     
     181                            buffer.append(pack(">H", len(val))) 
     182                            buffer.append(val) 
     183            buffer.append(chr(self.dictags["end-of-attributes-tag"])) 
     184        return "".join(buffer) 
     185         
     186    def parse(self) : 
     187        """Parses an IPP Message. 
     188         
     189           NB : Only a subset of RFC2910 is implemented. 
     190        """ 
     191        self._curname = None 
     192        self._curdict = None 
     193        self.version = "%s.%s" % (ord(self.data[0]), ord(self.data[1])) 
     194        self.operation_id = "0x%04x" % unpack(">H", self.data[2:4])[0] 
     195        self.request_id = "0x%08x" % unpack(">I", self.data[4:8])[0] 
     196        self.position = 8 
     197        endofattributes = self.dictags["end-of-attributes-tag"] 
     198        unsupportedattributes = self.dictags["unsupported-attributes-tag"] 
     199        try : 
     200            tag = ord(self.data[self.position]) 
     201            while tag != endofattributes : 
     202                self.position += 1 
     203                name = self.tags[tag] 
     204                if name is not None : 
     205                    func = getattr(self, name.replace("-", "_"), None) 
     206                    if func is not None : 
     207                        self.position += func() 
     208                        if ord(self.data[self.position]) > unsupportedattributes : 
     209                            self.position -= 1 
     210                            continue 
     211                tag = ord(self.data[self.position]) 
     212        except IndexError : 
     213            raise IPPError, "Unexpected end of IPP message." 
     214             
     215        # Now transform all one-element lists into single values 
     216        for attrtype in self.attributes_types : 
     217            attrdict = getattr(self, "%s_attributes" % attrtype) 
     218            for (key, value) in attrdict.items() : 
     219                if len(value) == 1 : 
     220                    attrdict[key] = value[0] 
     221        self.parsed = 1             
     222         
    127223    def parseTag(self) :     
    128224        """Extracts information from an IPP tag.""" 
     
    143239        if tagtype in ("integer", "enum") : 
    144240            value = unpack(">I", value)[0] 
     241        elif tagtype == "boolean" :     
     242            value = ord(value) 
    145243        oldval = self._curdict.setdefault(name, []) 
    146244        oldval.append((tagtype, value)) 
     
    171269        self._curdict = self.unsupported_attributes 
    172270        return self.parseTag() 
    173          
    174     def parse(self) : 
    175         """Parses an IPP Message. 
    176          
    177            NB : Only a subset of RFC2910 is implemented. 
    178         """ 
    179         self._curname = None 
    180         self._curdict = None 
    181         self.version = "%s.%s" % (ord(self.data[0]), ord(self.data[1])) 
    182         self.operation_id = "0x%04x" % unpack(">H", self.data[2:4])[0] 
    183         self.request_id = "0x%08x" % unpack(">I", self.data[4:8])[0] 
    184         self.position = 8 
    185         try : 
    186             tag = ord(self.data[self.position]) 
    187             while tag != END_OF_ATTRIBUTES_TAG : 
    188                 self.position += 1 
    189                 name = self.tags[tag] 
    190                 if name is not None : 
    191                     func = getattr(self, name.replace("-", "_"), None) 
    192                     if func is not None : 
    193                         self.position += func() 
    194                         if ord(self.data[self.position]) > UNSUPPORTED_ATTRIBUTES_TAG : 
    195                             self.position -= 1 
    196                             continue 
    197                 tag = ord(self.data[self.position]) 
    198         except IndexError : 
    199             raise IPPError, "Unexpected end of IPP message." 
    200              
    201         # Now transform all one-element lists into single values 
    202         for attrtype in self.attributes_types : 
    203             attrdict = getattr(self, "%s_attributes" % attrtype) 
    204             for (key, value) in attrdict.items() : 
    205                 if len(value) == 1 : 
    206                     attrdict[key] = value[0] 
    207271             
    208272if __name__ == "__main__" :             
     
    213277        message = IPPMessage(infile.read(), debug=(sys.argv[-1]=="--debug")) 
    214278        infile.close() 
    215         print "IPP version : %s" % message.version 
    216         print "IPP operation Id : %s" % message.operation_id 
    217         print "IPP request Id : %s" % message.request_id 
    218         for attrtype in message.attributes_types : 
    219             attrdict = getattr(message, "%s_attributes" % attrtype) 
    220             if attrdict : 
    221                 print "%s attributes :" % attrtype.title() 
    222                 for key in attrdict.keys() : 
    223                     print "  %s : %s" % (key, attrdict[key]) 
     279        message.parse() 
     280         
     281        message2 = IPPMessage(message.dump()) 
     282        message2.parse() 
     283         
     284        # We now compare the message parsed, and the output 
     285        # of the parsing of the dumped message which was parsed. 
     286        # We sort the results for the test, because the attributes ordering  
     287        # may vary since Python dictionnaries are not sorted. 
     288        strmessage = str(message) 
     289        strmessage2 = str(message2) 
     290        lstmessage = strmessage.split("\n") 
     291        lstmessage.sort() 
     292        lstmessage2 = strmessage2.split("\n") 
     293        lstmessage2.sort() 
     294        if lstmessage == lstmessage2 : 
     295            print "Test OK : parsing original and parsing the output of the dump produce the same result !" 
     296            print strmessage 
     297        else :     
     298            print "Test Failed !" 
     299            print strmessage 
     300            print 
     301            print strmessage2 
  • pykota/trunk/pykota/version.py

    r2305 r2311  
    2222# 
    2323 
    24 __version__ = "1.23alpha9_unofficial" 
     24__version__ = "1.23alpha10_unofficial" 
    2525 
    2626__doc__ = "PyKota : a complete Printing Quota Solution for CUPS and LPRng."