Ignore:
Timestamp:
Jan 11, 2012, 12:51:51 AM (12 years ago)
Author:
Jessica B. Hamrick <jhamrick@…>
Branches:
no-cups
Children:
be6ff03
Parents:
ffbe41d
git-author:
Jessica B. Hamrick <jhamrick@…> (01/11/12 00:51:51)
git-committer:
Jessica B. Hamrick <jhamrick@…> (01/11/12 00:51:51)
Message:

Clean up printer, job, and requests code

File:
1 edited

Legend:

Unmodified
Added
Removed
  • server/lib/gutenbach/server/requests.py

    rffbe41d rb01b6d1  
    3737    return response
    3838
     39def verify_attribute(attr, cls, length=1):
     40    vals = [val.value for val in attr.values]
     41    if attr != cls(*vals):
     42        raise ipp.errors.ClientErrorBadRequest(str(attr))
     43    if length is not None and len(vals) != length:
     44        raise ipp.errors.ClientErrorBadRequest(str(attr))
     45    return vals
     46
    3947class GutenbachRequestHandler(object):
    4048
     
    5664        # check charset
    5765        charset_attr = operation.attributes[0]
    58         expected = ipp.AttributesCharset(charset_attr.values[0].value)
    59         if charset_attr != expected:
    60             raise ipp.errors.ClientErrorBadRequest(str(charset_attr))
    61         if charset_attr.values[0].value != 'utf-8':
     66        charset = verify_attribute(charset_attr, ipp.AttributesCharset)[0]
     67        if charset != 'utf-8':
    6268            raise ipp.errors.ClientErrorAttributes(str(charset_attr))
    6369
    6470        # check for attributes-natural-language
    6571        natlang_attr = operation.attributes[1]
    66         expected = ipp.AttributesNaturalLanguage(natlang_attr.values[0].value)
    67         if natlang_attr != expected:
    68             raise ipp.errors.ClientErrorBadRequest(str(natlang_attr))
    69         if natlang_attr.values[0].value != 'en-us':
     72        natlang = verify_attribute(natlang_attr, ipp.AttributesNaturalLanguage)[0]
     73        if natlang != 'en-us':
    7074            raise ipp.errors.ClientErrorAttributes(str(natlang_attr))
    7175   
     
    213217        operation = request.attribute_groups[0]
    214218
     219        # initialize operation attribute variables
     220        printer_name = None
     221        user = None
     222        limit = None
     223        attributes = None
     224        which_jobs = None
     225        my_jobs = None
     226
    215227        # requested printer uri
    216228        if 'printer-uri' not in operation:
    217229            raise ipp.errors.ClientErrorBadRequest("Missing 'printer-uri' attribute")
    218         uri_attr = operation['printer-uri']
    219         printer_name = uri_attr.values[0].value.split("/")[-1]
    220         if uri_attr != ipp.PrinterUri(uri_attr.values[0].value):
    221             raise ipp.errors.ClientErrorBadRequest(str(uri_attr))
    222         if printer_name != self.printer.name:
    223             raise ipp.errors.ClientErrorAttributes(str(uri_attr), uri_attr)
    224 
     230        printer_uri = verify_attribute(operation['printer-uri'], ipp.PrinterUri)[0]
     231        if printer_uri not in self.printer.uris:
     232            raise ipp.errors.ClientErrorAttributes(
     233                str(operation['printer-uri']), operation['printer-uri'])
     234
     235        # optional attributes
     236        if 'limit' in operation:
     237            limit = verify_attribute(
     238                operation['limit'], ipp.Limit)[0]
     239           
     240        if 'requested-attributes' in operation:
     241            attributes = verify_attribute(
     242                operation['requested-attributes'], ipp.RequestedAttributes, length=None)
     243           
     244        if 'which-jobs' in operation:
     245            which_jobs = verify_attribute(
     246                operation['which-jobs'], ipp.WhichJobs)[0]
     247           
     248        if 'my-jobs' in operation:
     249            my_jobs = verify_attribute(
     250                operation['my-jobs'], ipp.MyJobs)[0]
     251
     252        if 'requesting-user-name' in operation:
     253            user = verify_attribute(
     254                operation['requesting-user-name'], ipp.RequestingUserName)[0]
     255            # ignore if we're not filtering jobs by user
     256            if not my_jobs:
     257                user = None
     258           
    225259        # get the job attributes and add them to the response
    226         for job in self.printer.get_jobs():
    227             attrs = job.get_job_attributes(operation)
     260        jobs = self.printer.get_jobs(
     261            which_jobs=which_jobs,
     262            requesting_user_name=user)
     263        for job in jobs:
     264            attrs = job.get_job_attributes(requested_attributes=attributes)
    228265            response.attribute_groups.append(ipp.AttributeGroup(
    229266                ipp.AttributeTags.JOB, attrs))
     
    283320        operation = request.attribute_groups[0]
    284321
     322        printer_uri = None
     323        requesting_user_name = None
     324        job_name = None
     325        ipp_attribute_fidelity=None
     326        job_k_octets = None
     327
    285328        # requested printer uri
    286329        if 'printer-uri' not in operation:
    287330            raise ipp.errors.ClientErrorBadRequest("Missing 'printer-uri' attribute")
    288         uri_attr = operation['printer-uri']
    289         printer_name = uri_attr.values[0].value.split("/")[-1]
    290         if uri_attr != ipp.PrinterUri(uri_attr.values[0].value):
    291             raise ipp.errors.ClientErrorBadRequest(str(uri_attr))
    292         if printer_name != self.printer.name:
    293             raise ipp.errors.ClientErrorAttributes(str(uri_attr), uri_attr)
     331        printer_uri = verify_attribute(operation['printer-uri'], ipp.PrinterUri)[0]
     332        if printer_uri not in self.printer.uris:
     333            raise ipp.errors.ClientErrorAttributes(
     334                str(operation['printer-uri']), operation['printer-uri'])
     335
     336        if 'requesting-user-name' in operation:
     337            user_name = verify_attribute(
     338                operation['requesting-user-name'], ipp.RequestingUserName)[0]
     339
     340        if 'job-name' in operation:
     341            job_name = verify_attribute(
     342                operation['job-name'], ipp.JobName)[0]
     343
     344        if 'job-k-octets' in operation:
     345            job_k_octets = verify_attribute(
     346                operation['job-k-octets'], ipp.JobKOctets)[0]
     347
     348        if 'ipp-attribute-fidelity' in operation:
     349            pass # don't care
     350        if 'job-impressions' in operation:
     351            pass # don't care
     352        if 'job-media-sheets' in operation:
     353            pass # don't care
    294354
    295355        # get attributes from the printer and add to response
    296         job = self.printer.create_job(request)
     356        job = self.printer.create_job(
     357            requesting_user_name=requesting_user_name,
     358            job_name=job_name,
     359            job_k_octets=job_k_octets)
    297360        response.attribute_groups.append(ipp.AttributeGroup(
    298             ipp.AttributeTags.JOB, job.get_job_attributes(operation)))
     361            ipp.AttributeTags.JOB, job.get_job_attributes()))
    299362   
    300363    @handler_for(ipp.OperationCodes.PAUSE_PRINTER)
     
    345408        operation = request.attribute_groups[0]
    346409
     410        printer_uri = None
     411        requesting_user_name = None
     412        requested_attributes = None
     413        document_format = None
     414
    347415        # requested printer uri
    348416        if 'printer-uri' not in operation:
    349417            raise ipp.errors.ClientErrorBadRequest("Missing 'printer-uri' attribute")
    350         uri_attr = operation['printer-uri']
    351         printer_name = uri_attr.values[0].value.split("/")[-1]
    352         if uri_attr != ipp.PrinterUri(uri_attr.values[0].value):
    353             raise ipp.errors.ClientErrorBadRequest(str(uri_attr))
    354         if printer_name != self.printer.name:
    355             raise ipp.errors.ClientErrorAttributes(str(uri_attr), uri_attr)
    356         printer = self.printer
     418        printer_uri = verify_attribute(operation['printer-uri'], ipp.PrinterUri)[0]
     419        if printer_uri not in self.printer.uris:
     420            raise ipp.errors.ClientErrorAttributes(
     421                str(operation['printer-uri']), operation['printer-uri'])
     422
     423        # optional attributes
     424        if 'requesting-user-name' in operation:
     425            user_name = verify_attribute(
     426                operation['requesting-user-name'], ipp.RequestingUserName)[0]
     427           
     428        if 'requested-attributes' in operation:
     429            requested_attributes = verify_attribute(
     430                operation['requested-attributes'], ipp.RequestedAttributes, length=None)
     431
     432        if 'document-format' in operation:
     433            pass # XXX: todo
    357434
    358435        # get attributes from the printer and add to response
    359436        response.attribute_groups.append(ipp.AttributeGroup(
    360             ipp.AttributeTags.PRINTER, printer.get_printer_attributes(operation)))
     437            ipp.AttributeTags.PRINTER,
     438            self.printer.get_printer_attributes(
     439                requested_attributes=requested_attributes)))
    361440
    362441    @handler_for(ipp.OperationCodes.SET_PRINTER_ATTRIBUTES)
     
    372451    @handler_for(ipp.OperationCodes.SEND_DOCUMENT)
    373452    def send_document(self, request, response):
     453        """3.3.1 Send-Document Operation
     454       
     455        This OPTIONAL operation allows a client to create a
     456        multi-document Job object that is initially 'empty' (contains
     457        no documents). In the Create-Job response, the Printer object
     458        returns the Job object's URI (the 'job-uri' attribute) and the
     459        Job object's 32-bit identifier (the 'job-id' attribute). For
     460        each new document that the client desires to add, the client
     461        uses a Send-Document operation. Each Send- Document Request
     462        contains the entire stream of document data for one document.
     463
     464        If the Printer supports this operation but does not support
     465        multiple documents per job, the Printer MUST reject subsequent
     466        Send-Document operations supplied with data and return the
     467        'server-error-multiple- document-jobs-not-supported'. However,
     468        the Printer MUST accept the first document with a 'true' or
     469        'false' value for the 'last-document' operation attribute (see
     470        below), so that clients MAY always submit one document jobs
     471        with a 'false' value for 'last-document' in the first
     472        Send-Document and a 'true' for 'last-document' in the second
     473        Send-Document (with no data).
     474       
     475        Since the Create-Job and the send operations (Send-Document or
     476        Send- URI operations) that follow could occur over an
     477        arbitrarily long period of time for a particular job, a client
     478        MUST send another send operation within an IPP Printer defined
     479        minimum time interval after the receipt of the previous
     480        request for the job. If a Printer object supports the
     481        Create-Job and Send-Document operations, the Printer object
     482        MUST support the 'multiple-operation-time-out' attribute (see
     483        section 4.4.31). This attribute indicates the minimum number
     484        of seconds the Printer object will wait for the next send
     485        operation before taking some recovery action.
     486
     487        An IPP object MUST recover from an errant client that does not
     488        supply a send operation, sometime after the minimum time
     489        interval specified by the Printer object's
     490        'multiple-operation-time-out' attribute.
     491
     492        Access Rights: The authenticated user (see section 8.3)
     493        performing this operation must either be the job owner (as
     494        determined in the Create-Job operation) or an operator or
     495        administrator of the Printer object (see Sections 1 and
     496        8.5). Otherwise, the IPP object MUST reject the operation and
     497        return: 'client-error-forbidden', 'client-
     498        error-not-authenticated', or 'client-error-not-authorized' as
     499        appropriate.
     500
     501        Request
     502        -------
     503
     504        Group 1: Operation Attributes
     505            REQUIRED 'attributes-charset'
     506            REQUIRED 'attributes-natural-language'
     507            REQUIRED 'job-id' (uri)
     508            OPTIONAL 'printer-uri' (uri)
     509            OPTIONAL 'requesting-user-name' (name(MAX))
     510            OPTIONAL 'document-name' (name(MAX))
     511            OPTIONAL 'compression' (type3 keyword)
     512            OPTIONAL 'document-format' (mimeMediaType)
     513            OPTIONAL 'document-natural-language' (naturalLanguage)
     514            OPTIONAL 'last-document' (boolean)
     515        Group 2: Document Content
     516           
     517        Response
     518        --------
     519
     520        Group 1: Operation Attributes
     521            OPTIONAL 'status-message' (text(255))
     522            OPTIONAL 'detailed-status-message' (text(MAX))
     523            REQUIRED 'attributes-charset'
     524            REQUIRED 'attributes-natural-language'
     525        Group 2: Unsupported Attributes
     526        Group 3: Job Object Attributes
     527            REQUIRED 'job-uri' (uri)
     528            REQUIRED 'job-id' (integer(1:MAX))
     529            REQUIRED 'job-state' (type1 enum)
     530            REQUIRED 'job-state-reasons' (1setOf type2 keyword)
     531            OPTIONAL 'job-state-message' (text(MAX))
     532            OPTIONAL 'number-of-intervening-jobs' (integer(0:MAX))
     533
     534        """
     535       
    374536        operation = request.attribute_groups[0]
    375537
    376         # requested printer uri
    377         if 'printer-uri' in operation:
    378             uri_attr = operation['printer-uri']
    379             printer_name = uri_attr.values[0].value.split("/")[-1]
    380             if uri_attr != ipp.PrinterUri(uri_attr.values[0].value):
    381                 raise ipp.errors.ClientErrorBadRequest(str(uri_attr))
    382             if printer_name != self.printer.name:
    383                 raise ipp.errors.ClientErrorAttributes(str(uri_attr), uri_attr)
    384         printer = self.printer
    385 
     538        job_id = None
     539        printer_uri = None
     540        requesting_user_name = None
     541        document_name = None
     542        compression = None
     543        document_format = None
     544        document_natural_language = None
     545        last_document = None
     546
     547        # required attributes
    386548        if 'job-id' not in operation:
    387549            raise ipp.errors.ClientErrorBadRequest("Missing 'job-id' attribute")
    388         job_id_attr = operation['job-id']
    389         job_id = job_id_attr.values[0].value
    390         if job_id_attr != ipp.JobId(job_id_attr.values[0].value):
    391             raise ipp.errors.ClientErrorBadRequest(str(job_id_attr))
    392         if job_id not in printer.jobs:
    393             raise ipp.errors.ClientErrorAttributes(str(job_id_attr))
    394         job = printer.jobs[job_id]
     550        job_id = verify_attribute(operation['job-id'], ipp.JobId)[0]
    395551
    396552        if 'last-document' not in operation:
    397553            raise ipp.errors.ClientErrorBadRequest("Missing 'last-document' attribute")
    398         last_attr = operation['last-document']
    399         last = last_attr.values[0].value
    400         if last_attr != ipp.LastDocument(last):
    401             raise ipp.errors.ClientErrorBadRequest(str(last_attr))
    402         if not last:
     554        last_document = verify_attribute(operation['last-document'], ipp.LastDocument)[0]
     555        if not last_document:
    403556            raise ipp.errors.ServerErrorMultipleJobsNotSupported
    404557
    405         printer.send_document(job_id, request.data)
    406         attrs = job.get_job_attributes()
     558        # optional attributes
     559        if 'printer-uri' in operation:
     560            printer_uri = verify_attribute(operation['printer-uri'], ipp.PrinterUri)[0]
     561            if printer_uri not in self.printer.uris:
     562                raise ipp.errors.ClientErrorAttributes(
     563                    str(operation['printer-uri']), operation['printer-uri'])
     564
     565        if 'requesting-user-name' in operation:
     566            user_name = verify_attribute(
     567                operation['requesting-user-name'], ipp.RequestingUserName)[0]
     568
     569        if 'document-name' in operation:
     570            document_name = verify_attribute(
     571                operation['document-name'], ipp.DocumentName)[0]
     572
     573        if 'compression' in operation:
     574            compression = verify_attribute(
     575                operation['compression'], ipp.Compression)[0]
     576
     577        if 'document-format' in operation:
     578            document_format = verify_attribute(
     579                operation['document-format'], ipp.DocumentFormat)[0]
     580
     581        if 'document-natural-language' in operation:
     582            document_natural_language = verify_attribute(
     583                operation['document_natural_language'],
     584                ipp.DocumentNaturalLanguage)[0]
     585
     586        job = self.printer.get_job(job_id)
     587        job.send_document(
     588            request.data,
     589            requesting_user_name=user_name,
     590            document_name=document_name,
     591            compression=compression,
     592            document_format=document_format,
     593            document_natural_language=document_natural_language,
     594            last_document=last_document)
     595
    407596        response.attribute_groups.append(ipp.AttributeGroup(
    408             ipp.AttributeTags.JOB, attrs))
     597            ipp.AttributeTags.JOB, job.get_job_attributes()))
    409598
    410599    @handler_for(ipp.OperationCodes.SEND_URI)
     
    414603    @handler_for(ipp.OperationCodes.GET_JOB_ATTRIBUTES)
    415604    def get_job_attributes(self, request, response):
     605        """3.3.4 Get-Job-Attributes Operation
     606
     607        This REQUIRED operation allows a client to request the values
     608        of attributes of a Job object and it is almost identical to
     609        the Get- Printer-Attributes operation (see section 3.2.5). The
     610        only differences are that the operation is directed at a Job
     611        object rather than a Printer object, there is no
     612        'document-format' operation attribute used when querying a Job
     613        object, and the returned attribute group is a set of Job
     614        object attributes rather than a set of Printer object
     615        attributes.
     616
     617        For Jobs, the possible names of attribute groups are:
     618          - 'job-template': the subset of the Job Template attributes
     619            that apply to a Job object (the first column of the table
     620            in Section 4.2) that the implementation supports for Job
     621            objects.
     622          - 'job-description': the subset of the Job Description
     623            attributes specified in Section 4.3 that the
     624            implementation supports for Job objects.
     625          - 'all': the special group 'all' that includes all
     626            attributes that the implementation supports for Job
     627            objects.
     628
     629        Since a client MAY request specific attributes or named
     630        groups, there is a potential that there is some overlap. For
     631        example, if a client requests, 'job-name' and
     632        'job-description', the client is actually requesting the
     633        'job-name' attribute once by naming it explicitly, and once by
     634        inclusion in the 'job-description' group. In such cases, the
     635        Printer object NEED NOT return the attribute only once in the
     636        response even if it is requested multiple times. The client
     637        SHOULD NOT request the same attribute in multiple ways.
     638
     639        It is NOT REQUIRED that a Job object support all attributes
     640        belonging to a group (since some attributes are
     641        OPTIONAL). However it is REQUIRED that each Job object support
     642        all these group names.
     643
     644        Request
     645        -------
     646
     647        Group 1: Operation Attributes
     648            REQUIRED 'attributes-charset'
     649            REQUIRED 'attributes-natural-language'
     650            REQUIRED 'job-id' (uri)
     651            OPTIONAL 'printer-uri' (uri)
     652            OPTIONAL 'requesting-user-name' (name(MAX))
     653            OPTIONAL 'requested-attributes' (1setOf keyword)
     654           
     655        Response
     656        --------
     657
     658        Group 1: Operation Attributes
     659            OPTIONAL 'status-message' (text(255))
     660            OPTIONAL 'detailed-status-message' (text(MAX))
     661            REQUIRED 'attributes-charset'
     662            REQUIRED 'attributes-natural-language'
     663        Group 2: Unsupported Attributes
     664        Group 3: Job Object Attributes
     665
     666        """
     667       
    416668        operation = request.attribute_groups[0]
    417669
    418         # requested printer uri
    419         if 'printer-uri' not in operation:
    420             raise ipp.errors.ClientErrorBadRequest("Missing 'printer-uri' attribute")
    421         uri_attr = operation['printer-uri']
    422         printer_name = uri_attr.values[0].value.split("/")[-1]
    423         if uri_attr != ipp.PrinterUri(uri_attr.values[0].value):
    424             raise ipp.errors.ClientErrorBadRequest(str(uri_attr))
    425         if printer_name != self.printer.name:
    426             raise ipp.errors.ClientErrorAttributes(str(uri_attr), uri_attr)
    427         printer = self.printer
    428 
     670        job_id = None
     671        printer_uri = None
     672        requesting_user_name = None
     673        requested_attributes = None
     674
     675        # required attributes
    429676        if 'job-id' not in operation:
    430677            raise ipp.errors.ClientErrorBadRequest("Missing 'job-id' attribute")
    431         job_id_attr = operation['job-id']
    432         job_id = job_id_attr.values[0].value
    433         if job_id_attr != ipp.JobId(job_id_attr.values[0].value):
    434             raise ipp.errors.ClientErrorBadRequest(str(job_id_attr))
    435         if job_id not in printer.jobs:
    436             raise ipp.errors.ClientErrorAttributes(str(job_id_attr))
    437         job = printer.get_job(job_id)
     678        job_id = verify_attribute(operation['job-id'], ipp.JobId)[0]
     679
     680        # optional attributes
     681        if 'printer-uri' in operation:
     682            printer_uri = verify_attribute(operation['printer-uri'], ipp.PrinterUri)[0]
     683            if printer_uri not in self.printer.uris:
     684                raise ipp.errors.ClientErrorAttributes(
     685                    str(operation['printer-uri']), operation['printer-uri'])
     686
     687        # optional attributes
     688        if 'requesting-user-name' in operation:
     689            user_name = verify_attribute(
     690                operation['requesting-user-name'], ipp.RequestingUserName)[0]
     691           
     692        if 'requested-attributes' in operation:
     693            requested_attributes = verify_attribute(
     694                operation['requested-attributes'], ipp.RequestedAttributes, length=None)
    438695
    439696        # get the job attributes and add them to the response
    440         attrs = job.get_job_attributes(operation)
     697        job = self.printer.get_job(job_id)
     698        attrs = job.get_job_attributes(requested_attributes=requested_attributes)
    441699        response.attribute_groups.append(ipp.AttributeGroup(
    442700            ipp.AttributeTags.JOB, attrs))
     
    487745
    488746        operation = request.attribute_groups[0]
    489         printer = self.printer
     747        requested_attributes = None
     748       
     749        if 'requested-attributes' in operation:
     750            requested_attributes = verify_attribute(
     751                operation['requested-attributes'], ipp.RequestedAttributes, length=None)
    490752
    491753        # get attributes from the printer and add to response
     754        attrs = self.printer.get_printer_attributes(
     755            requested_attributes=requested_attributes)
    492756        response.attribute_groups.append(ipp.AttributeGroup(
    493             ipp.AttributeTags.PRINTER, printer.get_printer_attributes(operation)))
     757            ipp.AttributeTags.PRINTER, attrs))
    494758
    495759    @handler_for(ipp.OperationCodes.CUPS_GET_PRINTERS)
     
    504768        """
    505769
    506         operation = request.attribute_groups[0]
    507 
    508770        # get attributes from the printer and add to response
    509771        response.attribute_groups.append(ipp.AttributeGroup(
    510             ipp.AttributeTags.PRINTER, self.printer.get_printer_attributes(operation)))
     772            ipp.AttributeTags.PRINTER, self.printer.get_printer_attributes()))
    511773
    512774    @handler_for(ipp.OperationCodes.CUPS_GET_CLASSES)
Note: See TracChangeset for help on using the changeset viewer.