annotate server.py @ 0:5e92642cd1f8

Initial import of code Currently version 1.0.2 but with the 1.0.3 changes as given in the CHANGES file. Is about ready for a 1.0.3 release. [[This repository is actually a lift into git made in October 2011 of code history originally kept in CVS and later in Subversion. This import marks the point at which the original private CVS moved to public CVS on SourceForge. Due to technical problems with CVS and the CVS to Subversion conversion tools, portions of the early history have somewhat garbled metadata. Here and elsewhere in this repo, comments enclosed in curly braces were added at the time of the git lift in an attempt to document the problem.]]
author Richard Jones <richard@users.sourceforge.net>
date Thu, 19 Jul 2001 02:16:19 +0000
parents
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/