diff options
| author | tkikuchi | 2006-11-13 12:29:34 +0000 |
|---|---|---|
| committer | tkikuchi | 2006-11-13 12:29:34 +0000 |
| commit | 367f816c741607f3b8e0846fc13abaf60374a909 (patch) | |
| tree | 544914b399ec530bfa94318aab5d0bd611b74cb9 | |
| parent | 425a8297a9987800f62cf61d47a916d026028864 (diff) | |
| download | mailman-367f816c741607f3b8e0846fc13abaf60374a909.tar.gz mailman-367f816c741607f3b8e0846fc13abaf60374a909.tar.zst mailman-367f816c741607f3b8e0846fc13abaf60374a909.zip | |
Fix environ['SCRIPT_NAME'] to match CGI spec.
Also, the now scripts can be accessed by arbitrary script base.
E.g. /listinfo can be accessed by /mailman/listinfo or /mailman/blah/listinfo
etc. etc. This is useful in testing wsgi directly without apache frontend
but we may have to limit the length or depth of prefixed script base.
| -rw-r--r-- | Mailman/Cgi/Auth.py | 2 | ||||
| -rw-r--r-- | Mailman/Cgi/wsgi_app.py | 152 | ||||
| -rw-r--r-- | Mailman/SecurityManager.py | 6 |
3 files changed, 75 insertions, 85 deletions
diff --git a/Mailman/Cgi/Auth.py b/Mailman/Cgi/Auth.py index 98e9fe49d..7954acfb2 100644 --- a/Mailman/Cgi/Auth.py +++ b/Mailman/Cgi/Auth.py @@ -38,7 +38,7 @@ def loginpage(mlist, scriptname, msg='', frontpage=False): if frontpage: actionurl = url else: - request = Utils.GetRequestURI(url) + request = Utils.GetRequestURI(url).lstrip('/') up = '../' * request.count('/') actionurl = up + request if msg: diff --git a/Mailman/Cgi/wsgi_app.py b/Mailman/Cgi/wsgi_app.py index 8b74fbd84..172a46b86 100644 --- a/Mailman/Cgi/wsgi_app.py +++ b/Mailman/Cgi/wsgi_app.py @@ -48,8 +48,6 @@ CRLF2 = '\r\n\r\n' dotonly = re.compile(r'^\.+$') -SCRIPT_BASE = urlparse(config.DEFAULT_URL_PATTERN)[2] - # WSGI to CGI wrapper. Mostly copied from scripts/driver. @@ -74,89 +72,81 @@ def mailman_app(environ, start_response): paths = path.split(SLASH) # sanity check for paths spaths = [ i for i in paths[1:] if i and not dotonly.match(i) ] - # Do some path mangling here because someone may access with - # trailing slash for script. (Eg., /mailman/listinfo/ -> - # /mailman/listinfo) Use of SCRIPT_BASE breaks relative - # URI principle but we do believe mailman WSGI should NOT exposed - # to the Internet. - if spaths != paths[1:]: - if path == SLASH: - newpath = SCRIPT_BASE + 'listinfo' - else: - # Sanitize URI by spaths - if paths[1] not in ARCHVIEW: - newpath = SCRIPT_BASE + SLASH.join(spaths) - else: - # 'private' is different because, if trailing slash is - # present, it silently redirecte to index.html. - # Let's make it explicit here. - newpath = SCRIPT_BASE + SLASH.join(spaths) + '/index.html' + if spaths and spaths != paths[1:]: + newpath = SLASH + SLASH.join(spaths) start_response(MOVED_RESPONSE, [('Location', newpath)]) return 'Location: ' + newpath - script = paths[1] - if script in SCRIPTS: - environ['SCRIPT_NAME'] = script - if len(paths) > 2: - path_info = SLASH + SLASH.join(paths[2:]) - if script in ARCHVIEW \ - and len(paths) in (3,4) \ - and not paths[-1].split('.')[-1] in ('html', 'txt', 'gz'): - # /private/listname or /private/listname/YYYYmm - newpath = SCRIPT_BASE + SLASH.join(spaths) + '/index.html' - start_response(MOVED_RESPONSE, [('Location', newpath)]) - return 'Location: ' + newpath - environ['PATH_INFO'] = path_info - else: - environ['PATH_INFO'] = '' - # Reverse proxy environment. - if environ.has_key('HTTP_X_FORWARDED_HOST'): - environ['HTTP_HOST'] = environ['HTTP_X_FORWARDED_HOST'] - if environ.has_key('HTTP_X_FORWARDED_FOR'): - environ['REMOTE_HOST'] = environ['HTTP_X_FORWARDED_FOR'] - modname = 'Mailman.Cgi.' + script - # Clear previous cookie before setting new one. - os.environ['HTTP_COOKIE'] = '' - for k, v in environ.items(): - os.environ[k] = str(v) - # Prepare for redirection - save_stdin = sys.stdin - # CGI writes its output to sys.stdout, while wsgi app should - # return (list of) strings. - save_stdout = sys.stdout - save_stderr = sys.stderr - tmpstdout = StringIO() - tmpstderr = StringIO() - response = '' + # find script name + for script in SCRIPTS: + if script in spaths: + # Get script position in spaths and break. + scrpos = spaths.index(script) + break + else: + # Can't find valid script. + start_response('404 Not Found', []) + return '404 Not Found' + # Conpose CGI SCRIPT_NAME and PATH_INFO from WSGI path + script_name = SLASH + SLASH.join(spaths[:scrpos+1]) + environ['SCRIPT_NAME'] = script_name + if len(paths) > scrpos+2: + path_info = SLASH + SLASH.join(paths[scrpos+2:]) + if script in ARCHVIEW \ + and path_info.count('/') in (1,2) \ + and not paths[-1].split('.')[-1] in ('html', 'txt', 'gz'): + # Add index.html if /private/listname or + # /private/listname/YYYYmm is requested. + newpath = script_name + path_info + '/index.html' + start_response(MOVED_RESPONSE, [('Location', newpath)]) + return 'Location: ' + newpath + environ['PATH_INFO'] = path_info + else: + environ['PATH_INFO'] = '' + # Reverse proxy environment. + if environ.has_key('HTTP_X_FORWARDED_HOST'): + environ['HTTP_HOST'] = environ['HTTP_X_FORWARDED_HOST'] + if environ.has_key('HTTP_X_FORWARDED_FOR'): + environ['REMOTE_HOST'] = environ['HTTP_X_FORWARDED_FOR'] + modname = 'Mailman.Cgi.' + script + # Clear previous cookie before setting new one. + os.environ['HTTP_COOKIE'] = '' + for k, v in environ.items(): + os.environ[k] = str(v) + # Prepare for redirection + save_stdin = sys.stdin + # CGI writes its output to sys.stdout, while wsgi app should + # return (list of) strings. + save_stdout = sys.stdout + save_stderr = sys.stderr + tmpstdout = StringIO() + tmpstderr = StringIO() + response = '' + try: + try: + sys.stdin = environ['wsgi.input'] + sys.stdout = tmpstdout + sys.stderr = tmpstderr + __import__(modname) + sys.modules[modname].main() + response = sys.stdout.getvalue() + finally: + sys.stdin = save_stdin + sys.stdout = save_stdout + sys.stderr = save_stderr + except SystemExit: + sys.stdout.write(tmpstdout.getvalue()) + if response: try: - try: - sys.stdin = environ['wsgi.input'] - sys.stdout = tmpstdout - sys.stderr = tmpstderr - __import__(modname) - sys.modules[modname].main() - response = sys.stdout.getvalue() - finally: - sys.stdin = save_stdin - sys.stdout = save_stdout - sys.stderr = save_stderr - except SystemExit: - sys.stdout.write(tmpstdout.getvalue()) - if response: - try: - head, content = response.split(NL2, 1) - except ValueError: - head, content = response.split(CRLF2, 1) - m = message_from_string(head + CRLF2) - start_response('200 OK', m.items()) - return [content] - else: - # TBD: Error Code/Message - start_response('500 Server Error', []) - return '500 Internal Server Error' + head, content = response.split(NL2, 1) + except ValueError: + head, content = response.split(CRLF2, 1) + m = message_from_string(head + CRLF2) + start_response('200 OK', m.items()) + return [content] else: - # TBD: Error Message - start_response('404 Not Found', []) - return '404 Not Found' + # TBD: Error Code/Message + start_response('500 Server Error', []) + return '500 Internal Server Error' except: start_response('200 OK', [('Content-Type', 'text/html')]) retstring = print_traceback(log) diff --git a/Mailman/SecurityManager.py b/Mailman/SecurityManager.py index eb7676835..14b699594 100644 --- a/Mailman/SecurityManager.py +++ b/Mailman/SecurityManager.py @@ -95,7 +95,7 @@ class SecurityManager: # AuthUser, but the user isn't a member of this mailing list, a # NotAMemberError will be raised. If the user's secret is None, raise # a MMBadUserError. - key = self.internal_name() + '+' + key = urllib.quote(self.fqdn_listname) + '+' if authcontext == Defaults.AuthUser: if user is None: # A bad system error @@ -236,7 +236,7 @@ class SecurityManager: # way to do it -- the original uri that's proxied to us is not # included in the backend request. XXX what happens when Apache 2.2's # ProxyPassReverseCookiePath is set? - target = '/%s/%s' % (os.environ['SCRIPT_NAME'], self.fqdn_listname) + target = '%s/%s' % (os.environ['SCRIPT_NAME'], self.fqdn_listname) referer = os.environ.get('HTTP_REFERER') if not referer: return target @@ -305,7 +305,7 @@ class SecurityManager: usernames = [user] else: usernames = [] - prefix = self.internal_name() + '+user+' + prefix = urllib.quote(self.fqdn_listname) + '+user+' for k in c.keys(): if k.startswith(prefix): usernames.append(k[len(prefix):]) |
