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