Changeset 8979f90
- Timestamp:
- Mar 5, 2011, 10:27:55 PM (14 years ago)
- Branches:
- no-cups
- Children:
- 2646571
- Parents:
- e97c37d
- git-author:
- Jessica B. Hamrick <jhamrick@…> (03/05/11 22:27:55)
- git-committer:
- Jessica B. Hamrick <jhamrick@…> (03/05/11 22:27:55)
- Location:
- server/lib
- Files:
-
- 3 added
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
server/lib/ippconstants.py
re97c37d r8979f90 1 #!/usr/bin/python 2 1 3 class Misc(): 2 4 """ -
server/lib/ipprequest.py
rc5e88d0 r8979f90 5 5 # initialize logger 6 6 logger = logging.getLogger("ippLogger") 7 8 class IPPTags():9 """10 Contains constants for the various IPP tags, as defined by RFC11 2565.12 """13 14 # various tags15 ZERO_NAME_LENGTH = 0x0016 OPERATION_ATTRIBUTES_TAG = 0x0117 JOB_ATTRIBUTES_TAG = 0x0218 END_OF_ATTRIBUTES_TAG = 0x0319 PRINTER_ATTRIBUTES_TAG = 0x0420 UNSUPPORTED_ATTRIBUTES_TAG = 0x0521 22 # "out of band" value tags23 UNSUPPORTED = 0x1024 DEFAULT = 0x1125 UNKNOWN = 0x1226 NO_VALUE = 0x1327 28 # integer value tags29 GENERIC_INTEGER = 0x2030 INTEGER = 0x2131 BOOLEAN = 0x2232 ENUM = 0x2333 34 # octetstring value tags35 UNSPECIFIED_OCTETSTRING = 0x3036 DATETIME = 0x3137 RESOLUTION = 0x3238 RANGE_OF_INTEGER = 0x3339 TEXT_WITH_LANGUAGE = 0x3540 NAME_WITH_LANGUAGE = 0x3641 42 # character-string value tags43 GENERIC_CHAR_STRING = 0x4044 TEXT_WITHOUT_LANGUAGE = 0x4145 NAME_WITHOUT_LANGUAGE = 0x4246 KEYWORD = 0x4447 URI = 0x4548 URI_SCHEME = 0x4649 CHARSET = 0x4750 NATURAL_LANGUAGE = 0x4851 MIME_MEDIA_TYPE = 0x4952 53 class IPPValue():54 """55 An IPP value consists of a tag and a value, and optionally, a name.56 57 From RFC 2565:58 -----------------------------------------------59 | value-tag | 1 byte60 -----------------------------------------------61 | name-length (value is u) | 2 bytes62 -----------------------------------------------63 | name | u bytes64 -----------------------------------------------65 | value-length (value is v) | 2 bytes66 -----------------------------------------------67 | value | v bytes68 -----------------------------------------------69 """70 71 def __init__(self, value_tag, value, unpack=True):72 """73 Initialize an IPPValue:74 75 Arguments:76 77 value_tag -- one byte, identifying the type of value78 79 value -- variable size, containing the actual value80 """81 82 # make sure value_tag isn't empty83 assert value_tag is not None84 # make sure value isn't empty85 assert value is not None86 87 self.value_tag = value_tag88 self.value = value89 90 if not unpack: return91 92 # out-of-band value tags93 if self.value_tag == IPPTags.UNSUPPORTED or \94 self.value_tag == IPPTags.DEFAULT or \95 self.value_tag == IPPTags.UNKNOWN or \96 self.value_tag == IPPTags.NO_VALUE:97 self.value = ''98 99 # integer value tags100 elif self.value_tag == IPPTags.GENERIC_INTEGER:101 pass # not supported102 elif self.value_tag == IPPTags.INTEGER:103 self.value = struct.unpack('>i', value)[0]104 elif self.value_tag == IPPTags.BOOLEAN:105 self.value = struct.unpack('>?', value)[0]106 elif self.value_tag == IPPTags.ENUM:107 self.value = struct.unpack('>i', value)[0]108 109 # octet string value tags110 elif self.value_tag == IPPTags.UNSPECIFIED_OCTETSTRING:111 pass112 113 elif self.value_tag == IPPTags.DATETIME:114 # field octets contents range115 # ----- ------ -------- -----116 # 1 1-2 year 0..65536117 # 2 3 month 1..12118 # 3 4 day 1..31119 # 4 5 hour 0..23120 # 5 6 minutes 0..59121 # 6 7 seconds 0..60122 # (use 60 for leap-second)123 # 7 8 deci-seconds 0..9124 # 8 9 direction from UTC '+' / '-'125 # 9 10 hours from UTC 0..11126 # 10 11 minutes from UTC 0..59127 128 self.value = struct.unpack('>hbbbbbbcbb', value)[0]129 130 elif self.value_tag == IPPTags.RESOLUTION:131 # OCTET-STRING consisting of nine octets of 2132 # SIGNED-INTEGERs followed by a SIGNED-BYTE. The first133 # SIGNED-INTEGER contains the value of cross feed134 # direction resolution. The second SIGNED-INTEGER contains135 # the value of feed direction resolution. The SIGNED-BYTE136 # contains the units137 138 self.value = struct.unpack('>iib', value)139 140 elif self.value_tag == IPPTags.RANGE_OF_INTEGER:141 # Eight octets consisting of 2 SIGNED-INTEGERs. The first142 # SIGNED-INTEGER contains the lower bound and the second143 # SIGNED-INTEGER contains the upper bound.144 145 self.value = struct.unpack('>ii', value)146 147 elif self.value_tag == IPPTags.TEXT_WITH_LANGUAGE or \148 self.value_tag == IPPTags.NAME_WITH_LANGUAGE:149 a = struct.unpack('>h', value[:2])[0]150 b = struct.unpack('>%ss' % a, value[2:a+2])[0]151 c = struct.unpack('>h', value[a+2:a+4])[0]152 d = struct.unpack('>%ss' % c, value[a+4:][0])153 self.value = (a, b, c, d)154 155 # character string value tags156 elif self.value_tag == IPPTags.TEXT_WITHOUT_LANGUAGE or \157 self.value_tag == IPPTags.NAME_WITHOUT_LANGUAGE:158 self.value = str(value)159 elif self.value_tag == IPPTags.GENERIC_CHAR_STRING or \160 self.value_tag == IPPTags.KEYWORD or \161 self.value_tag == IPPTags.URI or \162 self.value_tag == IPPTags.URI_SCHEME or \163 self.value_tag == IPPTags.CHARSET or \164 self.value_tag == IPPTags.NATURAL_LANGUAGE or \165 self.value_tag == IPPTags.MIME_MEDIA_TYPE:166 self.value = str(value)167 168 def valueToBinary(self):169 170 # out-of-band value tags171 if self.value_tag == IPPTags.UNSUPPORTED or \172 self.value_tag == IPPTags.DEFAULT or \173 self.value_tag == IPPTags.UNKNOWN or \174 self.value_tag == IPPTags.NO_VALUE:175 return (0, '')176 177 # integer value tags178 elif self.value_tag == IPPTags.GENERIC_INTEGER:179 pass180 elif self.value_tag == IPPTags.INTEGER:181 return (4, struct.pack('>i', self.value))182 elif self.value_tag == IPPTags.BOOLEAN:183 return (1, struct.pack('>?', self.value))184 elif self.value_tag == IPPTags.ENUM:185 return (4, struct.pack('>i', self.value))186 187 # octet string value tags188 elif self.value_tag == IPPTags.UNSPECIFIED_OCTETSTRING:189 pass190 elif self.value_tag == IPPTags.DATETIME:191 # field octets contents range192 # ----- ------ -------- -----193 # 1 1-2 year 0..65536194 # 2 3 month 1..12195 # 3 4 day 1..31196 # 4 5 hour 0..23197 # 5 6 minutes 0..59198 # 6 7 seconds 0..60199 # (use 60 for leap-second)200 # 7 8 deci-seconds 0..9201 # 8 9 direction from UTC '+' / '-'202 # 9 10 hours from UTC 0..11203 # 10 11 minutes from UTC 0..59204 205 return (11, struct.pack('>hbbbbbbcbb', self.value))206 207 elif self.value_tag == IPPTags.RESOLUTION:208 # OCTET-STRING consisting of nine octets of 2209 # SIGNED-INTEGERs followed by a SIGNED-BYTE. The first210 # SIGNED-INTEGER contains the value of cross feed211 # direction resolution. The second SIGNED-INTEGER contains212 # the value of feed direction resolution. The SIGNED-BYTE213 # contains the units214 215 return (9, struct.pack('>iib', self.value))216 217 elif self.value_tag == IPPTags.RANGE_OF_INTEGER:218 # Eight octets consisting of 2 SIGNED-INTEGERs. The first219 # SIGNED-INTEGER contains the lower bound and the second220 # SIGNED-INTEGER contains the upper bound.221 222 return (8, struct.pack('>ii', self.value))223 224 elif self.value_tag == IPPTags.TEXT_WITH_LANGUAGE or \225 self.value_tag == IPPTags.NAME_WITH_LANGUAGE:226 a_bin = struct.pack('>h', self.value[0])227 b_bin = struct.pack('>%ss' % self.value[0], self.value[1])228 c_bin = struct.pack('>h', self.value[2])229 d_bin = struct.pack('>%ss' % self.value[2], self.value[3])230 return (4 + self.value[0] + self.value[2],231 a_bin + b_bin + c_bin + d_bin)232 233 # character string value tags234 elif self.value_tag == IPPTags.TEXT_WITHOUT_LANGUAGE or \235 self.value_tag == IPPTags.NAME_WITHOUT_LANGUAGE:236 return (len(self.value), struct.pack('>%ss' % len(self.value), self.value))237 elif self.value_tag == IPPTags.GENERIC_CHAR_STRING or \238 self.value_tag == IPPTags.KEYWORD or \239 self.value_tag == IPPTags.URI or \240 self.value_tag == IPPTags.URI_SCHEME or \241 self.value_tag == IPPTags.CHARSET or \242 self.value_tag == IPPTags.NATURAL_LANGUAGE or \243 self.value_tag == IPPTags.MIME_MEDIA_TYPE:244 return (len(self.value), struct.pack('>%ss' % len(self.value), self.value))245 246 return len(self.value), self.value247 248 class IPPAttribute():249 """250 In addition to what the RFC reports, an attribute has an251 'attribute tag', which specifies what type of attribute it is.252 It is 1 bytes long, and comes before the list of values.253 254 From RFC 2565:255 256 Each attribute consists of:257 -----------------------------------------------258 | value-tag | 1 byte259 -----------------------------------------------260 | name-length (value is u) | 2 bytes261 -----------------------------------------------262 | name | u bytes263 -----------------------------------------------264 | value-length (value is v) | 2 bytes265 -----------------------------------------------266 | value | v bytes267 -----------------------------------------------268 269 An additional value consists of:270 -----------------------------------------------------------271 | value-tag | 1 byte |272 ----------------------------------------------- |273 | name-length (value is 0x0000) | 2 bytes |274 ----------------------------------------------- |-0 or more275 | value-length (value is w) | 2 bytes |276 ----------------------------------------------- |277 | value | w bytes |278 -----------------------------------------------------------279 """280 281 def __init__(self, name, values):282 """283 Initialize an IPPAttribute.284 285 Arguments:286 287 name -- the name of the attribute288 289 values -- a list of IPPValues. May not be empty.290 """291 292 # make sure name isn't empty293 assert name is not None294 295 # make sure the list of values isn't empty296 assert len(values) > 0297 # make sure each value is an IPPValue298 for value in values: assert isinstance(value, IPPValue)299 300 self.name = name301 self.values = values302 303 def toBinaryData(self):304 """305 Packs the attribute data into binary data.306 """307 308 # get the binary data for all the values309 values = []310 for v, i in zip(self.values, xrange(len(self.values))):311 312 # get the name length (0 for everything but the first313 # value)314 if i == 0:315 name_length = len(self.name)316 else:317 name_length = 0318 319 # get the value length and binary value320 value_length, value_bin = v.valueToBinary()321 322 logger.debug("dumping name_length : %i" % name_length)323 logger.debug("dumping name : %s" % self.name)324 logger.debug("dumping value_length : %i" % value_length)325 logger.debug("dumping value : %s" % v.value)326 327 # the value tag in binary328 value_tag_bin = struct.pack('>b', v.value_tag)329 330 # the name length in binary331 name_length_bin = struct.pack('>h', name_length)332 333 # the name in binary334 name_bin = self.name335 336 # the value length in binary337 value_length_bin = struct.pack('>h', value_length)338 339 if i == 0:340 values.append(''.join([value_tag_bin,341 name_length_bin,342 name_bin,343 value_length_bin,344 value_bin]))345 else:346 values.append(''.join([value_tag_bin,347 name_length_bin,348 value_length_bin,349 value_bin]))350 351 # concatenate everything together and return it352 return ''.join(values)353 354 class IPPAttributeGroup():355 """356 An IPPAttributeGroup consists of an attribute-group-tag, followed357 by a sequence of IPPAttributes.358 """359 360 def __init__(self, attribute_group_tag, attributes=[]):361 """362 Initialize an IPPAttributeGroup.363 364 Arguments:365 366 attribute_group_tag -- a signed char, holds the tag of the367 attribute group368 369 attributes -- (optional) a list of attributes370 """371 372 # make sure attribute_group_tag isn't empty373 assert attribute_group_tag is not None374 375 # make sure attributes is a list or tuple of IPPAttributes376 assert isinstance(attributes, (list, tuple))377 for a in attributes: assert isinstance(a, IPPAttribute)378 379 self.attribute_group_tag = attribute_group_tag380 self.attributes = attributes381 382 def getAttribute(self, name):383 return filter(lambda x: x.name == name, self.attributes)384 385 def toBinaryData(self):386 """387 Convert the IPPAttributeGroup to binary.388 """389 390 # conver the attribute_group_tag to binary391 tag = struct.pack('>b', self.attribute_group_tag)392 393 # convert each of the attributes to binary394 attributes = [a.toBinaryData() for a in self.attributes]395 396 # concatenate everything and return397 return tag + ''.join(attributes)398 7 399 8 class IPPRequest():
Note: See TracChangeset
for help on using the changeset viewer.