source: server/lib/ipp.py @ efee0f1

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

Started customization, then realized that ipplib isn't supported.
Will probably write a perl ipp server instead.

  • Property mode set to 100755
File size: 6.7 KB
RevLine 
[2876403]1#!/usr/bin/env python
2
[efee0f1]3# Adapted from the Quickprint IPP server code (http://quickprint.mit.edu)
4# Modifications and additions written by Jessica Hamrick (jhamrick@mit.edu)
[2876403]5
[efee0f1]6# Notes and Todo:
7#   - make sure package creates gutenbach folder in /var/log
8#   - ok, so ipplib actually seems to be an unsupported library.
9#     Maybe want to write this in perl instead since there is
10#     Net::IPP::IPPRequest
[2876403]11
[efee0f1]12import os, sys
13import cgi, cgitb
14import logging
[2876403]15import MySQLdb
16import ipplib
17
[efee0f1]18from ipplib import IPPRequest
[2876403]19from tempfile import mkstemp
20from shutil import move
[efee0f1]21from logging import debug, info, warning, error, critical
22
23# set up logging
24LOGFILE = "/var/log/gutenbach/ipp.log"
25logging.basicConfig(filename=LOGFILE, level=logging.DEBUG)
26cgitb.enable(logdir='/var/log/gutenbach/cgi.log')
27
28# make sure a temporary folder exists
29TEMPDIR = '/tmp/gutenbach/ipp'
30try:
31    if not os.path.exists(TEMPDIR):
32        info("Creating temporay directory '%s'" % TEMPDIR)
33        os.makedirs(TEMPDIR)
34except e, Exception:
35    error("Could not create temporary directory '%s'" % TEMPDIR)
36
[2876403]37
38authfail = False
39try:
40    printer_uri = 'http://%s%s' % (os.environ['SERVER_NAME'], os.environ['REQUEST_URI'])
41except:
42    pass
[efee0f1]43
[2876403]44try:
45    argv = cgi.parse(os.environ['QUERY_STRING'])
46    webauth = argv['BASIC']
47    if type(webauth) is list:
48        webauth = webauth[0]
49    webauth = webauth.split(' ')[1]
50    if not len(webauth):
51        authfail = True
52    else:
53        (authu, authp) = webauth.decode('base64').split(':')
54        db=MySQLdb.connect(read_default_file="/mit/gutenbach/.my.cnf")
55        c = db.cursor()
56        c.execute("SELECT 1 FROM auth WHERE auser=%s AND apass=%s LIMIT 1", (authu,authp,))
57        if c.fetchone() is None:
58            authfail = True
59except Exception, e:
60    authfail = True
61
62if authfail:
63    print "Status: 401 Authorization Required"
64    print "WWW-Authenticate: Basic realm=\"Gutenbach\""
65    print "Content-type: application/ipp\n"
66    sys.exit(0)
67else:
68    AUTH = authu.lower()
69
70print "Content-type: application/ipp\n"
71
72class IPPServer(object):
73    def __init__(self):
74        pass
75    def process(self, request_in, response_out):
76        data_in = request_in.read()
77        if not len(data_in):
78            return
79        request = IPPRequest(data=data_in)
80        request.parse()
81
82        response = IPPRequest(version=request.version,
83                            operation_id=request.operation_id,
84                            request_id=request.request_id)
85        #file('/mit/gutenbach/tmp/requests/'+str(request.operation_id)).write()
86        handler = getattr(self, "_operation_%d" % request.operation_id, None)
87
88        response._operation_attributes = [[]]
89        response._operation_attributes[0] = filter( \
90            lambda x: x[0] in ('attributes-charset', 'attributes-natural-language', 'printer-uri'),
91            request._operation_attributes[0])
92
[efee0f1]93        # f = file('/tmp/gutenbach/ipp/printer2.log','a')
[2876403]94        # f.write("\n" + "*"*80 + "\n")
95        # f.write(str(request))
96        if handler is not None:
97            response.setOperationId(handler(request, response))
98            data_out = response.dump()
99            response_out.write(data_out)
100            response_test = IPPRequest(data=data_out)
101            response_test.parse()
102        #     f.write("\n" + "-"*80 + "\n")
103        #     f.write(str(response_test))
104        # f.write("\n" + "*"*80 + "\n")
105        # f.close()
106
107    def _operation_2(self, request, response):
108        """print-job response"""
[efee0f1]109        (fno, fname) = mkstemp(dir='/tmp/gutenbach/ipp')
[2876403]110        os.write(fno, request.data)
111        os.close(fno)
112        opattr = filter(lambda x: x[0] in ('job-name'),
113            request._operation_attributes[0])
114        jname = 'unknown'
115        if len(opattr) and opattr[0][0] == 'job-name':
116            jname = opattr[0][1][0][1]
117        jstat = os.stat(fname)
118        jsize = jstat.st_size
119        c = db.cursor()
120        c.execute("INSERT INTO job (juser, jname, jfile, jsize, jtype) VALUES (%s, %s, %s, %s, %s)", \
121                (AUTH, jname, fname, jsize, 'PostScript',))
122        jid = db.insert_id()
123        jfile = '/mit/gutenbach/jobs/' + AUTH + '_' + str(jid)
124        move(fname, jfile)
125        c.execute("UPDATE job SET jfile=%s, dupdated=NOW() WHERE jid=%s", \
126                (jfile, str(jid),))
127        response._job_attributes = [[ \
128            ('job-id', [('integer', jid)]), \
129            ('printer-uri', [('uri', printer_uri)]), \
130            ('job-state', [('enum', ipplib.IPP_JOB_HELD)])]]
131        return ipplib.IPP_OK
132
133    def _operation_8(self, request, response):
134        """delete-job response"""
135        opattr = filter(lambda x: x[0] in ('job-id'),
136            request._operation_attributes[0])
137        if len(opattr) and opattr[0][0] == 'job-id':
138            jid = opattr[0][1][0][1]
139            c = db.cursor()
140            c.execute("UPDATE job SET jstate = 'DEL' WHERE juser = %s AND jid = %s", \
141                (AUTH, int(jid)))
142        return ipplib.IPP_OK
143
144    def _operation_9(self, request, response):
145        """get-job-properties response"""
146        opattr = filter(lambda x: x[0] in ('job-id'),
147            request._operation_attributes[0])
148        if len(opattr) and opattr[0][0] == 'job-id':
149            jid = opattr[0][1][0][1]
150        response._job_attributes.append([ \
151            ('job-id', [('integer', jid)]), \
152        #    ('job-name', [('nameWithoutLanguage', x[1])]), \
153            ('job-originating-user-name', [('nameWithoutLanguage', AUTH)]), \
154        #    ('job-k-octets', [('integer', x[2]/1024)]), \
155            ('job-state', [('enum', ipplib.IPP_JOB_COMPLETE)])
156        ])
157        return ipplib.IPP_OK
158
159    def _operation_10(self, request, response):
160        """get-jobs response"""
161        c = db.cursor()
162        c.execute("SELECT jid, jname, jsize, jstate FROM job WHERE juser = %s AND jstate != %s ORDER BY dadded", \
163            (AUTH, 'DEL',))
164        response._job_attributes = []
165        for x in c.fetchall():
166            if x[3] == 'NEW':
167                state = ipplib.IPP_JOB_HELD
168            elif x[3] == 'DONE':
169                state = ipplib.IPP_JOB_COMPLETE
170            else:
171                state = 0
172            response._job_attributes.append([ \
173                ('job-id', [('integer', x[0])]), \
174                ('job-name', [('nameWithoutLanguage', x[1])]), \
175                ('job-originating-user-name', [('nameWithoutLanguage', AUTH)]), \
176                ('job-k-octets', [('integer', x[2]/1024)]), \
177                ('job-state', [('enum', state)])
178            ])
179        return ipplib.IPP_OK
180
181    def _operation_11(self, request, response):
182        """get-printer-attributes response"""
183        response._printer_attributes = \
184            [[('printer-name', [('nameWithoutLanguage', 'Gutenbach')])]]
185        return ipplib.IPP_OK
186
187IPPServer().process(sys.stdin,sys.stdout)
Note: See TracBrowser for help on using the repository browser.