source: server/lib/ippattribute.py @ 569c377

no-cups
Last change on this file since 569c377 was 569c377, checked in by Quentin Smith <quentin@…>, 13 years ago

Err, make it work

  • Property mode set to 100644
File size: 5.1 KB
Line 
1#!/usr/bin/python
2
3import sys, struct, logging
4from ippvalue import Value
5
6# initialize logger
7logger = logging.getLogger("ippLogger")
8
9class Attribute(object):
10    """
11    In addition to what the RFC reports, an attribute has an
12    'attribute tag', which specifies what type of attribute it is.
13    It is 1 bytes long, and comes before the list of values.
14
15    From RFC 2565:
16
17    Each attribute consists of:
18    -----------------------------------------------
19    |                   value-tag                 |   1 byte
20    -----------------------------------------------
21    |               name-length  (value is u)     |   2 bytes
22    -----------------------------------------------
23    |                     name                    |   u bytes
24    -----------------------------------------------
25    |              value-length  (value is v)     |   2 bytes
26    -----------------------------------------------
27    |                     value                   |   v bytes
28    -----------------------------------------------
29
30    An additional value consists of:
31    -----------------------------------------------------------
32    |                   value-tag                 |   1 byte  |
33    -----------------------------------------------           |
34    |            name-length  (value is 0x0000)   |   2 bytes |
35    -----------------------------------------------           |-0 or more
36    |              value-length (value is w)      |   2 bytes |
37    -----------------------------------------------           |
38    |                     value                   |   w bytes |
39    -----------------------------------------------------------
40    """
41
42    def __init__(self, name=None, values=[]):
43        """
44        Initialize an Attribute.  This function can be called in three
45        different ways:
46
47            Attribute() -- creates an empty Attribute
48
49            Attribute(name) -- creates an empty Attribute with a name
50
51            Attribute(name, values) -- creates an Attribute
52            initialized with a name and list of values
53       
54        Arguments:
55
56            name -- the name of the attribute
57
58            values -- a list of Values.  May not be empty.
59        """
60
61        if name is not None:
62            assert isinstance(name, str), \
63                   "Attribute name must be a string!"
64        for value in values:
65            assert isinstance(value, Value), \
66                   "Value %r must be of type Value" % (value)
67
68        self.name = name
69        self.values = values
70
71    @property
72    def packed_value(self):
73        """
74        Packs the attribute data into binary data.
75        """
76
77        assert self.name is not None, \
78               "cannot pack unnamed attribute!"
79        assert len(self.values) > 0, \
80               "cannot pack empty attribute!"
81
82        # get the binary data for all the values
83        values = []
84        for v, i in zip(self.values, xrange(len(self.values))):
85
86            # get the name length (0 for everything but the first
87            # value)
88            if i == 0:
89                name_length = len(self.name)
90            else:
91                name_length = 0
92
93            # get the value length and binary value
94            value_bin = v.packed_value
95            value_length = len(value_bin)
96
97            logger.debug("dumping name_length : %i" % name_length)
98            logger.debug("dumping name : %s" % self.name)
99            logger.debug("dumping value_length : %i" % value_length)
100            logger.debug("dumping value : %s" % v.value)
101
102            # the value tag in binary
103            value_tag_bin = struct.pack('>b', v.value_tag)
104
105            # the name length in binary
106            name_length_bin = struct.pack('>h', name_length)
107
108            # the name in binary
109            name_bin = self.name
110
111            # the value length in binary
112            value_length_bin = struct.pack('>h', value_length)
113
114            if i == 0:
115                values.append(''.join([value_tag_bin,
116                                       name_length_bin,
117                                       name_bin,
118                                       value_length_bin,
119                                       value_bin]))
120            else:
121                values.append(''.join([value_tag_bin,
122                                       name_length_bin,
123                                       value_length_bin,
124                                       value_bin]))
125
126        # concatenate everything together and return it along with the
127        # total length of the attribute
128        return ''.join(values)
129
130    @property
131    def packed_value_size(self):
132        """
133        Gets the total size of the attribute.
134        """
135        return len(self.packed_value)
136
137    total_size = packed_value_size
138
139    def __str__(self):
140        if len(self.values) > 0:
141            values = [str(v) for v in self.values]
142        else:
143            values = "None"
144
145        if self.name is None:
146            name = "None"
147        else:
148            name = self.name
149       
150        return "%s: %s" % (name, str(values))
151
152    def __repr__(self):
153        return '<IPPAttribute (%r, %r)>' % (self.name, self.values)
Note: See TracBrowser for help on using the repository browser.