Code

Uniformly use """...""" instead of '''...''' for comments.
[roundup.git] / roundup / cgi / apache.py
1 # mod_python interface for Roundup Issue Tracker
2 #
3 # This module is free software, you may redistribute it
4 # and/or modify under the same terms as Python.
5 #
6 # This module provides Roundup Web User Interface
7 # using mod_python Apache module.  Initially written
8 # with python 2.3.3, mod_python 3.1.3, roundup 0.7.0.
9 #
10 # This module operates with only one tracker
11 # and must be placed in the tracker directory.
12 #
13 # History (most recent first):
14 # 11-jul-2004 [als] added 'TrackerLanguage' option;
15 #                   pass message translator to the tracker client instance
16 # 04-jul-2004 [als] tracker lookup moved from module global to request handler;
17 #                   use PythonOption TrackerHome (configured in apache)
18 #                   to open the tracker
19 # 06-may-2004 [als] use cgi.FieldStorage from Python library
20 #                   instead of mod_python FieldStorage
21 # 29-apr-2004 [als] created
23 __version__ = "$Revision: 1.6 $"[11:-2]
24 __date__ = "$Date: 2006-11-09 00:36:21 $"[7:-2]
26 import cgi
27 import os
29 from mod_python import apache
31 import roundup.instance
32 from roundup.cgi import TranslationService
34 class Headers(dict):
36     """HTTP headers wrapper"""
38     def __init__(self, headers):
39         """Initialize with `apache.table`"""
40         super(Headers, self).__init__(headers)
41         self.getheader = self.get
43 class Request(object):
45     """`apache.Request` object wrapper providing roundup client interface"""
47     def __init__(self, request):
48         """Initialize with `apache.Request` object"""
49         self._req = request
50         # .headers.getheader()
51         self.headers = Headers(request.headers_in)
52         # .wfile.write()
53         self.wfile = self._req
55     def start_response(self, headers, response):
56         self.send_response(response)
57         for key, value in headers:
58             self.send_header(key, value)
59         self.end_headers()
61     def send_response(self, response_code):
62         """Set HTTP response code"""
63         self._req.status = response_code
65     def send_header(self, name, value):
66         """Set output header"""
67         # value may be an instance of roundup.cgi.exceptions.HTTPException
68         value = str(value)
69         # XXX default content_type is "text/plain",
70         #   and ain't overrided by "Content-Type" header
71         if name == "Content-Type":
72             self._req.content_type = value
73         else:
74             self._req.headers_out.add(name, value)
76     def end_headers(self):
77         """NOOP. There aint no such thing as 'end_headers' in mod_python"""
78         pass
80  
81     def sendfile(self, filename, offset = 0, len = -1):
82         """Send 'filename' to the user."""
84         return self._req.sendfile(filename, offset, len)
87 def handler(req):
88     """HTTP request handler"""
89     _options = req.get_options()
90     _home = _options.get("TrackerHome")
91     _lang = _options.get("TrackerLanguage")
92     _timing = _options.get("TrackerTiming", "no")
93     if _timing.lower() in ("no", "false"):
94         _timing = ""
95     _debug = _options.get("TrackerDebug", "no")
96     _debug = _debug.lower() not in ("no", "false")
97     if not (_home and os.path.isdir(_home)):
98         apache.log_error(
99             "PythonOption TrackerHome missing or invalid for %(uri)s"
100             % {'uri': req.uri})
101         return apache.HTTP_INTERNAL_SERVER_ERROR
102     _tracker = roundup.instance.open(_home, not _debug)
103     # create environment
104     # Note: cookies are read from HTTP variables, so we need all HTTP vars
105     req.add_common_vars()
106     _env = dict(req.subprocess_env)
107     # XXX classname must be the first item in PATH_INFO.  roundup.cgi does:
108     #       path = string.split(os.environ.get('PATH_INFO', '/'), '/')
109     #       os.environ['PATH_INFO'] = string.join(path[2:], '/')
110     #   we just remove the first character ('/')
111     _env["PATH_INFO"] = req.path_info[1:]
112     if _timing:
113         _env["CGI_SHOW_TIMING"] = _timing
114     _form = cgi.FieldStorage(req, environ=_env)
115     _client = _tracker.Client(_tracker, Request(req), _env, _form,
116         translator=TranslationService.get_translation(_lang,
117             tracker_home=_home))
118     _client.main()
119     return apache.OK
121 # vim: set et sts=4 sw=4 :