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

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

Fix bugs; can now again do 'lpq' and get back a reasonable response

  • Property mode set to 100644
File size: 22.0 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
7import logging
8
9logger = logging.getLogger(__name__)
10
11def verify_operations(request):
12    """Pretty much all requests have the first attribute group for
13    operation attributes, and these all have 'attributes-charset' and
14    'attributes-natural-language' as the first two attributes.  This
15    method just generically verifies that these attributes are there.
16
17    """
18
19    # XXX: check version
20    if False:
21        raise err.VersionNotSupported(str(request.version))
22
23    # check operation id
24    if False:
25        raise err.OperationNotSupported(str(request.operation_id))
26
27    # check operation attributes tag
28    op_attrs = request.attribute_groups[0]
29    if op_attrs.tag != AttributeTags.OPERATION:
30        raise err.BadRequest(
31            "Attribute group does not have OPERATION tag: 0x%x" % op_attrs.tag)
32
33    # # check compression
34    # if False:
35    #     raise err.CompressionNotSupported
36
37    # # check document format
38    # if False:
39    #     raise err.DocumentFormatNotSupported
40
41    # # check document uri
42    # if False:
43    #     raise err.UriSchemeNotSupported
44
45    # check charset
46    charset_attr = op_attrs.attributes[0]
47    if charset_attr.name != 'attributes-charset':
48        raise err.BadRequest(
49            "Attribute is not attributes-charset: %s" % charset_attr.name)
50    if len(charset_attr.values) != 1:
51        raise err.BadRequest(
52            "Too many values for attributes-charset: %d" % len(charset_attr.values))
53    # check charset value
54    charset_value = charset_attr.values[0]
55    if charset_value.tag != operations_attribute_value_tags['attributes-charset']:
56        raise err.BadRequest(
57            "Wrong tag for charset value: 0x%x" % charset_value.tag)
58    if charset_value.value != 'utf-8':
59        raise err.CharsetNotSupported(str(charset_value.value))
60
61    # check for attributes-natural-language
62    natlang_attr = op_attrs.attributes[1]
63    if natlang_attr.name != 'attributes-natural-language':
64        raise err.BadRequest(
65            "Attribute is not attributes-natural-language: %s" % natlang_attr.name)
66    if len(charset_attr.values) != 1:
67        raise err.BadRequest(
68            "Too many values for attributes-natural-language: %s" % len(natlang_attr.values))
69    # check natural language value
70    natlang_value = natlang_attr.values[0]
71    if natlang_value.tag != operations_attribute_value_tags['attributes-natural-language']:
72        raise err.BadRequest(
73            "Natural language value does not have NATURAL_LANGUAGE tag: 0x%x" % natlang_value.tag)
74    if natlang_value.value != 'en-us':
75        raise err.Attributes(
76            "Invalid natural language value: %s" % natlang_value.value, [natlang_attr])
77
78    return dict([(attr.name, attr.values) for attr in op_attrs.attributes])
79
80def verify_printer_uri(values):
81    if len(values) != 1:
82        raise err.BadRequest(
83            "Requesting printer uri attribute has too many values: %d" % len(values))
84    uri_value = values[0]
85    if uri_value.tag != operations_attribute_value_tags['printer-uri']:
86        raise err.BadRequest(
87            "Bad value tag (expected URI): 0x%x" % uri_value_tag)
88   
89    # actually get the printer name
90    # XXX: hack -- CUPS will strip the port from the request, so
91    # we can't do an exact comparison (also the hostname might be
92    # different, depending on the CNAME or whether it's localhost)
93    uri = uri_value.value.split("/")[-1]
94    return uri
95
96def verify_requesting_username(values):
97    if len(values) != 1:
98        raise err.BadRequest(
99            "Requesting user name attribute has too many values: %d" % len(values))
100    requser_value = values[0]
101    if requser_value.tag != operations_attribute_value_tags['requesting-user-name']:
102        raise err.BadRequest(
103            "Bad value tag (expected NAME_WITHOUT_LANGUAGE): 0x%x" % requser_value.tag)
104   
105    return requser_value.value
106
107def make_empty_response(request):
108    # Operation attributes -- typically the same for any request
109    attributes = [
110        Attribute(
111            'attributes-charset',
112            [Value(operations_attribute_value_tags['attributes-charset'], 'utf-8')]),
113        Attribute(
114            'attributes-natural-language',
115            [Value(operations_attribute_value_tags['attributes-natural-language'], 'en-us')])
116        ]
117    # Put the operation attributes in a group
118    attribute_group = AttributeGroup(
119        AttributeTags.OPERATION,
120        attributes)
121
122    # Set up the default response -- handlers will override these
123    # values if they need to
124    response_kwargs = {}
125    response_kwargs['version']          = request.version
126    response_kwargs['operation_id']     = StatusCodes.OK
127    response_kwargs['request_id']       = request.request_id
128    response_kwargs['attribute_groups'] = [attribute_group]
129    response = Request(**response_kwargs)
130
131    return response
132
133#### GET-JOBS
134
135def verify_get_jobs_request(request):
136    """RFC 2911 3.2.6.1 Get-Jobs Request
137
138    The client submits the Get-Jobs request to a Printer object.
139   
140    The following groups of attributes are part of the Get-Jobs
141    Request:
142
143    Group 1: Operation Attributes
144        Natural Language and Character Set:
145            The 'attributes-charset' and
146            'attributes-natural-language' attributes as described
147            in section 3.1.4.1.
148        Target:
149            The 'printer-uri' (uri) operation attribute which is
150            the target for this operation as described in section
151            3.1.5.
152        Requesting User Name:
153            The 'requesting-user-name' (name(MAX)) attribute
154            SHOULD be supplied by the client as described in
155            section 8.3.
156        'limit' (integer(1:MAX)):
157            The client OPTIONALLY supplies this attribute. The
158            Printer object MUST support this attribute. It is an
159            integer value that determines the maximum number of
160            jobs that a client will receive from the Printer even
161            if 'which-jobs' or 'my-jobs' constrain which jobs are
162            returned. The limit is a 'stateless limit' in that if
163            the value supplied by the client is 'N', then only the
164            first 'N' jobs are returned in the Get-Jobs Response.
165            There is no mechanism to allow for the next 'M' jobs
166            after the first 'N' jobs. If the client does not
167            supply this attribute, the Printer object responds
168            with all applicable jobs.
169        'requested-attributes' (1setOf type2 keyword):
170            The client OPTIONALLY supplies this attribute. The
171            Printer object MUST support this attribute. It is a
172            set of Job attribute names and/or attribute groups
173            names in whose values the requester is
174            interested. This set of attributes is returned for
175            each Job object that is returned. The allowed
176            attribute group names are the same as those defined in
177            the Get-Job-Attributes operation in section 3.3.4. If
178            the client does not supply this attribute, the Printer
179            MUST respond as if the client had supplied this
180            attribute with two values: 'job-uri' and 'job-id'.
181        'which-jobs' (type2 keyword):
182            The client OPTIONALLY supplies this attribute. The
183            Printer object MUST support this attribute. It
184            indicates which Job objects MUST be returned by the
185            Printer object. The values for this attribute are:
186             - 'completed': This includes any Job object whose
187               state is 'completed', 'canceled', or 'aborted'.
188             - 'not-completed': This includes any Job object whose
189               state is 'pending', 'processing',
190               'processing-stopped', or 'pending-held'.
191            A Printer object MUST support both values. However, if
192            the implementation does not keep jobs in the
193            'completed', 'canceled', and 'aborted' states, then it
194            returns no jobs when the 'completed' value is
195            supplied.  If a client supplies some other value, the
196            Printer object MUST copy the attribute and the
197            unsupported value to the Unsupported Attributes
198            response group, reject the request, and return the
199            'client-error-attributes-or-values-not-supported'
200            status code.  If the client does not supply this
201            attribute, the Printer object MUST respond as if the
202            client had supplied the attribute with a value of
203            'not-completed'.
204        'my-jobs' (boolean):
205            The client OPTIONALLY supplies this attribute. The
206            Printer object MUST support this attribute. It
207            indicates whether jobs from all users or just the jobs
208            submitted by the requesting user of this request MUST
209            be considered as candidate jobs to be returned by the
210            Printer object. If the client does not supply this
211            attribute, the Printer object MUST respond as if the
212            client had supplied the attribute with a value of
213            'false', i.e., jobs from all users. The means for
214            authenticating the requesting user and matching the
215            jobs is described in section 8.
216
217    """
218
219    out = {}
220
221    # generic operations verification
222    attrs = verify_operations(request)
223
224    # requested printer uri
225    if 'printer-uri' not in attrs:
226        raise err.BadRequest("Missing 'printer-uri' attribute")
227    out['printer-uri'] = verify_printer_uri(attrs['printer-uri'])
228   
229    # requesting username
230    if 'requesting-user-name' not in attrs:
231        logger.warning("Missing 'requesting-user-name' attribute")
232    else:
233        out['requesting-user-name'] = verify_requesting_username(attrs['requesting-user-name'])
234
235    if 'limit' in attrs:
236        out['limit'] = None # XXX
237
238    if 'requested-attributes' in attrs:
239        out['requested-attributes'] = None # XXX
240
241    if 'which-jobs' in attrs:
242        out['which-jobs'] = None # XXX
243
244    if 'my-jobs' in attrs:
245        out['my-jobs'] = None # XXX
246
247    return out
248
249def make_get_jobs_response(self, request):
250    """RFC 2911: 3.2.6.2 Get-Jobs Response
251       
252    The Printer object returns all of the Job objects up to the number
253    specified by the 'limit' attribute that match the criteria as
254    defined by the attribute values supplied by the client in the
255    request. It is possible that no Job objects are returned since
256    there may literally be no Job objects at the Printer, or there may
257    be no Job objects that match the criteria supplied by the
258    client. If the client requests any Job attributes at all, there is
259    a set of Job Object Attributes returned for each Job object.
260
261    It is not an error for the Printer to return 0 jobs. If the
262    response returns 0 jobs because there are no jobs matching the
263    criteria, and the request would have returned 1 or more jobs
264    with a status code of 'successful-ok' if there had been jobs
265    matching the criteria, then the status code for 0 jobs MUST be
266    'successful-ok'.
267
268    Group 1: Operation Attributes
269        Status Message:
270            In addition to the REQUIRED status code returned in
271            every response, the response OPTIONALLY includes a
272            'status-message' (text(255)) and/or a
273            'detailed-status-message' (text(MAX)) operation
274            attribute as described in sections 13 and 3.1.6.
275        Natural Language and Character Set:
276            The 'attributes-charset' and
277            'attributes-natural-language' attributes as described
278            in section 3.1.4.2.
279
280    Group 2: Unsupported Attributes
281        See section 3.1.7 for details on returning Unsupported
282        Attributes.  The response NEED NOT contain the
283        'requested-attributes' operation attribute with any
284        supplied values (attribute keywords) that were requested
285        by the client but are not supported by the IPP object.  If
286        the Printer object does return unsupported attributes
287        referenced in the 'requested-attributes' operation
288        attribute and that attribute included group names, such as
289        'all', the unsupported attributes MUST NOT include
290        attributes described in the standard but not supported by
291        the implementation.
292
293    Groups 3 to N: Job Object Attributes
294        The Printer object responds with one set of Job Object
295        Attributes for each returned Job object. The Printer
296        object ignores (does not respond with) any requested
297        attribute or value which is not supported or which is
298        restricted by the security policy in force, including
299        whether the requesting user is the user that submitted the
300        job (job originating user) or not (see section
301        8). However, the Printer object MUST respond with the
302        'unknown' value for any supported attribute (including all
303        REQUIRED attributes) for which the Printer object does not
304        know the value, unless it would violate the security
305        policy. See the description of the 'out-of- band' values
306        in the beginning of Section 4.1.
307
308        Jobs are returned in the following order:
309        - If the client requests all 'completed' Jobs (Jobs in the
310          'completed', 'aborted', or 'canceled' states), then the
311          Jobs are returned newest to oldest (with respect to
312          actual completion time)
313        - If the client requests all 'not-completed' Jobs (Jobs in
314          the 'pending', 'processing', 'pending-held', and
315          'processing- stopped' states), then Jobs are returned in
316          relative chronological order of expected time to
317          complete (based on whatever scheduling algorithm is
318          configured for the Printer object).
319
320    """
321
322    pass
323
324## GET-PRINTER-ATTRIBUTES
325
326def verify_get_printer_attributes_request(request):
327    """RFC 2911: 3.2.5.1 Get-Printer-Attributes Request
328
329    The following sets of attributes are part of the Get-Printer-
330    Attributes Request:
331
332    Group 1: Operation Attributes
333        Natural Language and Character Set:
334            The 'attributes-charset' and 'attributes-natural-language'
335            attributes as described in section 3.1.4.1.
336        Target:
337            The 'printer-uri' (uri) operation attribute which is the
338            target for this operation as described in section 3.1.5.
339        Requesting User Name:
340            The 'requesting-user-name' (name(MAX)) attribute SHOULD be
341            supplied by the client as described in section 8.3.
342        'requested-attributes' (1setOf keyword):
343            The client OPTIONALLY supplies a set of attribute names
344            and/or attribute group names in whose values the requester
345            is interested. The Printer object MUST support this
346            attribute.  If the client omits this attribute, the
347            Printer MUST respond as if this attribute had been
348            supplied with a value of 'all'.
349        'document-format' (mimeMediaType):
350            The client OPTIONALLY supplies this attribute. The Printer
351            object MUST support this attribute. This attribute is
352            useful for a Printer object to determine the set of
353            supported attribute values that relate to the requested
354            document format.  The Printer object MUST return the
355            attributes and values that it uses to validate a job on a
356            create or Validate-Job operation in which this document
357            format is supplied. The Printer object SHOULD return only
358            (1) those attributes that are supported for the specified
359            format and (2) the attribute values that are supported for
360            the specified document format. By specifying the document
361            format, the client can get the Printer object to eliminate
362            the attributes and values that are not supported for a
363            specific document format. For example, a Printer object
364            might have multiple interpreters to support both
365            'application/postscript' (for PostScript) and 'text/plain'
366            (for text) documents. However, for only one of those
367            interpreters might the Printer object be able to support
368            'number-up' with values of '1', '2', and '4'. For the
369            other interpreter it might be able to only support
370            'number-up' with a value of '1'.  Thus a client can use
371            the Get-Printer-Attributes operation to obtain the
372            attributes and values that will be used to accept/reject a
373            create job operation.
374
375            If the Printer object does not distinguish between
376            different sets of supported values for each different
377            document format when validating jobs in the create and
378            Validate-Job operations, it MUST NOT distinguish between
379            different document formats in the Get-Printer-Attributes
380            operation. If the Printer object does distinguish between
381            different sets of supported values for each different
382            document format specified by the client, this
383            specialization applies only to the following Printer
384            object attributes:
385
386            - Printer attributes that are Job Template attributes
387              ('xxx- default' 'xxx-supported', and 'xxx-ready' in the
388              Table in Section 4.2),
389
390            - 'pdl-override-supported',
391            - 'compression-supported',
392            - 'job-k-octets-supported',
393            - 'job-impressions-supported',
394            - 'job-media-sheets-supported',
395            - 'printer-driver-installer',
396            - 'color-supported', and
397            - 'reference-uri-schemes-supported'
398
399            The values of all other Printer object attributes
400            (including 'document-format-supported') remain invariant
401            with respect to the client supplied document format
402            (except for new Printer description attribute as
403            registered according to section 6.2).
404
405            If the client omits this 'document-format' operation
406            attribute, the Printer object MUST respond as if the
407            attribute had been supplied with the value of the Printer
408            object's 'document-format- default' attribute. It is
409            RECOMMENDED that the client always supply a value for
410            'document-format', since the Printer object's
411            'document-format-default' may be
412            'application/octet-stream', in which case the returned
413            attributes and values are for the union of the document
414            formats that the Printer can automatically sense.  For
415            more details, see the description of the 'mimeMediaType'
416            attribute syntax in section 4.1.9.
417
418            If the client supplies a value for the 'document-format'
419            Operation attribute that is not supported by the Printer,
420            i.e., is not among the values of the Printer object's
421            'document-format-supported' attribute, the Printer object
422            MUST reject the operation and return the
423            'client-error-document-format-not-supported' status code.
424
425    """
426
427    out = {}
428
429    # generic operations verification
430    attrs = verify_operations(request)
431
432    # requested printer uri
433    if 'printer-uri' not in attrs:
434        raise err.BadRequest("Missing 'printer-uri' attribute")
435    out['printer-uri']  = verify_printer_uri(attrs['printer-uri'])
436
437    # requesting username
438    if 'requesting-user-name' not in attrs:
439        logger.warning("Missing 'requesting-user-name' attribute")
440    else:
441        out['requesting-user-name'] = verify_requesting_username(attrs['requesting-user-name'])
442
443    if 'requested-attributes' in attrs:
444        out['requested-attributes'] = None # XXX
445
446    if 'document-format' in attrs:
447        out['document-format'] = None # XXX
448
449    return out
450
451
452def make_get_printer_attributes_response(self, request):
453    """3.2.5.2 Get-Printer-Attributes Response
454
455    The Printer object returns the following sets of attributes as
456    part of the Get-Printer-Attributes Response:
457
458    Group 1: Operation Attributes
459        Status Message:
460            In addition to the REQUIRED status code returned in every
461            response, the response OPTIONALLY includes a
462            'status-message' (text(255)) and/or a
463            'detailed-status-message' (text(MAX)) operation attribute
464            as described in sections 13 and 3.1.6.
465        Natural Language and Character Set:
466            The 'attributes-charset' and 'attributes-natural-language'
467            attributes as described in section 3.1.4.2.
468
469    Group 2: Unsupported Attributes
470        See section 3.1.7 for details on returning Unsupported
471        Attributes.  The response NEED NOT contain the
472        'requested-attributes' operation attribute with any supplied
473        values (attribute keywords) that were requested by the client
474        but are not supported by the IPP object.  If the Printer
475        object does return unsupported attributes referenced in the
476        'requested-attributes' operation attribute and that attribute
477        included group names, such as 'all', the unsupported
478        attributes MUST NOT include attributes described in the
479        standard but not supported by the implementation.
480
481    Group 3: Printer Object Attributes
482        This is the set of requested attributes and their current
483        values.  The Printer object ignores (does not respond with)
484        any requested attribute which is not supported. The Printer
485        object MAY respond with a subset of the supported attributes
486        and values, depending on the security policy in
487        force. However, the Printer object MUST respond with the
488        'unknown' value for any supported attribute (including all
489        REQUIRED attributes) for which the Printer object does not
490        know the value. Also the Printer object MUST respond with the
491        'no-value' for any supported attribute (including all REQUIRED
492        attributes) for which the system administrator has not
493        configured a value. See the description of the 'out-of-band'
494        values in the beginning of Section 4.1.
495
496    """
497    pass
Note: See TracBrowser for help on using the repository browser.