annotate server.py @ 4:b10f8834cce4

modified to use localconfig.py (if it exists) and to make the various options (e.g. paths) based on ROUNDUP_HOME &c.
author Anthony Baxter <anthonybaxter@users.sourceforge.net>
date Thu, 19 Jul 2001 05:46:47 +0000
parents 5e92642cd1f8
children 72a0ba086b3e
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
0
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
1 #!/usr/bin/python
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
2 """ HTTP Server that serves roundup.
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
3
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
4 Stolen from CGIHTTPServer
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
5
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
6 """
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
7 import sys
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
8 if int(sys.version[0]) < 2:
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
9 print "Content-Type: text/plain\n"
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
10 print "Roundup requires Python 2.0 or newer."
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
11
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
12 __version__ = "0.1"
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
13
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
14 __all__ = ["CGIHTTPRequestHandler"]
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
15
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
16 import os, urllib, StringIO, traceback, cgi, binascii
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
17 import BaseHTTPServer
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
18 import SimpleHTTPServer
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
19 import date, hyperdb, template, roundupdb, roundup_cgi
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
20 import cgitb
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
21
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
22 class RoundupRequestHandler(SimpleHTTPServer.SimpleHTTPRequestHandler):
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
23 def send_head(self):
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
24 """Version of send_head that support CGI scripts"""
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
25 return self.run_cgi()
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
26
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
27 def run_cgi(self):
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
28 """Execute a CGI script."""
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
29 rest = self.path
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
30 i = rest.rfind('?')
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
31 if i >= 0:
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
32 rest, query = rest[:i], rest[i+1:]
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
33 else:
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
34 query = ''
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
35
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
36 # Set up the CGI environment
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
37 env = {}
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
38 env['REQUEST_METHOD'] = self.command
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
39 env['PATH_INFO'] = urllib.unquote(rest)
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
40 if query:
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
41 env['QUERY_STRING'] = query
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
42 host = self.address_string()
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
43 if self.headers.typeheader is None:
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
44 env['CONTENT_TYPE'] = self.headers.type
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
45 else:
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
46 env['CONTENT_TYPE'] = self.headers.typeheader
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
47 length = self.headers.getheader('content-length')
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
48 if length:
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
49 env['CONTENT_LENGTH'] = length
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
50 co = filter(None, self.headers.getheaders('cookie'))
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
51 if co:
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
52 env['HTTP_COOKIE'] = ', '.join(co)
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
53 env['SCRIPT_NAME'] = ''
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
54 env['SERVER_NAME'] = self.server.server_name
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
55 env['SERVER_PORT'] = str(self.server.server_port)
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
56
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
57 decoded_query = query.replace('+', ' ')
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
58
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
59 # if root, setuid to nobody
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
60 if not os.getuid():
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
61 nobody = nobody_uid()
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
62 os.setuid(nobody)
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
63
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
64 # TODO check for file timestamp changes
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
65 reload(date)
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
66 reload(hyperdb)
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
67 reload(roundupdb)
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
68 reload(template)
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
69 reload(roundup_cgi)
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
70
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
71 # initialise the roundupdb, check for auth
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
72 db = roundupdb.openDB('db', 'admin')
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
73 message = 'Unauthorised'
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
74 auth = self.headers.getheader('authorization')
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
75 if auth:
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
76 l = binascii.a2b_base64(auth.split(' ')[1]).split(':')
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
77 user = l[0]
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
78 password = None
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
79 if len(l) > 1:
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
80 password = l[1]
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
81 try:
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
82 uid = db.user.lookup(user)
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
83 except KeyError:
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
84 auth = None
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
85 message = 'Username not recognised'
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
86 else:
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
87 if password != db.user.get(uid, 'password'):
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
88 message = 'Incorrect password'
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
89 auth = None
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
90 db.close()
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
91 del db
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
92 if not auth:
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
93 self.send_response(401)
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
94 self.send_header('Content-Type', 'text/html')
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
95 self.send_header('WWW-Authenticate', 'basic realm="Roundup"')
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
96 self.end_headers()
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
97 self.wfile.write(message)
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
98 return
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
99
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
100 self.send_response(200, "Script output follows")
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
101
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
102 # do the roundup thang
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
103 save_stdin = sys.stdin
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
104 try:
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
105 sys.stdin = self.rfile
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
106 client = roundup_cgi.Client(self.wfile, env, user)
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
107 client.main()
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
108 except roundup_cgi.Unauthorised:
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
109 self.wfile.write('Content-Type: text/html\n')
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
110 self.wfile.write('Status: 403\n')
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
111 self.wfile.write('Unauthorised')
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
112 except:
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
113 try:
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
114 reload(cgitb)
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
115 self.wfile.write(cgitb.breaker())
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
116 self.wfile.write(cgitb.html())
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
117 except:
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
118 self.wfile.write("Content-Type: text/html\n\n")
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
119 self.wfile.write("<pre>")
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
120 s = StringIO.StringIO()
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
121 traceback.print_exc(None, s)
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
122 self.wfile.write(cgi.escape(s.getvalue()))
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
123 self.wfile.write("</pre>\n")
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
124 sys.stdin = save_stdin
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
125 do_POST = run_cgi
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
126
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
127
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
128 nobody = None
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
129
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
130 def nobody_uid():
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
131 """Internal routine to get nobody's uid"""
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
132 global nobody
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
133 if nobody:
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
134 return nobody
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
135 try:
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
136 import pwd
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
137 except ImportError:
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
138 return -1
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
139 try:
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
140 nobody = pwd.getpwnam('nobody')[2]
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
141 except KeyError:
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
142 nobody = 1 + max(map(lambda x: x[2], pwd.getpwall()))
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
143 return nobody
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
144
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
145 if __name__ == '__main__':
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
146 address = ('dirk.adroit', 9080)
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
147 httpd = BaseHTTPServer.HTTPServer(address, RoundupRequestHandler)
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
148 print 'Roundup server started on', address
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
149 httpd.serve_forever()
5e92642cd1f8 Initial import of code
Richard Jones <richard@users.sourceforge.net>
parents:
diff changeset
150

Roundup Issue Tracker: http://roundup-tracker.org/