diff options
Diffstat (limited to '')
-rw-r--r-- | Mailman/Cgi/private.py | 162 |
1 files changed, 162 insertions, 0 deletions
diff --git a/Mailman/Cgi/private.py b/Mailman/Cgi/private.py new file mode 100644 index 00000000..6b7af70a --- /dev/null +++ b/Mailman/Cgi/private.py @@ -0,0 +1,162 @@ +# Copyright (C) 1998,1999,2000,2001,2002 by the Free Software Foundation, Inc. +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 +# of the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +"""Provide a password-interface wrapper around private archives. +""" + +import sys +import os +import cgi + +from Mailman import mm_cfg +from Mailman import Utils +from Mailman import MailList +from Mailman import Errors +from Mailman import i18n +from Mailman.htmlformat import * +from Mailman.Logging.Syslog import syslog + +# Set up i18n. Until we know which list is being requested, we use the +# server's default. +_ = i18n._ +i18n.set_language(mm_cfg.DEFAULT_SERVER_LANGUAGE) + + + +def true_path(path): + "Ensure that the path is safe by removing .." + path = path.replace('../', '') + path = path.replace('./', '') + return path[1:] + + +def content_type(path): + if path[-3:] == '.gz': + path = path[:-3] + if path[-4:] == '.txt': + return 'text/plain' + return 'text/html' + + + +def main(): + doc = Document() + doc.set_language(mm_cfg.DEFAULT_SERVER_LANGUAGE) + + parts = Utils.GetPathPieces() + if not parts: + doc.SetTitle(_("Private Archive Error")) + doc.AddItem(Header(3, _("You must specify a list."))) + print doc.Format() + return + + path = os.environ.get('PATH_INFO') + # BAW: This needs to be converted to the Site module abstraction + true_filename = os.path.join( + mm_cfg.PRIVATE_ARCHIVE_FILE_DIR, + true_path(path)) + + listname = parts[0].lower() + mboxfile = '' + if len(parts) > 1: + mboxfile = parts[1] + + # See if it's the list's mbox file is being requested + if listname.endswith('.mbox') and mboxfile.endswith('.mbox') and \ + listname[:-5] == mboxfile[:-5]: + listname = listname[:-5] + else: + mboxfile = '' + + # If it's a directory, we have to append index.html in this script. We + # must also check for a gzipped file, because the text archives are + # usually stored in compressed form. + if os.path.isdir(true_filename): + true_filename = true_filename + '/index.html' + if not os.path.exists(true_filename) and \ + os.path.exists(true_filename + '.gz'): + true_filename = true_filename + '.gz' + + try: + mlist = MailList.MailList(listname, lock=0) + except Errors.MMListError, e: + # Avoid cross-site scripting attacks + safelistname = Utils.websafe(listname) + msg = _('No such list <em>%(safelistname)s</em>') + doc.SetTitle(_("Private Archive Error - %(msg)s")) + doc.AddItem(Header(2, msg)) + print doc.Format() + syslog('error', 'No such list "%s": %s\n', listname, e) + return + + i18n.set_language(mlist.preferred_language) + doc.set_language(mlist.preferred_language) + + cgidata = cgi.FieldStorage() + username = cgidata.getvalue('username', '') + password = cgidata.getvalue('password', '') + + is_auth = 0 + realname = mlist.real_name + message = '' + + if not mlist.WebAuthenticate((mm_cfg.AuthUser, + mm_cfg.AuthListModerator, + mm_cfg.AuthListAdmin, + mm_cfg.AuthSiteAdmin), + password, username): + if cgidata.has_key('submit'): + # This is a re-authorization attempt + message = Bold(FontSize('+1', _('Authorization failed.'))).Format() + # Output the password form + charset = Utils.GetCharSet(mlist.preferred_language) + print 'Content-type: text/html; charset=' + charset + '\n\n' + while path and path[0] == '/': + path=path[1:] # Remove leading /'s + print Utils.maketext( + 'private.html', + {'action' : mlist.GetScriptURL('private', absolute=1), + 'realname': mlist.real_name, + 'message' : message, + }, mlist=mlist) + return + + lang = mlist.getMemberLanguage(username) + i18n.set_language(lang) + doc.set_language(lang) + + # Authorization confirmed... output the desired file + try: + ctype = content_type(path) + if mboxfile: + f = open(os.path.join(mlist.archive_dir() + '.mbox', + mlist.internal_name() + '.mbox')) + ctype = 'text/plain' + elif true_filename[-3:] == '.gz': + import gzip + f = gzip.open(true_filename, 'r') + else: + f = open(true_filename, 'r') + except IOError: + msg = _('Private archive file not found') + doc.SetTitle(msg) + doc.AddItem(Header(2, msg)) + print doc.Format() + syslog('error', 'Private archive file not found: %s', true_filename) + else: + print 'Content-type: %s\n' % ctype + sys.stdout.write(f.read()) + f.close() |