source: server/lib/gutenbach/server/requests.py @ ef8df33

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

Move more ipp-specific code into ipp/operations from server/requests; Fix more bugs

  • Property mode set to 100644
File size: 8.9 KB
Line 
1from gutenbach.server.printer import GutenbachPrinter
2import gutenbach.ipp as ipp
3import gutenbach.ipp.constants as const
4import logging
5
6# initialize logger
7logger = logging.getLogger(__name__)
8
9def handler_for(operation):
10    """A decorator method to mark a function with the operation id
11    that it handles.  This value will be stored in
12    'func.ipp_operation'.
13
14    """
15   
16    def f(func):
17        func.ipp_operation = operation
18        return func
19    return f
20
21class GutenbachRequestHandler(object):
22
23    def __init__(self):
24        self.printers = {
25            "test": GutenbachPrinter(name="test")
26            }
27        self.default = "test"
28   
29    def handle(self, request):
30        # look up the handler
31        handler = None
32        handler_name = None
33        for d in dir(self):
34            if getattr(getattr(self, d), "ipp_operation", None) == request.operation_id:
35                handler_name = d
36                break
37        # we couldn't find a handler, so default to unknown operation
38        if handler_name is None:
39            handler_name = "unknown_operation"
40        # call the handler
41        handler = getattr(self, handler_name)
42        logger.info("Handling request of type '%s'" % handler_name)
43        response = handler(request)
44        return response
45
46    def unknown_operation(self, request):
47        logger.warning("Received unknown operation 0x%x" % request.operation_id)
48        response = ipp.ops.make_empty_response(request)
49        response.operation_id = const.StatusCodes.OPERATION_NOT_SUPPORTED
50        return response
51       
52    ##### Printer Commands
53
54    def print_job(self, request):
55        pass
56
57    def validate_job(self, request):
58        pass
59
60    @handler_for(const.Operations.GET_JOBS)
61    def get_jobs(self, request):
62        """RFC 2911: 3.2.6 Get-Jobs Operation
63       
64        This REQUIRED operation allows a client to retrieve the list
65        of Job objects belonging to the target Printer object. The
66        client may also supply a list of Job attribute names and/or
67        attribute group names. A group of Job object attributes will
68        be returned for each Job object that is returned.
69
70        This operation is similar to the Get-Job-Attributes operation,
71        except that this Get-Jobs operation returns attributes from
72        possibly more than one object.
73
74        """
75       
76        req_dict = ipp.ops.verify_get_jobs_request(request)
77        printer_name = req_dict['printer-uri']
78        if printer_name not in self.printers:
79            raise ipp.errors.Attributes(
80                "Invalid printer uri: %s" % printer_name,
81                [request.attribute_groups[0].attributes[2]])
82
83        # Each job will append a new job attribute group.
84        jobs = [job.get_job_attributes(request) for job in \
85                self.printers[printer_name].get_jobs()]
86        response = ipp.ops.make_get_jobs_response(jobs, request)
87        return response
88
89    def print_uri(self, request):
90        pass
91
92    def create_job(self, request):
93        pass
94
95    def pause_printer(self, request):
96        pass
97
98    def resume_printer(self, request):
99        pass
100
101    @handler_for(const.Operations.GET_PRINTER_ATTRIBUTES)
102    def get_printer_attributes(self, request):
103        """RFC 2911: 3.2.5 Get-Printer-Attributes Operation
104
105        This REQUIRED operation allows a client to request the values
106        of the attributes of a Printer object.
107       
108        In the request, the client supplies the set of Printer
109        attribute names and/or attribute group names in which the
110        requester is interested. In the response, the Printer object
111        returns a corresponding attribute set with the appropriate
112        attribute values filled in.
113
114        For Printer objects, the possible names of attribute groups are:
115       
116        - 'job-template': the subset of the Job Template attributes
117          that apply to a Printer object (the last two columns of the
118          table in Section 4.2) that the implementation supports for
119          Printer objects.
120
121        - 'printer-description': the subset of the attributes
122          specified in Section 4.4 that the implementation supports
123          for Printer objects.
124
125        - 'all': the special group 'all' that includes all attributes
126          that the implementation supports for Printer objects.
127       
128        Since a client MAY request specific attributes or named
129        groups, there is a potential that there is some overlap. For
130        example, if a client requests, 'printer-name' and 'all', the
131        client is actually requesting the 'printer-name' attribute
132        twice: once by naming it explicitly, and once by inclusion in
133        the 'all' group. In such cases, the Printer object NEED NOT
134        return each attribute only once in the response even if it is
135        requested multiple times. The client SHOULD NOT request the
136        same attribute in multiple ways.
137
138        It is NOT REQUIRED that a Printer object support all
139        attributes belonging to a group (since some attributes are
140        OPTIONAL). However, it is REQUIRED that each Printer object
141        support all group names.
142
143        """
144
145        # this is just like cups_get_default, except the printer name
146        # is given
147        req_dict = ipp.ops.verify_get_printer_attributes_request(request)
148        printer_name = req_dict['printer-uri']
149        if printer_name not in self.printers:
150            raise ipp.errors.Attributes(
151                "Invalid printer uri: %s" % printer_name,
152                [request.attribute_groups[0].attributes[2]])
153       
154        response = ipp.ops.make_get_printer_attributes_response(
155            self.printers[printer_name].get_printer_attributes(request), request)
156        return response
157
158    def set_printer_attributes(self, request):
159        pass
160
161    ##### Job Commands
162
163    def cancel_job(self, request):
164        pass
165
166    def send_document(self, request):
167        pass
168
169    def send_uri(self, request):
170        pass
171
172    def get_job_attributes(self, request):
173        req_dict = ipp.ops.verify_get_jobs_request(request)
174        printer_name = req_dict['printer-uri']
175        job_id = req_dict['job-id']
176       
177        if printer_name not in self.printers:
178            raise ipp.errors.Attributes(
179                "Invalid printer uri: %s" % printer_name,
180                [request.attribute_groups[0].attributes[2]])
181        try:
182            job = self.printers[printer_name].get_job(job_id)
183        except InvalidJobException:
184            raise ipp.errors.Attributes(
185                "Invalid job id: %d" % job_id,
186                [request.attribute_groups[0].attributes[2]]) # XXX: this is wrong
187
188        # Each job will append a new job attribute group.
189        # XXX: we need to honor the things that the request actually asks for
190        response = ipp.ops.make_get_job_attributes_response(
191            job.get_job_attributes(request), request)
192        return response
193
194    def set_job_attributes(self, request):
195        pass
196
197    def cups_get_document(self, request):
198        pass
199
200    def restart_job(self, request):
201        pass
202
203    def promote_job(self, request):
204        pass
205
206    ##### CUPS Specific Commands
207
208    @handler_for(const.Operations.CUPS_GET_DEFAULT)
209    def cups_get_default(self, request):
210        """The CUPS-Get-Default operation (0x4001) returns the default
211        printer URI and attributes.
212
213        (Source: http://www.cups.org/documentation.php/spec-ipp.html#CUPS_GET_DEFAULT )
214
215        """
216
217        req_dict = ipp.ops.verify_cups_get_default_request(request)
218        response = ipp.ops.make_get_printer_attributes_response(
219            self.printers[self.default].get_printer_attributes(request), request)
220        return response
221
222    @handler_for(const.Operations.CUPS_GET_PRINTERS)
223    def cups_get_printers(self, request):
224        """The CUPS-Get-Printers operation (0x4002) returns the
225        printer attributes for every printer known to the system. This
226        may include printers that are not served directly by the
227        server.
228
229        (Source: http://www.cups.org/documentation.php/spec-ipp.html#CUPS_GET_PRINTERS )
230           
231        """
232
233        req_dict = ipp.ops.verify_cups_get_printers_request(request)
234        attrs = [self.printers[printer].get_printer_attributes(request) \
235                 for printer in self.printers]
236        response = ipp.ops.make_cups_get_printers_response(attrs, request)
237        return response
238
239    @handler_for(const.Operations.CUPS_GET_CLASSES)
240    def cups_get_classes(self, request):
241        """The CUPS-Get-Classes operation (0x4005) returns the printer
242        attributes for every printer class known to the system. This
243        may include printer classes that are not served directly by
244        the server.
245       
246        (Source: http://www.cups.org/documentation.php/spec-ipp.html#CUPS_GET_CLASSES )
247
248        """
249
250        req_dict = ipp.ops.verify_cups_get_classes_request(request)
251        response = ipp.ops.make_cups_get_classes_response(request)
252        return response
Note: See TracBrowser for help on using the repository browser.