Changeset 8403f61
- Timestamp:
- Nov 6, 2010, 6:59:32 PM (14 years ago)
- Branches:
- no-cups
- Children:
- 478ca74
- Parents:
- d56a0bc
- git-author:
- Jessica B. Hamrick <jhamrick@…> (11/06/10 18:59:32)
- git-committer:
- Jessica B. Hamrick <jhamrick@…> (11/06/10 18:59:32)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
server/lib/ipprequest.py
rd56a0bc r8403f61 1 1 #!/usr/bin/python 2 2 3 import sys, struct 3 import sys, struct, logging 4 5 # initialize logger 6 logger = logging.getLogger("ippLogger") 4 7 5 8 class IPPTags(): … … 33 36 DATETIME = 0x31 34 37 RESOLUTION = 0x32 35 RANGE OFINTEGER= 0x3338 RANGE_OF_INTEGER = 0x33 36 39 COLLECTION = 0x34 37 TEXT WITHLANGUAGE= 0x3538 NAME WITHLANGUAGE= 0x3640 TEXT_WITH_LANGUAGE = 0x35 41 NAME_WITH_LANGUAGE = 0x36 39 42 40 43 # character-string value tags 41 44 GENERIC_CHAR_STRING = 0x40 42 TEXT WITHOUTLANGUAGE= 0x4143 NAME WITHOUTLANGUAGE= 0x4245 TEXT_WITHOUT_LANGUAGE = 0x41 46 NAME_WITHOUT_LANGUAGE = 0x42 44 47 KEYWORD = 0x44 45 48 URI = 0x45 46 URI SCHEME= 0x4649 URI_SCHEME = 0x46 47 50 CHARSET = 0x47 48 NATURAL LANGUAGE= 0x4849 MIME MEDIATYPE= 0x4951 NATURAL_LANGUAGE = 0x48 52 MIME_MEDIA_TYPE = 0x49 50 53 51 54 class IPPValue(): … … 67 70 """ 68 71 69 def __init__(self, value_tag, name,value):72 def __init__(self, value_tag, value): 70 73 """ 71 74 Initialize an IPPValue: … … 74 77 75 78 value_tag -- one byte, identifying the type of value 76 77 name -- (optional) variable size, identifying the name of78 this value79 79 80 80 value -- variable size, containing the actual value … … 83 83 # make sure value_tag isn't empty 84 84 assert value_tag is not None 85 # make sure the size of value_tag is one byte86 assert sys.getsizeof(value_tag) == 187 85 # make sure value isn't empty 88 86 assert value is not None 89 87 90 88 self.value_tag = hex(value_tag) 89 self.value = str(value) 90 91 class IPPAttribute(): 92 """ 93 In addition to what the RFC reports, an attribute has an 94 'attribute tag', which specifies what type of attribute it is. 95 It is 1 bytes long, and comes before the list of values. 96 97 From RFC 2565: 98 99 Each attribute consists of: 100 ----------------------------------------------- 101 | value-tag | 1 byte 102 ----------------------------------------------- 103 | name-length (value is u) | 2 bytes 104 ----------------------------------------------- 105 | name | u bytes 106 ----------------------------------------------- 107 | value-length (value is v) | 2 bytes 108 ----------------------------------------------- 109 | value | v bytes 110 ----------------------------------------------- 111 112 An additional value consists of: 113 ----------------------------------------------------------- 114 | value-tag | 1 byte | 115 ----------------------------------------------- | 116 | name-length (value is 0x0000) | 2 bytes | 117 ----------------------------------------------- |-0 or more 118 | value-length (value is w) | 2 bytes | 119 ----------------------------------------------- | 120 | value | w bytes | 121 ----------------------------------------------------------- 122 """ 123 124 def __init__(self, name, values): 125 """ 126 Initialize an IPPAttribute. 127 128 Arguments: 129 130 name -- the name of the attribute 131 132 values -- a list of IPPValues. May not be empty. 133 """ 134 135 # make sure name isn't empty 136 assert name is not None 137 138 # make sure the list of values isn't empty 139 assert len(values) > 0 140 # make sure each value is an IPPValue 141 for value in values: assert isinstance(value, IPPValue) 142 91 143 self.name = str(name) 92 self.value = str(value)144 self.values = values 93 145 94 146 def toBinaryData(self): 95 147 """ 96 Packs the value data into binary data.97 """98 99 # get the length in bytes of the name100 name_length = sys.getsizeof(name)101 # get the length in bytes of the value102 value_length = sys.getsizeof(value)103 104 # if the name is of length zero, then don't include it in the105 # binary data106 if name_length == IPPTags.ZERO_NAME_LENGTH:107 binary = struct.pack('>bhhs',108 self.value_tag,109 name_length,110 value_length,111 self.value)112 else:113 binary = struct.pack('>bhshs',114 self.value_tag,115 name_length,116 self.name,117 value_length,118 self.value)119 120 return binary121 122 class IPPAttribute():123 """124 In addition to what the RFC reports, an attribute has an125 'attribute tag', which specifies what type of attribute it is.126 It is 1 bytes long, and comes before the list of values.127 128 From RFC 2565:129 130 Each attribute consists of:131 -----------------------------------------------132 | value-tag | 1 byte133 -----------------------------------------------134 | name-length (value is u) | 2 bytes135 -----------------------------------------------136 | name | u bytes137 -----------------------------------------------138 | value-length (value is v) | 2 bytes139 -----------------------------------------------140 | value | v bytes141 -----------------------------------------------142 143 An additional value consists of:144 -----------------------------------------------------------145 | value-tag | 1 byte |146 ----------------------------------------------- |147 | name-length (value is 0x0000) | 2 bytes |148 ----------------------------------------------- |-0 or more149 | value-length (value is w) | 2 bytes |150 ----------------------------------------------- |151 | value | w bytes |152 -----------------------------------------------------------153 """154 155 def __init__(self, attribute_tag, values):156 """157 Initialize an IPPAttribute.158 159 Arguments:160 161 attribute_tag -- one byte, identifying the type of attribute162 163 values -- a list of IPPValues. May not be empty.164 """165 166 # make sure attribute_tag isn't empty167 assert attribute_tag is not None168 # make sure attribute_tag is of the right size169 assert sys.getsizeof(attribute_tag) == 1170 171 # make sure the list of values isn't empty172 assert len(values) > 0173 # make sure each value is an IPPValue174 for value in values: assert isinstance(value, IPPValue)175 176 self.attribute_tag = hex(attribute_tag)177 self.values = values178 179 def toBinaryData(self):180 """181 148 Packs the attribute data into binary data. 182 149 """ 183 150 184 # pack the attribute tag185 attribute_tag = struct.pack('>b', self.attribute_tag)186 151 # get the binary data for all the values 187 values = [v.toBinaryData() for v in self.values] 188 152 values = [] 153 for v, i in zip(self.values, xrange(len(self.values))): 154 if i == 0: 155 name_length = sys.getsizeof(self.name) 156 value_length = sys.getsizeof(v.value) 157 values.append(struct.pack('>bh%ssh%ss' % (name_length, value_length), 158 v.value_tag, 159 name_length, 160 self.name, 161 value_length, 162 v.value)) 163 else: 164 value_length = sys.getsizeof(v.value) 165 values.append(struct.pack('>bhh%ss' % (value_length), 166 v.value_tag, 167 name_length, 168 value_length, 169 v.value)) 170 189 171 # concatenate everything together and return it 190 return attribute_tag +''.join(values)172 return ''.join(values) 191 173 192 174 class IPPRequest(): … … 253 235 assert isinstance(version, tuple) 254 236 assert len(version) == 2 255 # make sure the major version number is one byte long256 assert sys.getsizeof(version[0]) == 1257 # make sure the minor version number is one byte long258 assert sys.getsizeof(version[1]) == 1259 237 # make sure the operation id isn't empty 260 238 assert operation_id is not None 261 # make sure the operation id is two bytes long262 assert sys.getsizeof(operation_id) == 2263 239 # make sure the request id isn't empty 264 240 assert request_id is not None 265 # make sure the request id is four bytes long266 assert sys.getsizeof(request_id) == 4267 241 268 242 # if the request isn't None, then we'll read directly from … … 271 245 # read the version-number (two signed chars) 272 246 self.version = struct.unpack('>bb', request.read(2)) 247 logger.debug("version-number : (0x%X, 0x%X)" % self.version) 273 248 274 249 # read the operation-id (or status-code, but that's only 275 250 # for a response) (signed short) 276 self.operation_id = struct.unpack('>h', request.read(2)) 251 self.operation_id = struct.unpack('>h', request.read(2))[0] 252 logger.debug("operation-id : 0x%X" % self.operation_id) 277 253 278 254 # read the request-id (signed int) 279 self.request_id = struct.unpack('>i', request.read(4)) 255 self.request_id = struct.unpack('>i', request.read(4))[0] 256 logger.debug("request-id : 0x%X" % self.request_id) 280 257 281 258 # now we have to read in the attributes. Each attribute … … 284 261 285 262 # read in the next byte 286 next_byte = struct.unpack('>b', request.read(1)) 263 next_byte = struct.unpack('>b', request.read(1))[0] 264 logger.debug("next byte : 0x%X" % next_byte) 287 265 288 266 # as long as the next byte isn't signaling the end of the … … 290 268 while next_byte != IPPTags.END_OF_ATTRIBUTES_TAG: 291 269 292 # if the next byte is an attribute tag, then we're at 293 # the start of a new attribute 294 if next_byte <= 0x0F: 295 296 attribute_tag = next_byte 270 attribute_group_tag = next_byte 271 logger.debug("attribute-tag : %i" % attribute_group_tag) 272 273 next_byte = struct.unpack('>b', request.read(1))[0] 274 logger.debug("next byte : 0x%X" % next_byte) 275 276 while next_byte > 0x0F: 277 297 278 # read in the value tag (signed char) 298 value_tag = struct.unpack('>b', request.read(1)) 279 value_tag = next_byte 280 logger.debug("value-tag : 0x%X" % value_tag) 281 299 282 # read in the length of the name (signed short) 300 name_length = struct.unpack('>h', request.read(2)) 301 # read the name (a string of name_length bytes)302 name = struct.unpack('>s', request.read(name_length))303 # read in the length of the value (signed short)304 value_length = struct.unpack('>h', request.read(2))305 # read in the value (string of value_length bytes)306 value = struct.unpack('>%sb' % value_length, request.read(value_length))307 308 # create a new IPPAttribute from the data we just309 # read in, and add it to our attributes list310 self.attributes.append(IPPAttribute(311 attribute_tag,312 [IPPValue(value_tag, name, value)]))313 314 # otherwise, we're still in the process of reading the315 # current attribute (now we'll read in another value) 316 else:317 318 value_tag = next_byte319 # read in the length of the name (two bytes) --320 # this should be 0x0 321 name_length = struct.unpack('>h', request.read(2))322 assert name_length == IPPTags.ZERO_NAME_LENGTH323 # name should be empty324 name = ''325 # read in the length of the value (two bytes)326 value_length = struct.unpack('>h', request.read(2))327 # read in the value (value_length bytes)328 value = struct.unpack('>%sb' % value_length, request.read(value_length))329 330 # add another value to the last attribute331 self.attributes[-1].values.append(IPPValue(value_tag, name, value))332 333 # read another byte334 next_byte = struct.unpack('>b', request.read(1))283 name_length = struct.unpack('>h', request.read(2))[0] 284 logger.debug("name-length : %i" % name_length) 285 286 if name_length != IPPTags.ZERO_NAME_LENGTH: 287 # read the name (a string of name_length bytes) 288 name = request.read(name_length) 289 logger.debug("name : %s" % name) 290 291 # read in the length of the value (signed short) 292 value_length = struct.unpack('>h', request.read(2))[0] 293 logger.debug("value-length : %i" % value_length) 294 295 # read in the value (string of value_length bytes) 296 value = request.read(value_length) 297 logger.debug("value : %s" % value) 298 299 # create a new IPPAttribute from the data we just 300 # read in, and add it to our attributes list 301 self.attributes.append(IPPAttribute(name, 302 [IPPValue(value_tag, value)])) 303 304 else: 305 # read in the length of the value (signed short) 306 value_length = struct.unpack('>h', request.read(2))[0] 307 logger.debug("value-length : %i" % value_length) 308 309 # read in the value (string of value_length bytes) 310 value = request.read(value_length) 311 logger.debug("value : %s" % value) 312 313 # add another value to the last attribute 314 self.attributes[-1].values.append(IPPValue(value_tag, value)) 315 316 # read another byte 317 next_byte = struct.unpack('>b', request.read(1))[0] 335 318 336 319 # once we hit the end-of-attributes tag, the only thing 337 320 # left is the data, so go ahead and read all of it 338 buff= request.read()339 self.data = struct.unpack('>%sb' % len(buff), sys.getsizeof(buff))321 self.data = request.read() 322 logger.debug("data : %s" % self.data) 340 323 341 324 # otherwise, just set the class variables to the keyword 342 325 # arguments passed in 343 326 else: 344 self.version = int(version)327 self.version = (int(version[0]), int(version[1])) 345 328 self.operation_id = int(operation_id) 346 329 self.request_id = int(request_id) … … 361 344 362 345 # convert the attributes to binary 363 attributes = ''.join([a.toBinaryData() for a in attributes])346 attributes = ''.join([a.toBinaryData() for a in self.attributes]) 364 347 365 348 # conver the end-of-attributes-tag to binary … … 367 350 368 351 # convert the data to binary 369 data = ''.join([struct.pack('>b', x) for x in self.data]) 352 if self.data is not None: 353 data = ''.join([struct.pack('>b', x) for x in self.data]) 354 else: 355 data = '' 370 356 371 357 # append everything together and return it
Note: See TracChangeset
for help on using the changeset viewer.