Mercurial > p > roundup > code
view frontends/roundup.cgi @ 8566:e4191aa7b402 default tip
doc: issue2551415 correct doc for change input->input_payload
in 2.5 the rest interface changed a variable name from input to
input_payload. An earlier commit changed the rest docs. This commit
adds an item for it to the upgrading 2.4.0->2.5.0 section. Also cross
reference added to the rest docs with the updated examples.
| author | John Rouillard <rouilj@ieee.org> |
|---|---|
| date | Thu, 09 Apr 2026 00:19:06 -0400 |
| parents | 646ba821f63e |
| children |
line wrap: on
line source
#!/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. import sys import time # If roundup is not on your normal path, add it here. # sys.path.append('/home/username/develop/roundup_dev') from roundup import version_check # noqa: F401 from roundup.anypy.html import html_escape from roundup.anypy.strings import StringIO, s2b from roundup.i18n import _ # ## 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 # Return timing information to the client. # Set TIMING to: # "" - Do not sent timing info to client. (Default) # "COMMENT" - Hide timing in html comment, view source to see it. # "INLINE" - Display timing at bottom of web page TIMING = "" # 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 from roundup.cgi import cgitb except ImportError: print("Content-Type: text/plain\n") print(_("Failed to import cgitb!\n\n")) s = StringIO() traceback.print_exc(None, s) print(s.getvalue()) # # Check environment for config items # def checkconfig(): import os global TRACKER_HOMES, LOG # see if there's an environment var. ROUNDUP_INSTANCE_HOMES is the # old name for it. if 'ROUNDUP_INSTANCE_HOMES' in os.environ: homes = os.environ.get('ROUNDUP_INSTANCE_HOMES') else: homes = os.environ.get('TRACKER_HOMES', '') if homes: TRACKER_HOMES = {} for home in homes.split(os.pathsep): try: name, dir_ = home.split('=', 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.rfile = sys.stdin self.wfile = wfile def write(self, data): self.wfile.write(data) def send_response(self, code): self.write(s2b('Status: %s\r\n' % code)) def send_header(self, keyword, value): self.write(s2b("%s: %s\r\n" % (keyword, value))) def end_headers(self): self.write(b"\r\n") def start_response(self, headers, response): self.send_response(response) for key, value in headers: self.send_header(key, value) self.end_headers() # # Main CGI handler # def main(out, err): import os import roundup.cgi.client import roundup.instance if TIMING: os.environ["CGI_SHOW_TIMING"] = TIMING request = RequestWrapper(out) problem_header = roundup.cgi.client.are_header_values_safe(os.environ) if problem_header: error_body = """<!DOCTYPE HTML> <html lang="en"> <head> <meta charset="utf-8"> <title>Error response</title> </head> <body> <h1>Error response</h1> <p>Error code: 400</p> <p>Message: Invalid value: %s.</p> <p>Error code explanation: 400 - The value for the header is unacceptable.</p> </body> </html> """ % problem_header request.send_response(400) request.send_header('Content-Type', 'text/html') request.send_header('Content-Length', '%s' % len(error_body)) request.end_headers() out.write(s2b(error_body)) return path = os.environ.get('PATH_INFO', '/').split('/') request.path = os.environ.get('PATH_INFO', '/') tracker = path[1] os.environ['TRACKER_NAME'] = tracker os.environ['PATH_INFO'] = '/'.join(path[2:]) if tracker in TRACKER_HOMES: # 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(b'Moved Permanently') else: tracker_home = TRACKER_HOMES[tracker] tracker = roundup.instance.open(tracker_home) 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(b'Unauthorised') except roundup.cgi.client.NotFound: request.send_response(404) request.send_header('Content-Type', 'text/html') request.end_headers() out.write(s2b('Not found: %s' % html_escape(client.path))) else: from roundup.anypy import urllib_ request.send_response(200) request.send_header('Content-Type', 'text/html') request.end_headers() w = request.write w(s2b(_('<html><head><title>Roundup trackers index</title></head>\n'))) w(s2b(_('<body><h1>Roundup trackers index</h1><ol>\n'))) homes = sorted(TRACKER_HOMES.keys()) for tracker in homes: w(s2b(_('<li><a href="%(tracker_url)s/index">%(tracker_name)s</a>\n') % { 'tracker_url': os.environ['SCRIPT_NAME'] + '/' + urllib_.quote(tracker), 'tracker_name': html_escape(tracker)})) w(s2b(_('</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 msvcrt import os msvcrt.setmode(sys.stdin.fileno(), os.O_BINARY) msvcrt.setmode(sys.stdout.fileno(), os.O_BINARY) checkconfig() sys.stdout = sys.stderr = LOG if sys.version_info[0] > 2: out_buf = out.buffer else: out_buf = out main(out_buf, 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 information.</p>''' % ts) print('EXCEPTION AT', ts, file=sys.stderr) 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
