source: server/lib/server.py @ 1176f8b

no-cups
Last change on this file since 1176f8b was 1176f8b, checked in by Quentin Smith <quentin@…>, 14 years ago

Enough of a skeleton is implemented to properly handle CUPS_GET_PRINTERS, CUPS_GET_CLASSES, and CUPS_GET_DEFAULT

  • Property mode set to 100755
File size: 12.2 KB
Line 
1#!/usr/bin/python
2
3import logging, BaseHTTPServer
4import time
5import ipp
6import ipp.constants as const
7from ipp.constants import Operations
8
9logging.basicConfig(level=logging.DEBUG)
10
11def handler_for(operation):
12    def f(func):
13        func.ipp_operation = operation
14        return func
15    return f
16
17class IPPRequestHandler(object):
18    def _ipp_dispatch(self, request):
19        for d in dir(self):
20            if getattr(getattr(self, d), "ipp_operation", None) == request.operation_id:
21                return getattr(self, d)
22        return self.unknown_operation
23
24    def unknown_operation(self, request, response):
25        print "Received UNKNOWN OPERATION %x" % request.operation_id
26        response.operation_id = const.StatusCodes.OPERATION_NOT_SUPPORTED
27
28class PrinterRequestHandler(IPPRequestHandler):
29    def __init__(self, name):
30        self.name = name
31
32    @handler_for(Operations.GET_PRINTER_ATTRIBUTES)
33    def get_printer_attributes(self, request, response):
34        printer_attributes = ipp.AttributeGroup(const.AttributeTags.PRINTER)
35        printer_attributes[:] = \
36            ipp.Attribute("printer-uri-supported",
37                          [ipp.Value(ipp.Tags.URI,
38                                     "ipp://localhost:8000/printers/"+self.name)]
39                          )
40        printer_attributes[:] = \
41            ipp.Attribute("uri-authentication-supported",
42                          [ipp.Value(ipp.Tags.KEYWORD,
43                                     "none")]
44                          )
45        printer_attributes[:] = \
46            ipp.Attribute("uri-security-supported",
47                          [ipp.Value(ipp.Tags.KEYWORD,
48                                     "none")]
49                          )
50        printer_attributes[:] = \
51            ipp.Attribute("printer-name",
52                          [ipp.Value(ipp.Tags.NAME_WITHOUT_LANGUAGE,
53                                     self.name)]
54                          )
55        printer_attributes[:] = \
56            ipp.Attribute("printer-state",
57                          [ipp.Value(ipp.Tags.ENUM,
58                                     const.PrinterStates.IDLE)]
59                          )
60        printer_attributes[:] = \
61            ipp.Attribute("printer-state-reasons",
62                          [ipp.Value(ipp.Tags.KEYWORD,
63                                     "none")]
64                          )
65        printer_attributes[:] = \
66            ipp.Attribute("ipp-versions-supported",
67                          [ipp.Value(ipp.Tags.KEYWORD,
68                                     "1.0"),
69                           ipp.Value(ipp.Tags.KEYWORD,
70                                     "1.1")]
71                          )
72        printer_attributes[:] = \
73            ipp.Attribute("operations-supported",
74                          [ipp.Value(ipp.Tags.ENUM,
75                                     Operations.GET_JOBS)]
76                          ) #XXX: We should query ourself for the supported operations
77        printer_attributes[:] = \
78            ipp.Attribute("charset-configured",
79                          [ipp.Value(ipp.Tags.CHARSET,
80                                     "utf-8")]
81                          )
82        printer_attributes[:] = \
83            ipp.Attribute("charset-supported",
84                          [ipp.Value(ipp.Tags.CHARSET,
85                                     "utf-8")]
86                          )
87        printer_attributes[:] = \
88            ipp.Attribute("natural-language-configured",
89                          [ipp.Value(ipp.Tags.NATURAL_LANGUAGE,
90                                     "en-us")]
91                          )
92        printer_attributes[:] = \
93            ipp.Attribute("generated-natural-language-supported",
94                          [ipp.Value(ipp.Tags.NATURAL_LANGUAGE,
95                                     "en-us")]
96                          )
97        printer_attributes[:] = \
98            ipp.Attribute("document-format-default",
99                          [ipp.Value(ipp.Tags.MIME_MEDIA_TYPE,
100                                     "application/octet-stream")]
101                          )
102        printer_attributes[:] = \
103            ipp.Attribute("document-format-supported",
104                          [ipp.Value(ipp.Tags.MIME_MEDIA_TYPE,
105                                     "application/octet-stream"),
106                           ipp.Value(ipp.Tags.MIME_MEDIA_TYPE,
107                                     "audio/mp3")]
108                          )
109        printer_attributes[:] = \
110            ipp.Attribute("printer-is-accepting-jobs",
111                          [ipp.Value(ipp.Tags.BOOLEAN,
112                                     True)]
113                          )
114        printer_attributes[:] = \
115            ipp.Attribute("queued-job-count",
116                          [ipp.Value(ipp.Tags.INTEGER,
117                                     1)]
118                          )
119        printer_attributes[:] = \
120            ipp.Attribute("pdl-override-supported",
121                          [ipp.Value(ipp.Tags.KEYWORD,
122                                     "not-attempted")]
123                          )
124        printer_attributes[:] = \
125            ipp.Attribute("printer-up-time",
126                          [ipp.Value(ipp.Tags.INTEGER,
127                                     int(time.time()))]
128                          )
129        printer_attributes[:] = \
130            ipp.Attribute("compression-supported",
131                          [ipp.Value(ipp.Tags.KEYWORD,
132                                     "none")]
133                          )
134
135        response.attribute_groups.append(printer_attributes)
136        response.operation_id = const.StatusCodes.OK
137        print "get_printer_attributes called"
138
139class RootRequestHandler(IPPRequestHandler):
140    printers = [PrinterRequestHandler(name="sipbmp3")]
141
142    @handler_for(Operations.CUPS_GET_DEFAULT)
143    def cups_get_default(self, request, response):
144        print "get_default called"
145        return self.printers[0].get_printer_attributes(request, response)
146
147    @handler_for(Operations.CUPS_GET_PRINTERS)
148    def cups_get_printers(self, request, response):
149        print "get_printers called"
150        response.operation_id = const.StatusCodes.OK
151        for p in self.printers:
152            # Each printer will append a new printer attribute group.
153            p.get_printer_attributes(request, response)
154
155    @handler_for(Operations.CUPS_GET_CLASSES)
156    def cups_get_classes(self, request, response):
157        print "get_classes called"
158        response.operation_id = const.StatusCodes.OK
159        # We have no printer classes, so nothing to return.
160
161class GutenbachIPPHandler(BaseHTTPServer.BaseHTTPRequestHandler):
162    def setup(self):
163        self.root = RootRequestHandler()
164        BaseHTTPServer.BaseHTTPRequestHandler.setup(self)
165
166    def handle_one_request(self):
167        self.raw_requestline = self.rfile.readline()
168        if not self.raw_requestline:
169            self.close_connection = 1
170            return
171        if not self.parse_request(): # An error code has been sent, just exit
172            return
173        self.handle_ipp()
174
175    def handle_ipp(self):
176        length = int(self.headers.getheader('content-length', 0))
177        request = ipp.Request(request=self.rfile,
178                              length=length)
179        print "Received request:", repr(request)
180
181        response_kwargs = {}
182        response_kwargs['version'] = request.version
183        response_kwargs['operation_id'] = const.StatusCodes.INTERNAL_ERROR
184        response_kwargs['request_id'] = request.request_id
185        response_kwargs['attribute_groups'] = [
186            ipp.AttributeGroup(const.AttributeTags.OPERATION,
187                               [ipp.Attribute('attributes-charset',
188                                              [ipp.Value(ipp.Tags.CHARSET,
189                                                         'utf-8'
190                                                         )]),
191                                ipp.Attribute('attributes-natural-language',
192                                              [ipp.Value(ipp.Tags.NATURAL_LANGUAGE,
193                                                         'en-us'
194                                                         )])
195                                ])]
196
197        response = ipp.Request(**response_kwargs)
198        handler = self.root._ipp_dispatch(request)
199        handler(request, response)
200        print "Sending response:", repr(response)
201
202        self.send_response(200, "o hai")
203        self.send_header("Content-Type", "application/ipp")
204        self.send_header("Connection", "close")
205        self.end_headers()
206        self.wfile.write(response.packed_value)
207
208    def get_jobs(self, request, response_kwargs):
209        """get-jobs response"""
210
211        job_attributes = [ipp.Attribute('job-id',
212                                       [ipp.Value(ipp.Tags.INTEGER,
213                                                 12345,
214                                                 )]),
215                          ipp.Attribute('job-name',
216                                       [ipp.Value(ipp.Tags.NAME_WITHOUT_LANGUAGE,
217                                                 'foo',
218                                                 )]),
219                          ipp.Attribute('job-originating-user-name',
220                                       [ipp.Value(ipp.Tags.NAME_WITHOUT_LANGUAGE,
221                                                 'jhamrick',
222                                                 )]),
223                          ipp.Attribute('job-k-octets',
224                                       [ipp.Value(ipp.Tags.INTEGER,
225                                                 1,
226                                                 )]),
227                          ipp.Attribute('job-state',
228                                       [ipp.Value(ipp.Tags.ENUM,
229                                                 const.JobStates.HELD,
230                                                 )]),
231                          ipp.Attribute('job-printer-uri',
232                                       [ipp.Value(ipp.Tags.URI,
233                                                 'ipp://localhost:8000/printers/foo',
234                                                 )])]
235
236
237        #req_op_attributes = request.getAttributeGroup(ipp.Tags.OPERATION_ATTRIBUTES_TAG)
238        #print req_op_attributes
239        #printer_uri = req_op_attributes[0].getAttribute('printer-uri')
240
241        op_attributes = [ipp.Attribute('attributes-charset',
242                                      [ipp.Value(ipp.Tags.CHARSET,
243                                                'utf-8',
244                                                )]),
245                         ipp.Attribute('attributes-natural-language',
246                                      [ipp.Value(ipp.Tags.NATURAL_LANGUAGE,
247                                                'en-us',
248                                                )])]
249       
250        job_attribute_group = ipp.AttributeGroup(const.AttributeTags.JOB,
251                                                 job_attributes)
252        op_attributes_group = ipp.AttributeGroup(const.AttributeTags.OPERATION,
253                                                 op_attributes)
254        response_kwargs['attribute_groups'] = [op_attributes_group,job_attribute_group]
255        response_kwargs['operation_id'] = const.StatusCodes.OK
256
257        return response_kwargs
258
259    ##### Printer Commands
260
261    def print_job(self, request):
262        pass
263
264    def validate_job(self, request):
265        pass
266
267    #def get_jobs(self, request):
268    #    pass
269
270    def print_uri(self, request):
271        pass
272
273    def create_job(self, request):
274        pass
275
276    def pause_printer(self, request):
277        pass
278
279    def resume_printer(self, request):
280        pass
281
282    def set_printer_attributes(self, request):
283        pass
284
285    ##### Job Commands
286
287    def cancel_job(self, request):
288        pass
289
290    def get_job_attributes(self, request):
291        pass
292
293    def send_document(self, request):
294        pass
295
296    def send_uri(self, request):
297        pass
298
299    def set_job_attributes(self, request):
300        pass
301
302    def cups_get_document(self, request):
303        pass
304
305    def restart_job(self, request):
306        pass
307
308    def promote_job(self, request):
309        pass
310
311if __name__ == '__main__':
312    server_address = ('', 8000)
313    httpd = BaseHTTPServer.HTTPServer(server_address, GutenbachIPPHandler)
314    httpd.serve_forever()
Note: See TracBrowser for help on using the repository browser.