diff options
| -rw-r--r-- | Mailman/Archiver/Archiver.py | 4 | ||||
| -rw-r--r-- | Mailman/Cgi/edithtml.py | 10 | ||||
| -rw-r--r-- | Mailman/Cgi/private.py | 2 | ||||
| -rw-r--r-- | Mailman/Cgi/wsgi_app.py | 40 | ||||
| -rw-r--r-- | Mailman/MailList.py | 7 |
5 files changed, 52 insertions, 11 deletions
diff --git a/Mailman/Archiver/Archiver.py b/Mailman/Archiver/Archiver.py index f76992928..96d6c46dc 100644 --- a/Mailman/Archiver/Archiver.py +++ b/Mailman/Archiver/Archiver.py @@ -136,15 +136,13 @@ class Archiver: def GetBaseArchiveURL(self): if self.archive_private: - url = self.GetScriptURL('private') + url = self.GetScriptURL('private') + '/index.html' else: web_host = config.domains.get(self.host_name, self.host_name) url = config.PUBLIC_ARCHIVE_URL % { 'listname': self.internal_name(), 'hostname': web_host, } - if not url.endswith('/'): - url += '/' return url def __archive_file(self, afn): diff --git a/Mailman/Cgi/edithtml.py b/Mailman/Cgi/edithtml.py index b0275de75..7a16c1c28 100644 --- a/Mailman/Cgi/edithtml.py +++ b/Mailman/Cgi/edithtml.py @@ -27,9 +27,11 @@ from Mailman import Errors from Mailman import i18n from Mailman import MailList from Mailman import Utils +from Mailman import Defaults from Mailman.Cgi import Auth from Mailman.htmlformat import * from Mailman.HTMLFormatter import HTMLFormatter +from Mailman.configuration import config _ = i18n._ @@ -54,8 +56,8 @@ def main(): doc = Document() # Set up the system default language - i18n.set_language(mm_cfg.DEFAULT_SERVER_LANGUAGE) - doc.set_language(mm_cfg.DEFAULT_SERVER_LANGUAGE) + i18n.set_language(config.DEFAULT_SERVER_LANGUAGE) + doc.set_language(config.DEFAULT_SERVER_LANGUAGE) parts = Utils.GetPathPieces() if not parts: @@ -82,8 +84,8 @@ def main(): cgidata = cgi.FieldStorage() # Editing the html for a list is limited to the list admin and site admin. - if not mlist.WebAuthenticate((mm_cfg.AuthListAdmin, - mm_cfg.AuthSiteAdmin), + if not mlist.WebAuthenticate((Defaults.AuthListAdmin, + Defaults.AuthSiteAdmin), cgidata.getvalue('adminpw', '')): if cgidata.has_key('admlogin'): # This is a re-authorization attempt diff --git a/Mailman/Cgi/private.py b/Mailman/Cgi/private.py index c9e69944b..1ed6fa23d 100644 --- a/Mailman/Cgi/private.py +++ b/Mailman/Cgi/private.py @@ -139,7 +139,7 @@ def main(): print 'Content-type: text/html; charset=' + charset + '\n\n' # Put the original full path in the authorization form, but avoid # trailing slash if we're not adding parts. We add it below. - action = mlist.GetScriptURL('private', absolute=1) + action = mlist.GetScriptURL('private') if parts[1:]: action = os.path.join(action, SLASH.join(parts[1:])) # If we added '/index.html' to true_filename, add a slash to the URL. diff --git a/Mailman/Cgi/wsgi_app.py b/Mailman/Cgi/wsgi_app.py index 8e77352d6..402745e3b 100644 --- a/Mailman/Cgi/wsgi_app.py +++ b/Mailman/Cgi/wsgi_app.py @@ -16,8 +16,10 @@ # USA. import os +import re import sys +from urlparse import urlparse from cStringIO import StringIO from email import message_from_string @@ -25,6 +27,9 @@ from Mailman.configuration import config # XXX Should this be configurable in Defaults.py? STEALTH_MODE = False +MOVED_RESPONSE = '302 Found' +# Above is for debugging convenience. We should use: +# MOVED_RESPONSE = '301 Moved Permanently' @@ -35,11 +40,15 @@ def websafe(s): SCRIPTS = ['admin', 'admindb', 'confirm', 'create', 'edithtml', 'listinfo', 'options', 'private', 'rmlist', 'roster', 'subscribe'] +ARCHVIEW = ['private'] SLASH = '/' NL2 = '\n\n' 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. @@ -62,11 +71,40 @@ def mailman_app(environ, start_response): path = environ['PATH_INFO'] 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' + start_response(MOVED_RESPONSE, [('Location', newpath)]) + return 'Location: ' + newpath script = paths[1] if script in SCRIPTS: environ['SCRIPT_NAME'] = script if len(paths) > 2: - environ['PATH_INFO'] = SLASH + SLASH.join(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. diff --git a/Mailman/MailList.py b/Mailman/MailList.py index 245f16ad8..555717eff 100644 --- a/Mailman/MailList.py +++ b/Mailman/MailList.py @@ -263,8 +263,11 @@ class MailList(HTMLFormatter, Deliverer, ListAdmin, acct, host = tuple(member.split('@')) return "%s%s@%s" % (acct, self.umbrella_member_suffix, host) - def GetScriptURL(self, target): - return Utils.ScriptURL(target) + '/' + self.fqdn_listname + def GetScriptURL(self, target, absolute=False): + if absolute: + return self.web_page_url + target + '/' + self.fqdn_listname + else: + return Utils.ScriptURL(target) + '/' + self.fqdn_listname def GetOptionsURL(self, user, obscure=False, absolute=False): url = self.GetScriptURL('options', absolute) |
