1 #!/usr/bin/python
2 """ HTTP Server that serves roundup.
4 Stolen from CGIHTTPServer
6 $Id: server.py,v 1.3 2001-07-19 06:27:07 anthonybaxter Exp $
8 """
9 import sys
10 if int(sys.version[0]) < 2:
11 print "Content-Type: text/plain\n"
12 print "Roundup requires Python 2.0 or newer."
14 __version__ = "0.1"
16 __all__ = ["CGIHTTPRequestHandler"]
18 import os, urllib, StringIO, traceback, cgi, binascii
19 import BaseHTTPServer
20 import SimpleHTTPServer
21 import date, hyperdb, template, roundupdb, roundup_cgi
22 import cgitb
24 class RoundupRequestHandler(SimpleHTTPServer.SimpleHTTPRequestHandler):
25 def send_head(self):
26 """Version of send_head that support CGI scripts"""
27 return self.run_cgi()
29 def run_cgi(self):
30 """Execute a CGI script."""
31 rest = self.path
32 i = rest.rfind('?')
33 if i >= 0:
34 rest, query = rest[:i], rest[i+1:]
35 else:
36 query = ''
38 # Set up the CGI environment
39 env = {}
40 env['REQUEST_METHOD'] = self.command
41 env['PATH_INFO'] = urllib.unquote(rest)
42 if query:
43 env['QUERY_STRING'] = query
44 host = self.address_string()
45 if self.headers.typeheader is None:
46 env['CONTENT_TYPE'] = self.headers.type
47 else:
48 env['CONTENT_TYPE'] = self.headers.typeheader
49 length = self.headers.getheader('content-length')
50 if length:
51 env['CONTENT_LENGTH'] = length
52 co = filter(None, self.headers.getheaders('cookie'))
53 if co:
54 env['HTTP_COOKIE'] = ', '.join(co)
55 env['SCRIPT_NAME'] = ''
56 env['SERVER_NAME'] = self.server.server_name
57 env['SERVER_PORT'] = str(self.server.server_port)
59 decoded_query = query.replace('+', ' ')
61 # if root, setuid to nobody
62 if not os.getuid():
63 nobody = nobody_uid()
64 os.setuid(nobody)
66 # TODO check for file timestamp changes
67 reload(date)
68 reload(hyperdb)
69 reload(roundupdb)
70 reload(template)
71 reload(roundup_cgi)
73 # initialise the roundupdb, check for auth
74 db = roundupdb.openDB('db', 'admin')
75 message = 'Unauthorised'
76 auth = self.headers.getheader('authorization')
77 if auth:
78 l = binascii.a2b_base64(auth.split(' ')[1]).split(':')
79 user = l[0]
80 password = None
81 if len(l) > 1:
82 password = l[1]
83 try:
84 uid = db.user.lookup(user)
85 except KeyError:
86 auth = None
87 message = 'Username not recognised'
88 else:
89 if password != db.user.get(uid, 'password'):
90 message = 'Incorrect password'
91 auth = None
92 db.close()
93 del db
94 if not auth:
95 self.send_response(401)
96 self.send_header('Content-Type', 'text/html')
97 self.send_header('WWW-Authenticate', 'basic realm="Roundup"')
98 self.end_headers()
99 self.wfile.write(message)
100 return
102 self.send_response(200, "Script output follows")
104 # do the roundup thang
105 save_stdin = sys.stdin
106 try:
107 sys.stdin = self.rfile
108 client = roundup_cgi.Client(self.wfile, env, user)
109 client.main()
110 except roundup_cgi.Unauthorised:
111 self.wfile.write('Content-Type: text/html\n')
112 self.wfile.write('Status: 403\n')
113 self.wfile.write('Unauthorised')
114 except:
115 try:
116 reload(cgitb)
117 self.wfile.write(cgitb.breaker())
118 self.wfile.write(cgitb.html())
119 except:
120 self.wfile.write("Content-Type: text/html\n\n")
121 self.wfile.write("<pre>")
122 s = StringIO.StringIO()
123 traceback.print_exc(None, s)
124 self.wfile.write(cgi.escape(s.getvalue()))
125 self.wfile.write("</pre>\n")
126 sys.stdin = save_stdin
127 do_POST = run_cgi
130 nobody = None
132 def nobody_uid():
133 """Internal routine to get nobody's uid"""
134 global nobody
135 if nobody:
136 return nobody
137 try:
138 import pwd
139 except ImportError:
140 return -1
141 try:
142 nobody = pwd.getpwnam('nobody')[2]
143 except KeyError:
144 nobody = 1 + max(map(lambda x: x[2], pwd.getpwall()))
145 return nobody
147 if __name__ == '__main__':
148 address = ('dirk.adroit', 9080)
149 httpd = BaseHTTPServer.HTTPServer(address, RoundupRequestHandler)
150 print 'Roundup server started on', address
151 httpd.serve_forever()
153 #
154 # $Log: not supported by cvs2svn $
155 # Revision 1.2 2001/07/19 05:52:22 anthonybaxter
156 # Added CVS keywords Id and Log to all python files.
157 #
158 #