Changeset 84e8137


Ignore:
Timestamp:
Nov 6, 2010, 3:24:25 PM (13 years ago)
Author:
Jessica B. Hamrick <jhamrick@…>
Branches:
no-cups
Children:
4ec7caa
Parents:
c216863
git-author:
Jessica B. Hamrick <jhamrick@…> (11/06/10 15:24:25)
git-committer:
Jessica B. Hamrick <jhamrick@…> (11/06/10 15:24:25)
Message:

Add comments and docstrings to ipprequest.py

File:
1 edited

Legend:

Unmodified
Added
Removed
  • server/lib/ipprequest.py

    rc216863 r84e8137  
    11#!/usr/bin/python
    22
     3import sys
     4
     5# various tags
     6zero_name_length                  = 0x00
     7operation_attributes_tag          = 0x01
     8job_attributes_tag                = 0x02
     9end_of_attributes_tag             = 0x03
     10printer_attributes_tag            = 0x04
     11unsupported_attributes_tag        = 0x05
     12
     13# "out of band" value tags
     14oob_unsupported_value_tag         = 0x10
     15oob_default_value_tag             = 0x11
     16oob_unknown_value_tag             = 0x12
     17oob_no_value_tag                  = 0x13
     18
     19# integer value tags
     20generic_integer_value_tag         = 0x20
     21integer_value_tag                 = 0x21
     22boolean_value_tag                 = 0x22
     23enum_value_tag                    = 0x23
     24                 
     25# octetString value tags
     26unspecified_octetString_value_tag = 0x30
     27dateTime_value_tag                = 0x31
     28resolution_value_tag              = 0x32
     29rangeOfInteger_value_tag          = 0x33
     30collection_value_tag              = 0x34
     31textWithLanguage_value_tag        = 0x35
     32nameWithLanguage_value_tag        = 0x36
     33
     34# character-string value tags
     35generic_char_string_value_tag     = 0x40
     36textWithoutLanguage_value_tag     = 0x41
     37nameWithoutLanguage_value_tag     = 0x42
     38keyword_value_tag                 = 0x44
     39uri_value_tag                     = 0x45
     40uriScheme_value_tag               = 0x46
     41charset_value_tag                 = 0x47
     42naturalLanguage_value_tag         = 0x48
     43mimeMediaType_value_tag           = 0x49                                   
     44
    345class IPPValue():
     46    """
     47    An IPP value consists of a tag and a value, and optionally, a name.
     48    """
     49
    450    def __init__(self, value_tag, name, value):
    5         assert value_tag is not None and \
    6                value is not None
     51        """
     52        Initialize an IPPValue:
     53
     54        Arguments:
     55
     56            value_tag -- one byte, identifying the type of value
     57
     58            name -- (optional) variable size, identifying the name of
     59                    this value
     60
     61            value -- variable size, containing the actual value
     62        """
     63
     64        # make sure value_tag isn't empty
     65        assert value_tag is not None
     66        # make sure the size of value_tag is one byte
     67        assert sys.getsizeof(value_tag) == 1
     68        # make sure value isn't empty
     69        assert value is not None
    770
    871        self.value_tag = value_tag
     
    1174
    1275class IPPAttribute():
    13     # From RFC 2565:
    14 
    15     # Each attribute consists of:
    16     # -----------------------------------------------
    17     # |                   value-tag                 |   1 byte
    18     # -----------------------------------------------
    19     # |               name-length  (value is u)     |   2 bytes
    20     # -----------------------------------------------
    21     # |                     name                    |   u bytes
    22     # -----------------------------------------------
    23     # |              value-length  (value is v)     |   2 bytes
    24     # -----------------------------------------------
    25     # |                     value                   |   v bytes
    26     # -----------------------------------------------
    27 
    28     # An additional value consists of:
    29     # -----------------------------------------------------------
    30     # |                   value-tag                 |   1 byte  |
    31     # -----------------------------------------------           |
    32     # |            name-length  (value is 0x0000)   |   2 bytes |
    33     # -----------------------------------------------           |-0 or more
    34     # |              value-length (value is w)      |   2 bytes |
    35     # -----------------------------------------------           |
    36     # |                     value                   |   w bytes |
    37     # -----------------------------------------------------------
    38 
    39     def __init__(self, attribute_tag, values):
    40         assert attribute_tag is not None
    41         for value in values: assert isinstance(value, IPPValue)
     76     """
     77     From RFC 2565:
     78
     79     Each attribute consists of:
     80     -----------------------------------------------
     81     |                   value-tag                 |   1 byte
     82     -----------------------------------------------
     83     |               name-length  (value is u)     |   2 bytes
     84     -----------------------------------------------
     85     |                     name                    |   u bytes
     86     -----------------------------------------------
     87     |              value-length  (value is v)     |   2 bytes
     88     -----------------------------------------------
     89     |                     value                   |   v bytes
     90     -----------------------------------------------
     91
     92     An additional value consists of:
     93     -----------------------------------------------------------
     94     |                   value-tag                 |   1 byte  |
     95     -----------------------------------------------           |
     96     |            name-length  (value is 0x0000)   |   2 bytes |
     97     -----------------------------------------------           |-0 or more
     98     |              value-length (value is w)      |   2 bytes |
     99     -----------------------------------------------           |
     100     |                     value                   |   w bytes |
     101     -----------------------------------------------------------
     102     """
     103
     104     def __init__(self, attribute_tag, values):
     105         """
     106         Initialize an IPPAttribute.
     107
     108         Arguments:
     109
     110             attribute_tag -- one byte, identifying the type of attribute
     111
     112             values -- a list of IPPValues.  May not be empty.
     113         """
     114
     115         # make sure attribute_tag isn't empty
     116         assert attribute_tag is not None
     117         # make sure attribute_tag is of the right size
     118         assert sys.getsizeof(attribute_tag) == 1
     119         
     120         # make sure the list of values isn't empty
     121         assert len(values) > 0
     122         # make sure each value is an IPPValue
     123         for value in values: assert isinstance(value, IPPValue)
    42124       
    43         self.attribute_tag = attribute_tag
    44         self.values = values
     125         self.attribute_tag = attribute_tag
     126         self.values = values
    45127
    46128class IPPRequest():
    47     # From RFC 2565:
     129    """
     130    From RFC 2565:
    48131   
    49     # The encoding for an operation request or response consists of:
    50     # -----------------------------------------------
    51     # |                  version-number             |   2 bytes  - required
    52     # -----------------------------------------------
    53     # |               operation-id (request)        |
    54     # |                      or                     |   2 bytes  - required
    55     # |               status-code (response)        |
    56     # -----------------------------------------------
    57     # |                   request-id                |   4 bytes  - required
    58     # -----------------------------------------------------------
    59     # |               xxx-attributes-tag            |   1 byte  |
    60     # -----------------------------------------------           |-0 or more
    61     # |             xxx-attribute-sequence          |   n bytes |
    62     # -----------------------------------------------------------
    63     # |              end-of-attributes-tag          |   1 byte   - required
    64     # -----------------------------------------------
    65     # |                     data                    |   q bytes  - optional
    66     # -----------------------------------------------
     132    The encoding for an operation request or response consists of:
     133    -----------------------------------------------
     134    |                  version-number             |   2 bytes  - required
     135    -----------------------------------------------
     136    |               operation-id (request)        |
     137    |                      or                     |   2 bytes  - required
     138    |               status-code (response)        |
     139    -----------------------------------------------
     140    |                   request-id                |   4 bytes  - required
     141    -----------------------------------------------------------
     142    |               xxx-attributes-tag            |   1 byte  |
     143    -----------------------------------------------           |-0 or more
     144    |             xxx-attribute-sequence          |   n bytes |
     145    -----------------------------------------------------------
     146    |              end-of-attributes-tag          |   1 byte   - required
     147    -----------------------------------------------
     148    |                     data                    |   q bytes  - optional
     149    -----------------------------------------------
     150    """
    67151
    68152    # either give the version, operation_id, request_id,
     
    70154    # can be read from to get the request
    71155    def __init__(self, version=None, operation_id=None, request_id=None, attributes=[], data=None, request=None):
    72         assert (version is not None and \
    73                 operation_id is not None and \
    74                 request_id is not None) or request is not None
    75 
     156        """
     157        Create an IPPRequest.  Takes either the segments of the
     158        request separately, or a file handle for the request to parse.
     159        If the file handle is passed in, all other arguments are
     160        ignored.
     161
     162        Keyword arguments for passing in the segments of the request:
     163       
     164            version -- two bytes, identifying the version number of
     165                       the request
     166                           
     167            operation_id -- two bytes, identifying the id of the
     168                            requested operation
     169
     170            request_id -- four bytes, identifying the id of the
     171                          request itself.
     172
     173            attributes -- a list of IPPAttributes.  May be empty.
     174
     175            data -- (optional) variable length, containing the actual
     176                    data of the request
     177
     178        Keyword arguments for passing in the raw request:
     179
     180            request -- a file handle that supports the read()
     181                       operation
     182        """
     183
     184        if request is None:
     185            # make sure the version number isn't empty
     186            assert version is not None
     187            # make sure the version number is two bytes long
     188            assert sys.getsizeof(version) == 2
     189            # make sure the operation id isn't empty
     190            assert operation_id is not None
     191            # make sure the operation id is two bytes long
     192            assert sys.getsizeof(operation_id) == 2
     193            # make sure the request id isn't empty
     194            assert request_id is not None
     195            # make sure the request id is four bytes long
     196            assert sys.getsizeof(request_id) == 4
     197           
     198        # if the request isn't None, then we'll read directly from
     199        # that file handle
    76200        if request is not None:
     201            # read the version-number (two bytes)
    77202            self.version        = request.read(2)
     203
     204            # read the operation-id (or status-code, but that's only
     205            # for a response) (two bytes)
    78206            self.operation_id   = request.read(2)
     207
     208            # read the request-id (4 bytes)
    79209            self.request_id     = request.read(4)
     210
     211            # now we have to read in the attributes.  Each attribute
     212            # has a tag (1 byte) and a sequence of values (n bytes)
    80213            self.attributes     = []
    81            
     214
     215            # read in the next byte
    82216            next_byte = request.read(1)
    83             while next_byte != 0x03:
     217
     218            # as long as the next byte isn't signaling the end of the
     219            # attributes, keep looping and parsing attributes
     220            while next_byte != end_of_attributes_tag:
     221               
     222                # if the next byte is an attribute tag, then we're at
     223                # the start of a new attribute
    84224                if next_byte <= 0x0F:
     225
    85226                    attribute_tag = next_byte
     227                    # read in the value tag (one byte)
    86228                    value_tag     = request.read(1)
     229                    # read in the length of the name (two bytes)
    87230                    name_length   = request.read(2)
     231                    # read the name (name_length bytes)
    88232                    name          = request.read(name_length)
     233                    # read in the length of the value (two bytes)
    89234                    value_length  = request.read(2)
     235                    # read in the value (value_length bytes)
    90236                    value         = request.read(value_length)
    91                    
     237
     238                    # create a new IPPAttribute from the data we just
     239                    # read in, and add it to our attributes list
    92240                    self.attributes.append(IPPAttribute(
    93241                        attribute_tag,
    94242                        [IPPValue(value_tag, name, value)]))
     243
     244                # otherwise, we're still in the process of reading the
     245                # current attribute (now we'll read in another value)
    95246                else:
     247                   
    96248                    value_tag     = next_byte
     249                    # read in the length of the name (two bytes) --
     250                    # this should be 0x0
    97251                    name_length   = request.read(2)
     252                    assert name_length == zero_name_length
     253                    # name should be empty
    98254                    name          = None
     255                    # read in the length of the value (two bytes)
    99256                    value_length  = request.read(2)
     257                    # read in the value (value_length bytes)
    100258                    value         = request.read(value_length)
    101                    
     259
     260                    # add another value to the last attribute
    102261                    self.attributes[-1].values.append(IPPValue(value_tag, name, value))
    103                    
     262
     263                # read another byte
    104264                next_byte = request.read(1)
    105265
     266            # once we hit the end-of-attributes tag, the only thing
     267            # left is the data, so go ahead and read all of it
    106268            self.data = request.read()
    107269
     270        # otherwise, just set the class variables to the keyword
     271        # arguments passed in
    108272        else:
    109273            self.version = version
Note: See TracChangeset for help on using the changeset viewer.