source: server/lib/ippvalue.py @ 8979f90

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

Put various IPP classes in their own files

  • Property mode set to 100644
File size: 8.6 KB
Line 
1#!/usr/bin/python
2
3import sys, struct, logging
4
5# initialize logger
6logger = logging.getLogger("ippLogger")
7
8class IPPValue():
9    """
10    An IPP value consists of a tag and a value, and optionally, a name.
11
12    From RFC 2565:
13     -----------------------------------------------
14     |                   value-tag                 |   1 byte
15     -----------------------------------------------
16     |               name-length  (value is u)     |   2 bytes
17     -----------------------------------------------
18     |                     name                    |   u bytes
19     -----------------------------------------------
20     |              value-length  (value is v)     |   2 bytes
21     -----------------------------------------------
22     |                     value                   |   v bytes
23     -----------------------------------------------   
24    """
25
26    def __init__(self, value_tag, value, unpack=True):
27        """
28        Initialize an IPPValue:
29
30        Arguments:
31
32            value_tag -- one byte, identifying the type of value
33
34            value -- variable size, containing the actual value
35        """
36
37        # make sure value_tag isn't empty
38        assert value_tag is not None
39        # make sure value isn't empty
40        assert value is not None
41
42        self.value_tag = value_tag
43        self.value = value
44
45        if not unpack: return
46
47        # out-of-band value tags
48        if self.value_tag == IPPTags.UNSUPPORTED or \
49               self.value_tag == IPPTags.DEFAULT or \
50               self.value_tag == IPPTags.UNKNOWN or \
51               self.value_tag == IPPTags.NO_VALUE:
52            self.value = ''
53
54        # integer value tags
55        elif self.value_tag == IPPTags.GENERIC_INTEGER:
56            pass # not supported
57        elif self.value_tag == IPPTags.INTEGER:
58            self.value = struct.unpack('>i', value)[0]
59        elif self.value_tag == IPPTags.BOOLEAN:
60            self.value = struct.unpack('>?', value)[0]
61        elif self.value_tag == IPPTags.ENUM:
62            self.value = struct.unpack('>i', value)[0]
63
64        # octet string value tags
65        elif self.value_tag == IPPTags.UNSPECIFIED_OCTETSTRING:
66            pass
67       
68        elif self.value_tag == IPPTags.DATETIME:
69            # field  octets  contents                  range
70            # -----  ------  --------                  -----
71            #   1      1-2   year                      0..65536
72            #   2       3    month                     1..12
73            #   3       4    day                       1..31
74            #   4       5    hour                      0..23
75            #   5       6    minutes                   0..59
76            #   6       7    seconds                   0..60
77            #                (use 60 for leap-second)
78            #   7       8    deci-seconds              0..9
79            #   8       9    direction from UTC        '+' / '-'
80            #   9      10    hours from UTC            0..11
81            #  10      11    minutes from UTC          0..59
82
83            self.value = struct.unpack('>hbbbbbbcbb', value)[0]
84           
85        elif self.value_tag == IPPTags.RESOLUTION:
86            # OCTET-STRING consisting of nine octets of 2
87            # SIGNED-INTEGERs followed by a SIGNED-BYTE. The first
88            # SIGNED-INTEGER contains the value of cross feed
89            # direction resolution. The second SIGNED-INTEGER contains
90            # the value of feed direction resolution. The SIGNED-BYTE
91            # contains the units
92
93            self.value = struct.unpack('>iib', value)
94           
95        elif self.value_tag == IPPTags.RANGE_OF_INTEGER:
96            # Eight octets consisting of 2 SIGNED-INTEGERs.  The first
97            # SIGNED-INTEGER contains the lower bound and the second
98            # SIGNED-INTEGER contains the upper bound.
99
100            self.value = struct.unpack('>ii', value)
101
102        elif self.value_tag == IPPTags.TEXT_WITH_LANGUAGE or \
103                 self.value_tag == IPPTags.NAME_WITH_LANGUAGE:
104            a = struct.unpack('>h', value[:2])[0]
105            b = struct.unpack('>%ss' % a, value[2:a+2])[0]
106            c = struct.unpack('>h', value[a+2:a+4])[0]
107            d = struct.unpack('>%ss' % c, value[a+4:][0])
108            self.value = (a, b, c, d)
109
110        # character string value tags
111        elif self.value_tag == IPPTags.TEXT_WITHOUT_LANGUAGE or \
112                 self.value_tag == IPPTags.NAME_WITHOUT_LANGUAGE:
113            self.value = str(value)
114        elif self.value_tag == IPPTags.GENERIC_CHAR_STRING or \
115                 self.value_tag == IPPTags.KEYWORD or \
116                 self.value_tag == IPPTags.URI or \
117                 self.value_tag == IPPTags.URI_SCHEME or \
118                 self.value_tag == IPPTags.CHARSET or \
119                 self.value_tag == IPPTags.NATURAL_LANGUAGE or \
120                 self.value_tag == IPPTags.MIME_MEDIA_TYPE:
121            self.value = str(value)
122
123    def valueToBinary(self):
124
125        # out-of-band value tags
126        if self.value_tag == IPPTags.UNSUPPORTED or \
127               self.value_tag == IPPTags.DEFAULT or \
128               self.value_tag == IPPTags.UNKNOWN or \
129               self.value_tag == IPPTags.NO_VALUE:
130            return (0, '')
131
132        # integer value tags
133        elif self.value_tag == IPPTags.GENERIC_INTEGER:
134            pass
135        elif self.value_tag == IPPTags.INTEGER:
136            return (4, struct.pack('>i', self.value))
137        elif self.value_tag == IPPTags.BOOLEAN:
138            return (1, struct.pack('>?', self.value))
139        elif self.value_tag == IPPTags.ENUM:
140            return (4, struct.pack('>i', self.value))
141
142        # octet string value tags
143        elif self.value_tag == IPPTags.UNSPECIFIED_OCTETSTRING:
144            pass
145        elif self.value_tag == IPPTags.DATETIME:
146            # field  octets  contents                  range
147            # -----  ------  --------                  -----
148            #   1      1-2   year                      0..65536
149            #   2       3    month                     1..12
150            #   3       4    day                       1..31
151            #   4       5    hour                      0..23
152            #   5       6    minutes                   0..59
153            #   6       7    seconds                   0..60
154            #                (use 60 for leap-second)
155            #   7       8    deci-seconds              0..9
156            #   8       9    direction from UTC        '+' / '-'
157            #   9      10    hours from UTC            0..11
158            #  10      11    minutes from UTC          0..59
159           
160            return (11, struct.pack('>hbbbbbbcbb', self.value))
161           
162        elif self.value_tag == IPPTags.RESOLUTION:
163            # OCTET-STRING consisting of nine octets of 2
164            # SIGNED-INTEGERs followed by a SIGNED-BYTE. The first
165            # SIGNED-INTEGER contains the value of cross feed
166            # direction resolution. The second SIGNED-INTEGER contains
167            # the value of feed direction resolution. The SIGNED-BYTE
168            # contains the units
169           
170            return (9, struct.pack('>iib', self.value))
171           
172        elif self.value_tag == IPPTags.RANGE_OF_INTEGER:
173            # Eight octets consisting of 2 SIGNED-INTEGERs.  The first
174            # SIGNED-INTEGER contains the lower bound and the second
175            # SIGNED-INTEGER contains the upper bound.
176           
177            return (8, struct.pack('>ii', self.value))
178
179        elif self.value_tag == IPPTags.TEXT_WITH_LANGUAGE or \
180                 self.value_tag == IPPTags.NAME_WITH_LANGUAGE:
181            a_bin = struct.pack('>h', self.value[0])
182            b_bin = struct.pack('>%ss' % self.value[0], self.value[1])
183            c_bin = struct.pack('>h', self.value[2])
184            d_bin = struct.pack('>%ss' % self.value[2], self.value[3])
185            return (4 + self.value[0] + self.value[2],
186                    a_bin + b_bin + c_bin + d_bin)
187
188        # character string value tags
189        elif self.value_tag == IPPTags.TEXT_WITHOUT_LANGUAGE or \
190                 self.value_tag == IPPTags.NAME_WITHOUT_LANGUAGE:
191            return (len(self.value), struct.pack('>%ss' % len(self.value), self.value))
192        elif self.value_tag == IPPTags.GENERIC_CHAR_STRING or \
193                 self.value_tag == IPPTags.KEYWORD or \
194                 self.value_tag == IPPTags.URI or \
195                 self.value_tag == IPPTags.URI_SCHEME or \
196                 self.value_tag == IPPTags.CHARSET or \
197                 self.value_tag == IPPTags.NATURAL_LANGUAGE or \
198                 self.value_tag == IPPTags.MIME_MEDIA_TYPE:
199            return (len(self.value), struct.pack('>%ss' % len(self.value), self.value))
200
201        return len(self.value), self.value
Note: See TracBrowser for help on using the repository browser.