source: server/lib/gutenbach/ipp/operations.py @ f6c6897

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

Fix some errors in ipp/

  • Property mode set to 100644
File size: 14.1 KB
Line 
1from .value import Value
2from .attribute import Attribute
3from .attributegroup import AttributeGroup
4from .request import Request
5from .constants import AttributeTags, StatusCodes, operations_attribute_value_tags
6import exceptions as err
7
8def verify_operations(request):
9    """Pretty much all requests have the first attribute group for
10    operation attributes, and these all have 'attributes-charset' and
11    'attributes-natural-language' as the first two attributes.  This
12    method just generically verifies that these attributes are there.
13
14    """
15
16    # check operation attributes tag
17    op_attrs = request.attribute_groups[0]
18    if op_attrs.tag != AttributeTags.OPERATION:
19        raise err.BadRequest(
20            "Attribute group does not have OPERATION tag: 0x%x" % op_attrs.tag)
21
22    # XXX: check version
23    if False:
24        raise err.VersionNotSupported(str(request.version))
25
26    # check operation id
27    if False:
28        raise err.OperationNotSupported(str(request.operation_id))
29
30    # # check compression
31    # if False:
32    #     raise err.CompressionNotSupported
33
34    # # check document format
35    # if False:
36    #     raise err.DocumentFormatNotSupported
37
38    # # check document uri
39    # if False:
40    #     raise err.UriSchemeNotSupported
41
42    # check charset
43    charset_attr = op_attrs.attributes[0]
44    if charset_attr.name != 'attributes-charset':
45        raise err.BadRequest(
46            "Attribute is not attributes-charset: %s" % charset_attr.name)
47    if len(charset_attr.values) != 1:
48        raise err.BadRequest(
49            "Too many values for attributes-charset: %d" % len(charset_attr.values))
50
51    # check charset value
52    charset_value = charset_attr.values[0]
53    if charset_value.tag != operations_attribute_value_tags['attributes-charset']:
54        raise err.BadRequest(
55            "Wrong tag for charset value: 0x%x" % charset_value.tag)
56    if charset_value.value != 'utf-8':
57        raise err.CharsetNotSupported(str(charset_value.value))
58
59    # check for attributes-natural-language
60    natlang_attr = op_attrs.attributes[1]
61    if natlang_attr.name != 'attributes-natural-language':
62        raise err.BadRequest(
63            "Attribute is not attributes-natural-language: %s" % natlang_attr.name)
64    if len(charset_attr.values) != 1:
65        raise err.BadRequest(
66            "Too many values for attributes-natural-language: %s" % len(natlang_attr.values))
67
68    # check natural language value
69    natlang_value = natlang_attr.values[0]
70    if natlang_value.tag != operations_attribute_value_tags['attributes-natural-language']:
71        raise err.BadRequest(
72            "Natural language value does not have NATURAL_LANGUAGE tag: 0x%x" % natlang_value.tag)
73    if natlang_value.value != 'en-us':
74        raise err.Attributes(
75            "Invalid natural language value: %s" % natlang_value.value, [natlang_attr])
76
77def verify_printer_uri(uri_attr):
78    if uri_attr.name != 'printer-uri':
79        raise err.BadRequest(
80            "Unexpected name for attribute 'printer-uri': %s" % uri_attr.name)
81    if len(uri_attr.values) != 1:
82        raise err.BadRequest(
83            "Requesting printer uri attribute has too many values: %d" % len(uri_attr.values))
84    printer_name_value = uri_attr.values[0]
85    if printer_name_value.tag != operations_attribute_value_tags['printer-uri']:
86        raise err.BadRequest(
87            "Bad value tag (expected URI): 0x%x" % printer_name_value_tag)
88   
89    # actually get the printer name
90    printer_name_value = printer_name_attr.values[0].value
91    # XXX: hack -- CUPS will strip the port from the request, so
92    # we can't do an exact comparison (also the hostname might be
93    # different, depending on the CNAME or whether it's localhost)
94    printer_name = printer_name_value.split("/")[-1]
95    return printer_name
96
97def verify_requesting_username(requser_attr):
98    if requser_attr.name != 'requesting-user-name':
99        raise err.BadRequest(
100            "Unexpected name for attribute 'requesting-user-name': %s" % requser_attr.name)
101    if len(requser_attr.values) != 1:
102        raise err.BadRequest(
103            "Requesting user name attribute has too many values: %d" % len(requser_attr.values))
104    requser_value = requser_attr.values[0]
105    if requser_value.tag != operations_attribute_value_tags['requesting-user-name']:
106        raise err.BadRequest(
107            "Bad value tag (expected NAME_WITHOUT_LANGUAGE): 0x%x" % requser_value.tag)
108   
109    return requser_value.value
110
111def make_empty_response(request):
112    # Operation attributes -- typically the same for any request
113    attributes = [
114        Attribute(
115            'attributes-charset',
116            [Value(operations_attribute_value_tags['attributes-charset'], 'utf-8')]),
117        Attribute(
118            'attributes-natural-language',
119            [Value(operations_attribute_value_tags['attributes-natural-language'], 'en-us')])
120        ]
121    # Put the operation attributes in a group
122    attribute_group = AttributeGroup(
123        AttributeTags.OPERATION,
124        attributes)
125
126    # Set up the default response -- handlers will override these
127    # values if they need to
128    response_kwargs = {}
129    response_kwargs['version']          = request.version
130    response_kwargs['operation_id']     = StatusCodes.OK
131    response_kwargs['request_id']       = request.request_id
132    response_kwargs['attribute_groups'] = [attribute_group]
133    response = Request(**response_kwargs)
134
135    return response
136
137#### GET-JOBS
138
139def verify_get_jobs_request(request):
140    """RFC 2911 3.2.6.1 Get-Jobs Request
141
142    The client submits the Get-Jobs request to a Printer object.
143   
144    The following groups of attributes are part of the Get-Jobs
145    Request:
146
147    Group 1: Operation Attributes
148        Natural Language and Character Set:
149            The 'attributes-charset' and
150            'attributes-natural-language' attributes as described
151            in section 3.1.4.1.
152        Target:
153            The 'printer-uri' (uri) operation attribute which is
154            the target for this operation as described in section
155            3.1.5.
156        Requesting User Name:
157            The 'requesting-user-name' (name(MAX)) attribute
158            SHOULD be supplied by the client as described in
159            section 8.3.
160        'limit' (integer(1:MAX)):
161            The client OPTIONALLY supplies this attribute. The
162            Printer object MUST support this attribute. It is an
163            integer value that determines the maximum number of
164            jobs that a client will receive from the Printer even
165            if 'which-jobs' or 'my-jobs' constrain which jobs are
166            returned. The limit is a 'stateless limit' in that if
167            the value supplied by the client is 'N', then only the
168            first 'N' jobs are returned in the Get-Jobs Response.
169            There is no mechanism to allow for the next 'M' jobs
170            after the first 'N' jobs. If the client does not
171            supply this attribute, the Printer object responds
172            with all applicable jobs.
173        'requested-attributes' (1setOf type2 keyword):
174            The client OPTIONALLY supplies this attribute. The
175            Printer object MUST support this attribute. It is a
176            set of Job attribute names and/or attribute groups
177            names in whose values the requester is
178            interested. This set of attributes is returned for
179            each Job object that is returned. The allowed
180            attribute group names are the same as those defined in
181            the Get-Job-Attributes operation in section 3.3.4. If
182            the client does not supply this attribute, the Printer
183            MUST respond as if the client had supplied this
184            attribute with two values: 'job-uri' and 'job-id'.
185        'which-jobs' (type2 keyword):
186            The client OPTIONALLY supplies this attribute. The
187            Printer object MUST support this attribute. It
188            indicates which Job objects MUST be returned by the
189            Printer object. The values for this attribute are:
190             - 'completed': This includes any Job object whose
191               state is 'completed', 'canceled', or 'aborted'.
192             - 'not-completed': This includes any Job object whose
193               state is 'pending', 'processing',
194               'processing-stopped', or 'pending-held'.
195            A Printer object MUST support both values. However, if
196            the implementation does not keep jobs in the
197            'completed', 'canceled', and 'aborted' states, then it
198            returns no jobs when the 'completed' value is
199            supplied.  If a client supplies some other value, the
200            Printer object MUST copy the attribute and the
201            unsupported value to the Unsupported Attributes
202            response group, reject the request, and return the
203            'client-error-attributes-or-values-not-supported'
204            status code.  If the client does not supply this
205            attribute, the Printer object MUST respond as if the
206            client had supplied the attribute with a value of
207            'not-completed'.
208        'my-jobs' (boolean):
209            The client OPTIONALLY supplies this attribute. The
210            Printer object MUST support this attribute. It
211            indicates whether jobs from all users or just the jobs
212            submitted by the requesting user of this request MUST
213            be considered as candidate jobs to be returned by the
214            Printer object. If the client does not supply this
215            attribute, the Printer object MUST respond as if the
216            client had supplied the attribute with a value of
217            'false', i.e., jobs from all users. The means for
218            authenticating the requesting user and matching the
219            jobs is described in section 8.
220
221    """
222
223
224    # generic operations verification
225    verify_operations(request)
226    # requested printer uri
227    printeruri = verify_printer_uri(request.attribute_groups[0].attributes[2])
228    # requesting username
229    requser = verify_requesting_username(request.attribute_groups[0].attributes[3])
230    # make the rest of the attributes into a dictionary
231    attrs = dict([(attr.name, attr.values) for attr in request.attributes[4:]])
232   
233    out = {
234        'printer-uri': printeruri,
235        'requesting-user-name': requser
236        }
237
238    if 'limit' in attrs:
239        out['limit'] = None # XXX
240
241    if 'requested-attributes' in attrs:
242        out['requested-attributes'] = None # XXX
243
244    if 'which-jobs' in attrs:
245        out['which-jobs'] = None # XXX
246
247    if 'my-jobs' in attrs:
248        out['my-jobs'] = None # XXX
249
250    return out
251
252def make_get_jobs_response(self, request):
253    """RFC 2911: 3.2.6.2 Get-Jobs Response
254       
255    The Printer object returns all of the Job objects up to the number
256    specified by the 'limit' attribute that match the criteria as
257    defined by the attribute values supplied by the client in the
258    request. It is possible that no Job objects are returned since
259    there may literally be no Job objects at the Printer, or there may
260    be no Job objects that match the criteria supplied by the
261    client. If the client requests any Job attributes at all, there is
262    a set of Job Object Attributes returned for each Job object.
263
264    It is not an error for the Printer to return 0 jobs. If the
265    response returns 0 jobs because there are no jobs matching the
266    criteria, and the request would have returned 1 or more jobs
267    with a status code of 'successful-ok' if there had been jobs
268    matching the criteria, then the status code for 0 jobs MUST be
269    'successful-ok'.
270
271    Group 1: Operation Attributes
272        Status Message:
273            In addition to the REQUIRED status code returned in
274            every response, the response OPTIONALLY includes a
275            'status-message' (text(255)) and/or a
276            'detailed-status-message' (text(MAX)) operation
277            attribute as described in sections 13 and 3.1.6.
278        Natural Language and Character Set:
279            The 'attributes-charset' and
280            'attributes-natural-language' attributes as described
281            in section 3.1.4.2.
282
283    Group 2: Unsupported Attributes
284        See section 3.1.7 for details on returning Unsupported
285        Attributes.  The response NEED NOT contain the
286        'requested-attributes' operation attribute with any
287        supplied values (attribute keywords) that were requested
288        by the client but are not supported by the IPP object.  If
289        the Printer object does return unsupported attributes
290        referenced in the 'requested-attributes' operation
291        attribute and that attribute included group names, such as
292        'all', the unsupported attributes MUST NOT include
293        attributes described in the standard but not supported by
294        the implementation.
295
296    Groups 3 to N: Job Object Attributes
297        The Printer object responds with one set of Job Object
298        Attributes for each returned Job object. The Printer
299        object ignores (does not respond with) any requested
300        attribute or value which is not supported or which is
301        restricted by the security policy in force, including
302        whether the requesting user is the user that submitted the
303        job (job originating user) or not (see section
304        8). However, the Printer object MUST respond with the
305        'unknown' value for any supported attribute (including all
306        REQUIRED attributes) for which the Printer object does not
307        know the value, unless it would violate the security
308        policy. See the description of the 'out-of- band' values
309        in the beginning of Section 4.1.
310
311        Jobs are returned in the following order:
312        - If the client requests all 'completed' Jobs (Jobs in the
313          'completed', 'aborted', or 'canceled' states), then the
314          Jobs are returned newest to oldest (with respect to
315          actual completion time)
316        - If the client requests all 'not-completed' Jobs (Jobs in
317          the 'pending', 'processing', 'pending-held', and
318          'processing- stopped' states), then Jobs are returned in
319          relative chronological order of expected time to
320          complete (based on whatever scheduling algorithm is
321          configured for the Printer object).
322
323    """
324
325    pass
Note: See TracBrowser for help on using the repository browser.