source: server/lib/ippattribute.py @ c269bc7

no-cups
Last change on this file since c269bc7 was c269bc7, checked in by Jessica B. Hamrick <jhamrick@…>, 13 years ago

Update API for Value, Attribute, and AttributeGroup?

  • Property mode set to 100644
File size: 6.9 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():
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 must be of type Value"
67
68        self.name = None
69        self.values = None
70
71        if name is not None:
72            self.name = name
73        if name is not None and len(values) > 0:
74            self.values = values
75            self.binary = self.pack()
76            self.verify()
77
78    def pack(self):
79        """
80        Packs the attribute data into binary data.
81        """
82
83        assert self.name is not None, \
84               "cannot pack unnamed attribute!"
85        assert len(self.values) > 0, \
86               "cannot pack empty attribute!"
87
88        # get the binary data for all the values
89        values = []
90        length = 0
91        for v, i in zip(self.values, xrange(len(self.values))):
92
93            # get the name length (0 for everything but the first
94            # value)
95            if i == 0:
96                name_length = len(self.name)
97            else:
98                name_length = 0
99
100            # get the value length and binary value
101            value_length, value_bin = v.pack()
102
103            logger.debug("dumping name_length : %i" % name_length)
104            logger.debug("dumping name : %s" % self.name)
105            logger.debug("dumping value_length : %i" % value_length)
106            logger.debug("dumping value : %s" % v.getValue())
107
108            # the value tag in binary
109            value_tag_bin = struct.pack('>b', v.getValueTag())
110
111            # the name length in binary
112            name_length_bin = struct.pack('>h', name_length)
113
114            # the name in binary
115            name_bin = self.name
116
117            # the value length in binary
118            value_length_bin = struct.pack('>h', value_length)
119
120            if i == 0:
121                values.append(''.join([value_tag_bin,
122                                       name_length_bin,
123                                       name_bin,
124                                       value_length_bin,
125                                       value_bin]))
126            else:
127                values.append(''.join([value_tag_bin,
128                                       name_length_bin,
129                                       value_length_bin,
130                                       value_bin]))
131
132            length += 2            # name-length
133            length += name_length  # name
134            length += value_length # value
135               
136        # concatenate everything together and return it along with the
137        # total length of the attribute
138        return length, ''.join(values)
139
140    def getName(self):
141        """
142        Get the attribute's name.
143        """
144       
145        return self.name
146
147    def getValues(self):
148        """
149        Get the list of values contained in the attribute.
150        """
151       
152        return self.values
153
154    def setName(self, name):
155        """
156        Set the attribute's name.
157        """
158
159        assert isinstance(name, str), \
160               "name must be a string!"
161       
162        self.name = name
163
164    def setValues(self, values):
165        """
166        Set the list of values contained in the attribute.
167        """
168
169        for v in values:
170            assert isinstance(v, Value), \
171                   "value must be of type Value!"
172       
173        self.values = values
174
175    def addValue(self, value):
176        """
177        Add a new value to the list of values contained in the
178        attribute."
179
180        assert isinstance(value, Value), \
181               "value must be of type Value!"
182
183        self.values.append(value)
184
185    def getSize(self):
186        """
187        Gets the total size of the attribute.
188        """
189
190        size = 2 + len(self.name)
191        for v in self.values:
192            size += v.getTotalSize()
193
194    def verify(self):
195        """
196        Check to make sure that the Attribute is valid.  This means
197        that is should have a name and a list of values, and that its
198        binary representation should match up to the stored binary
199        representation.
200        """
201       
202        assert self.name is not None, \
203               "attribute has no name!"
204        assert len(self.value) > 0, \
205               "attribute has no values!"
206
207        size, bindata = self.pack()
208
209        assert size == self.getSize(), \
210               "pack size does not match self.getSize()!"
211        assert bindata == self.binary_data, \
212               "packed binary data does not match self.binary_data!"
213
214    def __str__(self):
215        if len(self.values) > 0:
216            values = [str(v) for v in self.values]
217        else:
218            values = "None"
219
220        if self.name is None:
221            name = "None"
222        else:
223            name = self.name
224       
225        return "%s: %s" % (name, str(values))
Note: See TracBrowser for help on using the repository browser.