1 | #!/usr/bin/python |
---|
2 | |
---|
3 | class IPPValue(): |
---|
4 | def __init__(self, value_tag, name, value): |
---|
5 | assert value_tag is not None and \ |
---|
6 | value is not None |
---|
7 | |
---|
8 | self.value_tag = value_tag |
---|
9 | self.name = name |
---|
10 | self.value = value |
---|
11 | |
---|
12 | 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) |
---|
42 | |
---|
43 | self.attribute_tag = attribute_tag |
---|
44 | self.values = values |
---|
45 | |
---|
46 | class IPPRequest(): |
---|
47 | # From RFC 2565: |
---|
48 | |
---|
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 | # ----------------------------------------------- |
---|
67 | |
---|
68 | # either give the version, operation_id, request_id, |
---|
69 | # attribute_sequence, and data, or a file handler (request) which |
---|
70 | # can be read from to get the request |
---|
71 | 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 | |
---|
76 | if request is not None: |
---|
77 | self.version = request.read(2) |
---|
78 | self.operation_id = request.read(2) |
---|
79 | self.request_id = request.read(4) |
---|
80 | self.attributes = [] |
---|
81 | |
---|
82 | next_byte = request.read(1) |
---|
83 | while next_byte != 0x03: |
---|
84 | if next_byte <= 0x0F: |
---|
85 | attribute_tag = next_byte |
---|
86 | value_tag = request.read(1) |
---|
87 | name_length = request.read(2) |
---|
88 | name = request.read(name_length) |
---|
89 | value_length = request.read(2) |
---|
90 | value = request.read(value_length) |
---|
91 | |
---|
92 | self.attributes.append(IPPAttribute( |
---|
93 | attribute_tag, |
---|
94 | [IPPValue(value_tag, name, value)])) |
---|
95 | else: |
---|
96 | value_tag = next_byte |
---|
97 | name_length = request.read(2) |
---|
98 | name = None |
---|
99 | value_length = request.read(2) |
---|
100 | value = request.read(value_length) |
---|
101 | |
---|
102 | self.attributes[-1].values.append(IPPValue(value_tag, name, value)) |
---|
103 | |
---|
104 | next_byte = request.read(1) |
---|
105 | |
---|
106 | self.data = request.read() |
---|
107 | |
---|
108 | else: |
---|
109 | self.version = version |
---|
110 | self.operation_id = operation_id |
---|
111 | self.request_id = request_id |
---|
112 | self.attributes = attributes |
---|
113 | self.data = data |
---|