Mercurial > p > roundup > code
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 |
| 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 |
