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
Line 
1#!/usr/bin/env python
2
3# Adapted from the Quickprint IPP server code (http://quickprint.mit.edu)
4# Modifications and additions written by Jessica Hamrick (jhamrick@mit.edu)
5
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
11
12import os, sys
13import cgi, cgitb
14import logging
15import MySQLdb
16import ipplib
17
18from ipplib import IPPRequest
19from tempfile import mkstemp
20from shutil import move
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
37
38authfail = False
39try:
40    printer_uri = 'http://%s%s' % (os.environ['SERVER_NAME'], os.environ['REQUEST_URI'])
41except:
42    pass
43
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
93        # f = file('/tmp/gutenbach/ipp/printer2.log','a')
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"""
109        (fno, fname) = mkstemp(dir='/tmp/gutenbach/ipp')
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.