source: server/lib/ippvalue.py @ ebf327d

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

Change IPPValue, IPPAttribute, IPPAttributeGroup, and IPPRequest to Value, Attribute, AttributeGroup?, and Request, respectively, to make things a little less verbose

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