Changeset 8979f90


Ignore:
Timestamp:
Mar 5, 2011, 10:27:55 PM (13 years ago)
Author:
Jessica B. Hamrick <jhamrick@…>
Branches:
no-cups
Children:
2646571
Parents:
e97c37d
git-author:
Jessica B. Hamrick <jhamrick@…> (03/05/11 22:27:55)
git-committer:
Jessica B. Hamrick <jhamrick@…> (03/05/11 22:27:55)
Message:

Put various IPP classes in their own files

Location:
server/lib
Files:
3 added
2 edited

Legend:

Unmodified
Added
Removed
  • server/lib/ippconstants.py

    re97c37d r8979f90  
     1#!/usr/bin/python
     2
    13class Misc():
    24    """
  • server/lib/ipprequest.py

    rc5e88d0 r8979f90  
    55# initialize logger
    66logger = logging.getLogger("ippLogger")
    7 
    8 class IPPTags():
    9     """
    10     Contains constants for the various IPP tags, as defined by RFC
    11     2565.
    12     """
    13    
    14     # various tags
    15     ZERO_NAME_LENGTH                  = 0x00
    16     OPERATION_ATTRIBUTES_TAG          = 0x01
    17     JOB_ATTRIBUTES_TAG                = 0x02
    18     END_OF_ATTRIBUTES_TAG             = 0x03
    19     PRINTER_ATTRIBUTES_TAG            = 0x04
    20     UNSUPPORTED_ATTRIBUTES_TAG        = 0x05
    21    
    22     # "out of band" value tags
    23     UNSUPPORTED                       = 0x10
    24     DEFAULT                           = 0x11
    25     UNKNOWN                           = 0x12
    26     NO_VALUE                          = 0x13
    27    
    28     # integer value tags
    29     GENERIC_INTEGER                   = 0x20
    30     INTEGER                           = 0x21
    31     BOOLEAN                           = 0x22
    32     ENUM                              = 0x23
    33 
    34     # octetstring value tags
    35     UNSPECIFIED_OCTETSTRING           = 0x30
    36     DATETIME                          = 0x31
    37     RESOLUTION                        = 0x32
    38     RANGE_OF_INTEGER                  = 0x33
    39     TEXT_WITH_LANGUAGE                = 0x35
    40     NAME_WITH_LANGUAGE                = 0x36
    41 
    42     # character-string value tags
    43     GENERIC_CHAR_STRING               = 0x40
    44     TEXT_WITHOUT_LANGUAGE             = 0x41
    45     NAME_WITHOUT_LANGUAGE             = 0x42
    46     KEYWORD                           = 0x44
    47     URI                               = 0x45
    48     URI_SCHEME                        = 0x46
    49     CHARSET                           = 0x47
    50     NATURAL_LANGUAGE                  = 0x48
    51     MIME_MEDIA_TYPE                   = 0x49                                   
    52 
    53 class IPPValue():
    54     """
    55     An IPP value consists of a tag and a value, and optionally, a name.
    56 
    57     From RFC 2565:
    58      -----------------------------------------------
    59      |                   value-tag                 |   1 byte
    60      -----------------------------------------------
    61      |               name-length  (value is u)     |   2 bytes
    62      -----------------------------------------------
    63      |                     name                    |   u bytes
    64      -----------------------------------------------
    65      |              value-length  (value is v)     |   2 bytes
    66      -----------------------------------------------
    67      |                     value                   |   v bytes
    68      -----------------------------------------------   
    69     """
    70 
    71     def __init__(self, value_tag, value, unpack=True):
    72         """
    73         Initialize an IPPValue:
    74 
    75         Arguments:
    76 
    77             value_tag -- one byte, identifying the type of value
    78 
    79             value -- variable size, containing the actual value
    80         """
    81 
    82         # make sure value_tag isn't empty
    83         assert value_tag is not None
    84         # make sure value isn't empty
    85         assert value is not None
    86 
    87         self.value_tag = value_tag
    88         self.value = value
    89 
    90         if not unpack: return
    91 
    92         # out-of-band value tags
    93         if self.value_tag == IPPTags.UNSUPPORTED or \
    94                self.value_tag == IPPTags.DEFAULT or \
    95                self.value_tag == IPPTags.UNKNOWN or \
    96                self.value_tag == IPPTags.NO_VALUE:
    97             self.value = ''
    98 
    99         # integer value tags
    100         elif self.value_tag == IPPTags.GENERIC_INTEGER:
    101             pass # not supported
    102         elif self.value_tag == IPPTags.INTEGER:
    103             self.value = struct.unpack('>i', value)[0]
    104         elif self.value_tag == IPPTags.BOOLEAN:
    105             self.value = struct.unpack('>?', value)[0]
    106         elif self.value_tag == IPPTags.ENUM:
    107             self.value = struct.unpack('>i', value)[0]
    108 
    109         # octet string value tags
    110         elif self.value_tag == IPPTags.UNSPECIFIED_OCTETSTRING:
    111             pass
    112        
    113         elif self.value_tag == IPPTags.DATETIME:
    114             # field  octets  contents                  range
    115             # -----  ------  --------                  -----
    116             #   1      1-2   year                      0..65536
    117             #   2       3    month                     1..12
    118             #   3       4    day                       1..31
    119             #   4       5    hour                      0..23
    120             #   5       6    minutes                   0..59
    121             #   6       7    seconds                   0..60
    122             #                (use 60 for leap-second)
    123             #   7       8    deci-seconds              0..9
    124             #   8       9    direction from UTC        '+' / '-'
    125             #   9      10    hours from UTC            0..11
    126             #  10      11    minutes from UTC          0..59
    127 
    128             self.value = struct.unpack('>hbbbbbbcbb', value)[0]
    129            
    130         elif self.value_tag == IPPTags.RESOLUTION:
    131             # OCTET-STRING consisting of nine octets of 2
    132             # SIGNED-INTEGERs followed by a SIGNED-BYTE. The first
    133             # SIGNED-INTEGER contains the value of cross feed
    134             # direction resolution. The second SIGNED-INTEGER contains
    135             # the value of feed direction resolution. The SIGNED-BYTE
    136             # contains the units
    137 
    138             self.value = struct.unpack('>iib', value)
    139            
    140         elif self.value_tag == IPPTags.RANGE_OF_INTEGER:
    141             # Eight octets consisting of 2 SIGNED-INTEGERs.  The first
    142             # SIGNED-INTEGER contains the lower bound and the second
    143             # SIGNED-INTEGER contains the upper bound.
    144 
    145             self.value = struct.unpack('>ii', value)
    146 
    147         elif self.value_tag == IPPTags.TEXT_WITH_LANGUAGE or \
    148                  self.value_tag == IPPTags.NAME_WITH_LANGUAGE:
    149             a = struct.unpack('>h', value[:2])[0]
    150             b = struct.unpack('>%ss' % a, value[2:a+2])[0]
    151             c = struct.unpack('>h', value[a+2:a+4])[0]
    152             d = struct.unpack('>%ss' % c, value[a+4:][0])
    153             self.value = (a, b, c, d)
    154 
    155         # character string value tags
    156         elif self.value_tag == IPPTags.TEXT_WITHOUT_LANGUAGE or \
    157                  self.value_tag == IPPTags.NAME_WITHOUT_LANGUAGE:
    158             self.value = str(value)
    159         elif self.value_tag == IPPTags.GENERIC_CHAR_STRING or \
    160                  self.value_tag == IPPTags.KEYWORD or \
    161                  self.value_tag == IPPTags.URI or \
    162                  self.value_tag == IPPTags.URI_SCHEME or \
    163                  self.value_tag == IPPTags.CHARSET or \
    164                  self.value_tag == IPPTags.NATURAL_LANGUAGE or \
    165                  self.value_tag == IPPTags.MIME_MEDIA_TYPE:
    166             self.value = str(value)
    167 
    168     def valueToBinary(self):
    169 
    170         # out-of-band value tags
    171         if self.value_tag == IPPTags.UNSUPPORTED or \
    172                self.value_tag == IPPTags.DEFAULT or \
    173                self.value_tag == IPPTags.UNKNOWN or \
    174                self.value_tag == IPPTags.NO_VALUE:
    175             return (0, '')
    176 
    177         # integer value tags
    178         elif self.value_tag == IPPTags.GENERIC_INTEGER:
    179             pass
    180         elif self.value_tag == IPPTags.INTEGER:
    181             return (4, struct.pack('>i', self.value))
    182         elif self.value_tag == IPPTags.BOOLEAN:
    183             return (1, struct.pack('>?', self.value))
    184         elif self.value_tag == IPPTags.ENUM:
    185             return (4, struct.pack('>i', self.value))
    186 
    187         # octet string value tags
    188         elif self.value_tag == IPPTags.UNSPECIFIED_OCTETSTRING:
    189             pass
    190         elif self.value_tag == IPPTags.DATETIME:
    191             # field  octets  contents                  range
    192             # -----  ------  --------                  -----
    193             #   1      1-2   year                      0..65536
    194             #   2       3    month                     1..12
    195             #   3       4    day                       1..31
    196             #   4       5    hour                      0..23
    197             #   5       6    minutes                   0..59
    198             #   6       7    seconds                   0..60
    199             #                (use 60 for leap-second)
    200             #   7       8    deci-seconds              0..9
    201             #   8       9    direction from UTC        '+' / '-'
    202             #   9      10    hours from UTC            0..11
    203             #  10      11    minutes from UTC          0..59
    204            
    205             return (11, struct.pack('>hbbbbbbcbb', self.value))
    206            
    207         elif self.value_tag == IPPTags.RESOLUTION:
    208             # OCTET-STRING consisting of nine octets of 2
    209             # SIGNED-INTEGERs followed by a SIGNED-BYTE. The first
    210             # SIGNED-INTEGER contains the value of cross feed
    211             # direction resolution. The second SIGNED-INTEGER contains
    212             # the value of feed direction resolution. The SIGNED-BYTE
    213             # contains the units
    214            
    215             return (9, struct.pack('>iib', self.value))
    216            
    217         elif self.value_tag == IPPTags.RANGE_OF_INTEGER:
    218             # Eight octets consisting of 2 SIGNED-INTEGERs.  The first
    219             # SIGNED-INTEGER contains the lower bound and the second
    220             # SIGNED-INTEGER contains the upper bound.
    221            
    222             return (8, struct.pack('>ii', self.value))
    223 
    224         elif self.value_tag == IPPTags.TEXT_WITH_LANGUAGE or \
    225                  self.value_tag == IPPTags.NAME_WITH_LANGUAGE:
    226             a_bin = struct.pack('>h', self.value[0])
    227             b_bin = struct.pack('>%ss' % self.value[0], self.value[1])
    228             c_bin = struct.pack('>h', self.value[2])
    229             d_bin = struct.pack('>%ss' % self.value[2], self.value[3])
    230             return (4 + self.value[0] + self.value[2],
    231                     a_bin + b_bin + c_bin + d_bin)
    232 
    233         # character string value tags
    234         elif self.value_tag == IPPTags.TEXT_WITHOUT_LANGUAGE or \
    235                  self.value_tag == IPPTags.NAME_WITHOUT_LANGUAGE:
    236             return (len(self.value), struct.pack('>%ss' % len(self.value), self.value))
    237         elif self.value_tag == IPPTags.GENERIC_CHAR_STRING or \
    238                  self.value_tag == IPPTags.KEYWORD or \
    239                  self.value_tag == IPPTags.URI or \
    240                  self.value_tag == IPPTags.URI_SCHEME or \
    241                  self.value_tag == IPPTags.CHARSET or \
    242                  self.value_tag == IPPTags.NATURAL_LANGUAGE or \
    243                  self.value_tag == IPPTags.MIME_MEDIA_TYPE:
    244             return (len(self.value), struct.pack('>%ss' % len(self.value), self.value))
    245 
    246         return len(self.value), self.value
    247 
    248 class IPPAttribute():
    249     """
    250     In addition to what the RFC reports, an attribute has an
    251     'attribute tag', which specifies what type of attribute it is.
    252     It is 1 bytes long, and comes before the list of values.
    253 
    254     From RFC 2565:
    255 
    256     Each attribute consists of:
    257     -----------------------------------------------
    258     |                   value-tag                 |   1 byte
    259     -----------------------------------------------
    260     |               name-length  (value is u)     |   2 bytes
    261     -----------------------------------------------
    262     |                     name                    |   u bytes
    263     -----------------------------------------------
    264     |              value-length  (value is v)     |   2 bytes
    265     -----------------------------------------------
    266     |                     value                   |   v bytes
    267     -----------------------------------------------
    268 
    269     An additional value consists of:
    270     -----------------------------------------------------------
    271     |                   value-tag                 |   1 byte  |
    272     -----------------------------------------------           |
    273     |            name-length  (value is 0x0000)   |   2 bytes |
    274     -----------------------------------------------           |-0 or more
    275     |              value-length (value is w)      |   2 bytes |
    276     -----------------------------------------------           |
    277     |                     value                   |   w bytes |
    278     -----------------------------------------------------------
    279     """
    280 
    281     def __init__(self, name, values):
    282         """
    283         Initialize an IPPAttribute.
    284        
    285         Arguments:
    286 
    287             name -- the name of the attribute
    288 
    289             values -- a list of IPPValues.  May not be empty.
    290         """
    291 
    292         # make sure name isn't empty
    293         assert name is not None
    294          
    295         # make sure the list of values isn't empty
    296         assert len(values) > 0
    297         # make sure each value is an IPPValue
    298         for value in values: assert isinstance(value, IPPValue)
    299          
    300         self.name = name
    301         self.values = values
    302 
    303     def toBinaryData(self):
    304         """
    305         Packs the attribute data into binary data.
    306         """
    307 
    308         # get the binary data for all the values
    309         values = []
    310         for v, i in zip(self.values, xrange(len(self.values))):
    311 
    312             # get the name length (0 for everything but the first
    313             # value)
    314             if i == 0:
    315                 name_length = len(self.name)
    316             else:
    317                 name_length = 0
    318 
    319             # get the value length and binary value
    320             value_length, value_bin = v.valueToBinary()
    321 
    322             logger.debug("dumping name_length : %i" % name_length)
    323             logger.debug("dumping name : %s" % self.name)
    324             logger.debug("dumping value_length : %i" % value_length)
    325             logger.debug("dumping value : %s" % v.value)
    326 
    327             # the value tag in binary
    328             value_tag_bin = struct.pack('>b', v.value_tag)
    329 
    330             # the name length in binary
    331             name_length_bin = struct.pack('>h', name_length)
    332 
    333             # the name in binary
    334             name_bin = self.name
    335 
    336             # the value length in binary
    337             value_length_bin = struct.pack('>h', value_length)
    338 
    339             if i == 0:
    340                 values.append(''.join([value_tag_bin,
    341                                        name_length_bin,
    342                                        name_bin,
    343                                        value_length_bin,
    344                                        value_bin]))
    345             else:
    346                 values.append(''.join([value_tag_bin,
    347                                        name_length_bin,
    348                                        value_length_bin,
    349                                        value_bin]))
    350                
    351         # concatenate everything together and return it
    352         return ''.join(values)
    353 
    354 class IPPAttributeGroup():
    355     """
    356     An IPPAttributeGroup consists of an attribute-group-tag, followed
    357     by a sequence of IPPAttributes.
    358     """
    359 
    360     def __init__(self, attribute_group_tag, attributes=[]):
    361         """
    362         Initialize an IPPAttributeGroup.
    363 
    364         Arguments:
    365 
    366             attribute_group_tag -- a signed char, holds the tag of the
    367                                    attribute group
    368 
    369             attributes -- (optional) a list of attributes
    370         """
    371 
    372         # make sure attribute_group_tag isn't empty
    373         assert attribute_group_tag is not None
    374 
    375         # make sure attributes is a list or tuple of IPPAttributes
    376         assert isinstance(attributes, (list, tuple))
    377         for a in attributes: assert isinstance(a, IPPAttribute)
    378 
    379         self.attribute_group_tag = attribute_group_tag
    380         self.attributes = attributes
    381 
    382     def getAttribute(self, name):
    383         return filter(lambda x: x.name == name, self.attributes)
    384 
    385     def toBinaryData(self):
    386         """
    387         Convert the IPPAttributeGroup to binary.
    388         """
    389 
    390         # conver the attribute_group_tag to binary
    391         tag = struct.pack('>b', self.attribute_group_tag)
    392 
    393         # convert each of the attributes to binary
    394         attributes = [a.toBinaryData() for a in self.attributes]
    395 
    396         # concatenate everything and return
    397         return tag + ''.join(attributes)
    3987
    3998class IPPRequest():
Note: See TracChangeset for help on using the changeset viewer.