Changeset 84e8137
- Timestamp:
- Nov 6, 2010, 3:24:25 PM (14 years ago)
- Branches:
- no-cups
- Children:
- 4ec7caa
- Parents:
- c216863
- git-author:
- Jessica B. Hamrick <jhamrick@…> (11/06/10 15:24:25)
- git-committer:
- Jessica B. Hamrick <jhamrick@…> (11/06/10 15:24:25)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
server/lib/ipprequest.py
rc216863 r84e8137 1 1 #!/usr/bin/python 2 2 3 import sys 4 5 # various tags 6 zero_name_length = 0x00 7 operation_attributes_tag = 0x01 8 job_attributes_tag = 0x02 9 end_of_attributes_tag = 0x03 10 printer_attributes_tag = 0x04 11 unsupported_attributes_tag = 0x05 12 13 # "out of band" value tags 14 oob_unsupported_value_tag = 0x10 15 oob_default_value_tag = 0x11 16 oob_unknown_value_tag = 0x12 17 oob_no_value_tag = 0x13 18 19 # integer value tags 20 generic_integer_value_tag = 0x20 21 integer_value_tag = 0x21 22 boolean_value_tag = 0x22 23 enum_value_tag = 0x23 24 25 # octetString value tags 26 unspecified_octetString_value_tag = 0x30 27 dateTime_value_tag = 0x31 28 resolution_value_tag = 0x32 29 rangeOfInteger_value_tag = 0x33 30 collection_value_tag = 0x34 31 textWithLanguage_value_tag = 0x35 32 nameWithLanguage_value_tag = 0x36 33 34 # character-string value tags 35 generic_char_string_value_tag = 0x40 36 textWithoutLanguage_value_tag = 0x41 37 nameWithoutLanguage_value_tag = 0x42 38 keyword_value_tag = 0x44 39 uri_value_tag = 0x45 40 uriScheme_value_tag = 0x46 41 charset_value_tag = 0x47 42 naturalLanguage_value_tag = 0x48 43 mimeMediaType_value_tag = 0x49 44 3 45 class IPPValue(): 46 """ 47 An IPP value consists of a tag and a value, and optionally, a name. 48 """ 49 4 50 def __init__(self, value_tag, name, value): 5 assert value_tag is not None and \ 6 value is not None 51 """ 52 Initialize an IPPValue: 53 54 Arguments: 55 56 value_tag -- one byte, identifying the type of value 57 58 name -- (optional) variable size, identifying the name of 59 this value 60 61 value -- variable size, containing the actual value 62 """ 63 64 # make sure value_tag isn't empty 65 assert value_tag is not None 66 # make sure the size of value_tag is one byte 67 assert sys.getsizeof(value_tag) == 1 68 # make sure value isn't empty 69 assert value is not None 7 70 8 71 self.value_tag = value_tag … … 11 74 12 75 class IPPAttribute(): 13 # From RFC 2565: 14 15 # Each attribute consists of: 16 # ----------------------------------------------- 17 # | value-tag | 1 byte 18 # ----------------------------------------------- 19 # | name-length (value is u) | 2 bytes 20 # ----------------------------------------------- 21 # | name | u bytes 22 # ----------------------------------------------- 23 # | value-length (value is v) | 2 bytes 24 # ----------------------------------------------- 25 # | value | v bytes 26 # ----------------------------------------------- 27 28 # An additional value consists of: 29 # ----------------------------------------------------------- 30 # | value-tag | 1 byte | 31 # ----------------------------------------------- | 32 # | name-length (value is 0x0000) | 2 bytes | 33 # ----------------------------------------------- |-0 or more 34 # | value-length (value is w) | 2 bytes | 35 # ----------------------------------------------- | 36 # | value | w bytes | 37 # ----------------------------------------------------------- 38 39 def __init__(self, attribute_tag, values): 40 assert attribute_tag is not None 41 for value in values: assert isinstance(value, IPPValue) 76 """ 77 From RFC 2565: 78 79 Each attribute consists of: 80 ----------------------------------------------- 81 | value-tag | 1 byte 82 ----------------------------------------------- 83 | name-length (value is u) | 2 bytes 84 ----------------------------------------------- 85 | name | u bytes 86 ----------------------------------------------- 87 | value-length (value is v) | 2 bytes 88 ----------------------------------------------- 89 | value | v bytes 90 ----------------------------------------------- 91 92 An additional value consists of: 93 ----------------------------------------------------------- 94 | value-tag | 1 byte | 95 ----------------------------------------------- | 96 | name-length (value is 0x0000) | 2 bytes | 97 ----------------------------------------------- |-0 or more 98 | value-length (value is w) | 2 bytes | 99 ----------------------------------------------- | 100 | value | w bytes | 101 ----------------------------------------------------------- 102 """ 103 104 def __init__(self, attribute_tag, values): 105 """ 106 Initialize an IPPAttribute. 107 108 Arguments: 109 110 attribute_tag -- one byte, identifying the type of attribute 111 112 values -- a list of IPPValues. May not be empty. 113 """ 114 115 # make sure attribute_tag isn't empty 116 assert attribute_tag is not None 117 # make sure attribute_tag is of the right size 118 assert sys.getsizeof(attribute_tag) == 1 119 120 # make sure the list of values isn't empty 121 assert len(values) > 0 122 # make sure each value is an IPPValue 123 for value in values: assert isinstance(value, IPPValue) 42 124 43 self.attribute_tag = attribute_tag44 self.values = values125 self.attribute_tag = attribute_tag 126 self.values = values 45 127 46 128 class IPPRequest(): 47 # From RFC 2565: 129 """ 130 From RFC 2565: 48 131 49 # The encoding for an operation request or response consists of: 50 # ----------------------------------------------- 51 # | version-number | 2 bytes - required 52 # ----------------------------------------------- 53 # | operation-id (request) | 54 # | or | 2 bytes - required 55 # | status-code (response) | 56 # ----------------------------------------------- 57 # | request-id | 4 bytes - required 58 # ----------------------------------------------------------- 59 # | xxx-attributes-tag | 1 byte | 60 # ----------------------------------------------- |-0 or more 61 # | xxx-attribute-sequence | n bytes | 62 # ----------------------------------------------------------- 63 # | end-of-attributes-tag | 1 byte - required 64 # ----------------------------------------------- 65 # | data | q bytes - optional 66 # ----------------------------------------------- 132 The encoding for an operation request or response consists of: 133 ----------------------------------------------- 134 | version-number | 2 bytes - required 135 ----------------------------------------------- 136 | operation-id (request) | 137 | or | 2 bytes - required 138 | status-code (response) | 139 ----------------------------------------------- 140 | request-id | 4 bytes - required 141 ----------------------------------------------------------- 142 | xxx-attributes-tag | 1 byte | 143 ----------------------------------------------- |-0 or more 144 | xxx-attribute-sequence | n bytes | 145 ----------------------------------------------------------- 146 | end-of-attributes-tag | 1 byte - required 147 ----------------------------------------------- 148 | data | q bytes - optional 149 ----------------------------------------------- 150 """ 67 151 68 152 # either give the version, operation_id, request_id, … … 70 154 # can be read from to get the request 71 155 def __init__(self, version=None, operation_id=None, request_id=None, attributes=[], data=None, request=None): 72 assert (version is not None and \ 73 operation_id is not None and \ 74 request_id is not None) or request is not None 75 156 """ 157 Create an IPPRequest. Takes either the segments of the 158 request separately, or a file handle for the request to parse. 159 If the file handle is passed in, all other arguments are 160 ignored. 161 162 Keyword arguments for passing in the segments of the request: 163 164 version -- two bytes, identifying the version number of 165 the request 166 167 operation_id -- two bytes, identifying the id of the 168 requested operation 169 170 request_id -- four bytes, identifying the id of the 171 request itself. 172 173 attributes -- a list of IPPAttributes. May be empty. 174 175 data -- (optional) variable length, containing the actual 176 data of the request 177 178 Keyword arguments for passing in the raw request: 179 180 request -- a file handle that supports the read() 181 operation 182 """ 183 184 if request is None: 185 # make sure the version number isn't empty 186 assert version is not None 187 # make sure the version number is two bytes long 188 assert sys.getsizeof(version) == 2 189 # make sure the operation id isn't empty 190 assert operation_id is not None 191 # make sure the operation id is two bytes long 192 assert sys.getsizeof(operation_id) == 2 193 # make sure the request id isn't empty 194 assert request_id is not None 195 # make sure the request id is four bytes long 196 assert sys.getsizeof(request_id) == 4 197 198 # if the request isn't None, then we'll read directly from 199 # that file handle 76 200 if request is not None: 201 # read the version-number (two bytes) 77 202 self.version = request.read(2) 203 204 # read the operation-id (or status-code, but that's only 205 # for a response) (two bytes) 78 206 self.operation_id = request.read(2) 207 208 # read the request-id (4 bytes) 79 209 self.request_id = request.read(4) 210 211 # now we have to read in the attributes. Each attribute 212 # has a tag (1 byte) and a sequence of values (n bytes) 80 213 self.attributes = [] 81 214 215 # read in the next byte 82 216 next_byte = request.read(1) 83 while next_byte != 0x03: 217 218 # as long as the next byte isn't signaling the end of the 219 # attributes, keep looping and parsing attributes 220 while next_byte != end_of_attributes_tag: 221 222 # if the next byte is an attribute tag, then we're at 223 # the start of a new attribute 84 224 if next_byte <= 0x0F: 225 85 226 attribute_tag = next_byte 227 # read in the value tag (one byte) 86 228 value_tag = request.read(1) 229 # read in the length of the name (two bytes) 87 230 name_length = request.read(2) 231 # read the name (name_length bytes) 88 232 name = request.read(name_length) 233 # read in the length of the value (two bytes) 89 234 value_length = request.read(2) 235 # read in the value (value_length bytes) 90 236 value = request.read(value_length) 91 237 238 # create a new IPPAttribute from the data we just 239 # read in, and add it to our attributes list 92 240 self.attributes.append(IPPAttribute( 93 241 attribute_tag, 94 242 [IPPValue(value_tag, name, value)])) 243 244 # otherwise, we're still in the process of reading the 245 # current attribute (now we'll read in another value) 95 246 else: 247 96 248 value_tag = next_byte 249 # read in the length of the name (two bytes) -- 250 # this should be 0x0 97 251 name_length = request.read(2) 252 assert name_length == zero_name_length 253 # name should be empty 98 254 name = None 255 # read in the length of the value (two bytes) 99 256 value_length = request.read(2) 257 # read in the value (value_length bytes) 100 258 value = request.read(value_length) 101 259 260 # add another value to the last attribute 102 261 self.attributes[-1].values.append(IPPValue(value_tag, name, value)) 103 262 263 # read another byte 104 264 next_byte = request.read(1) 105 265 266 # once we hit the end-of-attributes tag, the only thing 267 # left is the data, so go ahead and read all of it 106 268 self.data = request.read() 107 269 270 # otherwise, just set the class variables to the keyword 271 # arguments passed in 108 272 else: 109 273 self.version = version
Note: See TracChangeset
for help on using the changeset viewer.