Show
Ignore:
Timestamp:
05/17/05 22:24:40 (19 years ago)
Author:
jerome
Message:

Integrated the major rewrite of ipp.py into PyKota.
Now the job-originating-hostname is correctly retrieved
in all cases I've seen.

Files:
1 modified

Legend:

Unmodified
Added
Removed
  • pykota/trunk/pykota/ipp.py

    r2190 r2254  
    22# -*- coding: ISO-8859-15 -*- 
    33# 
    4 # PyKota - Print Quotas for CUPS and LPRng 
    5 # 
    6 # (c) 2003-2004 Jerome Alet <alet@librelogiciel.com> 
     4# PyKota 
     5# 
     6# PyKota : Print Quotas for CUPS and LPRng 
     7# 
     8# (c) 2003, 2004, 2005 Jerome Alet <alet@librelogiciel.com> 
    79# This program is free software; you can redistribute it and/or modify 
    810# it under the terms of the GNU General Public License as published by 
     
    3234UNSUPPORTED_ATTRIBUTES_TAG = 0x05 
    3335 
    34 class PyKotaIPPError(Exception): 
    35     """An exception for PyKota IPP related stuff.""" 
     36class IPPError(Exception): 
     37    """An exception for IPP related stuff.""" 
    3638    def __init__(self, message = ""): 
    3739        self.message = message 
     
    4244 
    4345class IPPMessage : 
    44     """A class for IPP message files.""" 
    45     def __init__(self, data) : 
    46         """Initializes an IPP Message object.""" 
     46    """A class for IPP message files. 
     47     
     48       Usage : 
     49        
     50         fp = open("/var/spool/cups/c00001", "rb") 
     51         message = IPPMessage(fp.read()) 
     52         fp.close() 
     53         print "IPP version : %s" % message.version 
     54         print "IPP operation Id : %s" % message.operation_id 
     55         print "IPP request Id : %s" % message.request_id 
     56         for attrtype in ("operation", "job", "printer", "unsupported") : 
     57             attrdict = getattr(message, "%s_attributes" % attrtype) 
     58             if attrdict : 
     59                 print "%s attributes :" % attrtype.title() 
     60                 for key in attrdict.keys() : 
     61                     print "  %s : %s" % (key, attrdict[key]) 
     62    """ 
     63    def __init__(self, data, debug=0) : 
     64        """Initializes and parses IPP Message object. 
     65         
     66           Parameters : 
     67            
     68             data : the IPP Message's content. 
     69             debug : a boolean value to output debug info on stderr. 
     70        """ 
     71        self.debug = debug 
    4772        self.data = data 
    48         self._attributes = {} 
    49         self.curname = None 
     73        self.operation_attributes = {} 
     74        self.job_attributes = {} 
     75        self.printer_attributes = {} 
     76        self.unsupported_attributes = {} 
    5077        self.tags = [ None ] * 256      # by default all tags reserved 
    5178         
    5279        # Delimiter tags 
    53         self.tags[0x01] = "operation-attributes-tag" 
    54         self.tags[0x02] = "job-attributes-tag" 
    55         self.tags[0x03] = "end-of-attributes-tag" 
    56         self.tags[0x04] = "printer-attributes-tag" 
    57         self.tags[0x05] = "unsupported-attributes-tag" 
     80        self.tags[OPERATION_ATTRIBUTES_TAG] = "operation-attributes-tag" 
     81        self.tags[JOB_ATTRIBUTES_TAG] = "job-attributes-tag" 
     82        self.tags[END_OF_ATTRIBUTES_TAG] = "end-of-attributes-tag" 
     83        self.tags[PRINTER_ATTRIBUTES_TAG] = "printer-attributes-tag" 
     84        self.tags[UNSUPPORTED_ATTRIBUTES_TAG] = "unsupported-attributes-tag" 
    5885         
    5986        # out of band values 
     
    93120        self.parse() 
    94121         
    95     def __getattr__(self, attrname) :     
    96         """Allows self.attributes to return the attributes names.""" 
    97         if attrname == "attributes" : 
    98             keys = self._attributes.keys() 
    99             keys.sort() 
    100             return keys 
    101         raise AttributeError, attrname 
     122    def printInfo(self, msg) :     
     123        """Prints a debug message.""" 
     124        if self.debug : 
     125            sys.stderr.write("%s\n" % msg) 
     126            sys.stderr.flush() 
    102127             
    103     def __getitem__(self, ippattrname) :     
    104         """Fakes a dictionnary d['key'] notation.""" 
    105         value = self._attributes.get(ippattrname) 
    106         if value is not None : 
    107             if len(value) == 1 : 
    108                 value = value[0] 
    109         return value         
    110     get = __getitem__     
    111      
    112     def keys(self) : 
    113         """Fakes a dictionnary .keys() method.""" 
    114         return self._attributes.keys() 
    115          
    116128    def parseTag(self) :     
    117129        """Extracts information from an IPP tag.""" 
    118130        pos = self.position 
    119         valuetag = self.tags[ord(self.data[pos])] 
    120         # print valuetag.get("name") 
     131        tagtype = self.tags[ord(self.data[pos])] 
    121132        pos += 1 
    122133        posend = pos2 = pos + 2 
    123134        namelength = unpack(">H", self.data[pos:pos2])[0] 
    124135        if not namelength : 
    125             name = self.curname 
     136            name = self._curname 
    126137        else :     
    127138            posend += namelength 
    128             self.curname = name = self.data[pos2:posend] 
     139            self._curname = name = self.data[pos2:posend] 
    129140        pos2 = posend + 2 
    130141        valuelength = unpack(">H", self.data[posend:pos2])[0] 
    131142        posend = pos2 + valuelength 
    132143        value = self.data[pos2:posend] 
    133         oldval = self._attributes.setdefault(name, []) 
    134         oldval.append(value) 
     144        if tagtype in ("integer", "enum") : 
     145            value = unpack(">I", value)[0] 
     146        oldval = self._curdict.setdefault(name, []) 
     147        oldval.append((tagtype, value)) 
     148        self.printInfo("%s(%s) %s" % (name, tagtype, value)) 
    135149        return posend - self.position 
    136150         
    137151    def operation_attributes_tag(self) :  
    138152        """Indicates that the parser enters into an operation-attributes-tag group.""" 
     153        self.printInfo("Start of operation_attributes_tag") 
     154        self._curdict = self.operation_attributes 
    139155        return self.parseTag() 
    140156         
    141157    def job_attributes_tag(self) :  
    142         """Indicates that the parser enters into an operation-attributes-tag group.""" 
     158        """Indicates that the parser enters into a job-attributes-tag group.""" 
     159        self.printInfo("Start of job_attributes_tag") 
     160        self._curdict = self.job_attributes 
    143161        return self.parseTag() 
    144162         
    145163    def printer_attributes_tag(self) :  
    146         """Indicates that the parser enters into an operation-attributes-tag group.""" 
     164        """Indicates that the parser enters into a printer-attributes-tag group.""" 
     165        self.printInfo("Start of printer_attributes_tag") 
     166        self._curdict = self.printer_attributes 
     167        return self.parseTag() 
     168         
     169    def unsupported_attributes_tag(self) :  
     170        """Indicates that the parser enters into an unsupported-attributes-tag group.""" 
     171        self.printInfo("Start of unsupported_attributes_tag") 
     172        self._curdict = self.unsupported_attributes 
    147173        return self.parseTag() 
    148174         
     
    151177         
    152178           NB : Only a subset of RFC2910 is implemented. 
    153            We are only interested in textual informations for now anyway. 
    154179        """ 
     180        self._curname = None 
     181        self._curdict = None 
    155182        self.version = "%s.%s" % (ord(self.data[0]), ord(self.data[1])) 
    156183        self.operation_id = "0x%04x" % unpack(">H", self.data[2:4])[0] 
     
    171198                tag = ord(self.data[self.position]) 
    172199        except IndexError : 
    173             raise PyKotaIPPError, "Unexpected end of IPP message." 
     200            raise IPPError, "Unexpected end of IPP message." 
     201             
     202        # Now transform all one-element lists into single values 
     203        for attrtype in ("operation", "job", "printer") : 
     204            attrdict = getattr(self, "%s_attributes" % attrtype) 
     205            for (key, value) in attrdict.items() : 
     206                if len(value) == 1 : 
     207                    attrdict[key] = value[0] 
    174208             
    175209if __name__ == "__main__" :             
    176     if len(sys.argv) < 2 : 
    177         print "usage : python ipp.py /var/spool/cups/c00005 (for example)\n" 
     210    if (len(sys.argv) < 2) or (sys.argv[1] == "--debug") : 
     211        print "usage : python ipp.py /var/spool/cups/c00005 [--debug] (for example)\n" 
    178212    else :     
    179         infile = open(sys.argv[1]) 
    180         message = IPPMessage(infile.read()) 
     213        infile = open(sys.argv[1], "rb") 
     214        message = IPPMessage(infile.read(), debug=(sys.argv[-1]=="--debug")) 
    181215        infile.close() 
    182         for key in message.keys() : 
    183             print "%s : %s" % (key, message[key]) 
     216        print "IPP version : %s" % message.version 
     217        print "IPP operation Id : %s" % message.operation_id 
     218        print "IPP request Id : %s" % message.request_id 
     219        for attrtype in ("operation", "job", "printer", "unsupported") : 
     220            attrdict = getattr(message, "%s_attributes" % attrtype) 
     221            if attrdict : 
     222                print "%s attributes :" % attrtype.title() 
     223                for key in attrdict.keys() : 
     224                    print "  %s : %s" % (key, attrdict[key])