1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229
|
#!/usr/bin/env python
#
# Copyright (c) 2001 Bizar Software Pty Ltd (http://www.bizarsoftware.com.au/)
# This module is free software, and you may redistribute it and/or modify
# under the same terms as Python, so long as this copyright message and
# disclaimer are retained in their original form.
#
# IN NO EVENT SHALL BIZAR SOFTWARE PTY LTD BE LIABLE TO ANY PARTY FOR
# DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING
# OUT OF THE USE OF THIS CODE, EVEN IF THE AUTHOR HAS BEEN ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.
#
# BIZAR SOFTWARE PTY LTD SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
# BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
# FOR A PARTICULAR PURPOSE. THE CODE PROVIDED HEREUNDER IS ON AN "AS IS"
# BASIS, AND THERE IS NO OBLIGATION WHATSOEVER TO PROVIDE MAINTENANCE,
# SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
#
# $Id$
# python version check
from roundup import version_check
from roundup.i18n import _
import sys, time
#
## Configuration
#
# Configuration can also be provided through the OS environment (or via
# the Apache "SetEnv" configuration directive). If the variables
# documented below are set, they _override_ any configuation defaults
# given in this file.
# TRACKER_HOMES is a list of trackers, in the form
# "NAME=DIR<sep>NAME2=DIR2<sep>...", where <sep> is the directory path
# separator (";" on Windows, ":" on Unix).
# Make sure the NAME part doesn't include any url-unsafe characters like
# spaces, as these confuse the cookie handling in browsers like IE.
# ROUNDUP_LOG is the name of the logfile; if it's empty or does not exist,
# logging is turned off (unless you changed the default below).
# DEBUG_TO_CLIENT specifies whether debugging goes to the HTTP server (via
# stderr) or to the web client (via cgitb).
DEBUG_TO_CLIENT = False
# This indicates where the Roundup tracker lives
TRACKER_HOMES = {
# 'example': '/path/to/example',
}
# Where to log debugging information to. Use an instance of DevNull if you
# don't want to log anywhere.
class DevNull:
def write(self, info):
pass
def close(self):
pass
def flush(self):
pass
#LOG = open('/var/log/roundup.cgi.log', 'a')
LOG = DevNull()
#
## end configuration
#
#
# Set up the error handler
#
try:
import traceback, StringIO, cgi
from roundup.cgi import cgitb
except:
print "Content-Type: text/plain\n"
print _("Failed to import cgitb!\n\n")
s = StringIO.StringIO()
traceback.print_exc(None, s)
print s.getvalue()
#
# Check environment for config items
#
def checkconfig():
import os, string
global TRACKER_HOMES, LOG
# see if there's an environment var. ROUNDUP_INSTANCE_HOMES is the
# old name for it.
if os.environ.has_key('ROUNDUP_INSTANCE_HOMES'):
homes = os.environ.get('ROUNDUP_INSTANCE_HOMES')
else:
homes = os.environ.get('TRACKER_HOMES', '')
if homes:
TRACKER_HOMES = {}
for home in string.split(homes, os.pathsep):
try:
name, dir = string.split(home, '=', 1)
except ValueError:
# ignore invalid definitions
continue
if name and dir:
TRACKER_HOMES[name] = dir
logname = os.environ.get('ROUNDUP_LOG', '')
if logname:
LOG = open(logname, 'a')
# ROUNDUP_DEBUG is checked directly in "roundup.cgi.client"
#
# Provide interface to CGI HTTP response handling
#
class RequestWrapper:
'''Used to make the CGI server look like a BaseHTTPRequestHandler
'''
def __init__(self, wfile):
self.wfile = wfile
def write(self, data):
self.wfile.write(data)
def send_response(self, code):
self.write('Status: %s\r\n'%code)
def send_header(self, keyword, value):
self.write("%s: %s\r\n" % (keyword, value))
def end_headers(self):
self.write("\r\n")
#
# Main CGI handler
#
def main(out, err):
import os, string
import roundup.instance
path = string.split(os.environ.get('PATH_INFO', '/'), '/')
request = RequestWrapper(out)
request.path = os.environ.get('PATH_INFO', '/')
tracker = path[1]
os.environ['TRACKER_NAME'] = tracker
os.environ['PATH_INFO'] = string.join(path[2:], '/')
if TRACKER_HOMES.has_key(tracker):
# redirect if we need a trailing '/'
if len(path) == 2:
request.send_response(301)
# redirect
if os.environ.get('HTTPS', '') == 'on':
protocol = 'https'
else:
protocol = 'http'
absolute_url = '%s://%s%s/'%(protocol, os.environ['HTTP_HOST'],
os.environ.get('REQUEST_URI', ''))
request.send_header('Location', absolute_url)
request.end_headers()
out.write('Moved Permanently')
else:
tracker_home = TRACKER_HOMES[tracker]
tracker = roundup.instance.open(tracker_home)
import roundup.cgi.client
if hasattr(tracker, 'Client'):
client = tracker.Client(tracker, request, os.environ)
else:
client = roundup.cgi.client.Client(tracker, request, os.environ)
try:
client.main()
except roundup.cgi.client.Unauthorised:
request.send_response(403)
request.send_header('Content-Type', 'text/html')
request.end_headers()
out.write('Unauthorised')
except roundup.cgi.client.NotFound:
request.send_response(404)
request.send_header('Content-Type', 'text/html')
request.end_headers()
out.write('Not found: %s'%client.path)
else:
import urllib
request.send_response(200)
request.send_header('Content-Type', 'text/html')
request.end_headers()
w = request.write
w(_('<html><head><title>Roundup trackers index</title></head>\n'))
w(_('<body><h1>Roundup trackers index</h1><ol>\n'))
homes = TRACKER_HOMES.keys()
homes.sort()
for tracker in homes:
w(_('<li><a href="%(tracker_url)s/index">%(tracker_name)s</a>\n')%{
'tracker_url': os.environ['SCRIPT_NAME']+'/'+
urllib.quote(tracker),
'tracker_name': cgi.escape(tracker)})
w(_('</ol></body></html>'))
#
# Now do the actual CGI handling
#
out, err = sys.stdout, sys.stderr
try:
# force input/output to binary (important for file up/downloads)
if sys.platform == "win32":
import os, msvcrt
msvcrt.setmode(sys.stdin.fileno(), os.O_BINARY)
msvcrt.setmode(sys.stdout.fileno(), os.O_BINARY)
checkconfig()
sys.stdout = sys.stderr = LOG
main(out, err)
except SystemExit:
pass
except:
sys.stdout, sys.stderr = out, err
out.write('Content-Type: text/html\n\n')
if DEBUG_TO_CLIENT:
cgitb.handler()
else:
out.write(cgitb.breaker())
ts = time.ctime()
out.write('''<p>%s: An error occurred. Please check
the server log for more infomation.</p>'''%ts)
print >> sys.stderr, 'EXCEPTION AT', ts
traceback.print_exc(0, sys.stderr)
sys.stdout.flush()
sys.stdout, sys.stderr = out, err
LOG.close()
# vim: set filetype=python ts=4 sw=4 et si
|