diff options
| author | viega | 1998-06-14 01:00:28 +0000 |
|---|---|---|
| committer | viega | 1998-06-14 01:00:28 +0000 |
| commit | 73e488770ae493feeaf08ac9d21bd14eccdb2da2 (patch) | |
| tree | 950823c4949a13fcf3b3dcb82df1310bbe6be6ba | |
| parent | 8dfd4643c7d8216cfbf6e180ed7b868715b9e775 (diff) | |
| download | mailman-73e488770ae493feeaf08ac9d21bd14eccdb2da2.tar.gz mailman-73e488770ae493feeaf08ac9d21bd14eccdb2da2.tar.zst mailman-73e488770ae493feeaf08ac9d21bd14eccdb2da2.zip | |
| -rwxr-xr-x | cgi/admin | 840 | ||||
| -rwxr-xr-x | cgi/admindb | 225 | ||||
| -rwxr-xr-x | cgi/archives | 81 | ||||
| -rwxr-xr-x | cgi/edithtml | 160 | ||||
| -rwxr-xr-x | cgi/handle_opts | 199 | ||||
| -rwxr-xr-x | cgi/listinfo | 172 | ||||
| -rwxr-xr-x | cgi/options | 120 | ||||
| -rwxr-xr-x | cgi/private | 222 | ||||
| -rwxr-xr-x | cgi/roster | 108 | ||||
| -rwxr-xr-x | cgi/subscribe | 180 |
10 files changed, 58 insertions, 2249 deletions
@@ -16,840 +16,14 @@ # along with this program; if not, write to the Free Software # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -"""Process and produce the list-administration options forms. -To run stand-alone for debugging, set env var PATH_INFO to name of list -and, optionally, options category.""" +import paths -__version__ = "$Revision: 732 $" +def admin(): + import Mailman.Cgi.admin + Mailman.Cgi.admin.main() -import sys -import os, cgi, string, crypt, types, time -import paths # path hacking -import mm_utils, maillist, mm_cfg, mm_err, mm_mailcmd, Cookie -from htmlformat import * +from Mailman.runcgi import * +wrap_func(admin) -try: - sys.stderr = mm_utils.StampedLogger("error", label = 'admin', - manual_reprime=1, nofail=0) -except IOError: - pass # Oh well - SOL on redirect, errors show thru. - -CATEGORIES = [('general', "General Options"), - ('members', "Membership Management"), - ('privacy', "Privacy Options"), - ('nondigest', "Regular-member (non-digest) Options"), - ('digest', "Digest-member Options"), - ('bounce', "Bounce Options"), - ('archive', "Archival Options"), - ('gateway', "Mail-News and News-Mail gateways")] - - -LOGIN_PAGE = """ -<html> -<head> - <title>%(listname)s Administrative Authentication</title> -</head> -<body bgcolor="#ffffff"> -<FORM METHOD=POST ACTION="%(path)s"> -%(message)s - <TABLE WIDTH="100%%" BORDER="0" CELLSPACING="4" CELLPADDING="5"> - <TR> - <TD COLSPAN="2" WIDTH="100%%" BGCOLOR="#99CCFF" ALIGN="CENTER"> - <B><FONT COLOR="#000000" SIZE="+1">%(listname)s Administrative - Authentication</FONT></B> - </TD> - </TR> - <tr> - <TD> <div ALIGN="Right"> List Administrative Password: </div> </TD> - <TD> <INPUT TYPE=password NAME=adminpw SIZE=30></TD> - </tr> - <tr> - <td colspan=2 align=middle> <INPUT TYPE=SUBMIT name="request_login"> - </td> - </tr> - </TABLE> -</FORM> -""" - -# " <- icky emacs font-lock bug workaround - -SECRET="monty" - -def isAuthenticated(list, password=None, SECRET="SECRET"): - import base64, md5 - if password is not None: # explicit login - try: - list.ConfirmAdminPassword(password) - except mm_err.MMBadPasswordError: - AddErrorMessage(doc, 'Error: Incorrect admin password.') - return 0 - except: - print "Content-type: text/html\n" - - print "<p><h3>We're sorry, we hit a bug!</h3>\n" - print "If you would like to help us identify the problem, please " - print "email a copy of this page to the webmaster for this site" - print 'with a description of what happened. Thanks!' - print "\n<PRE>" - try: - import traceback - sys.stderr = sys.stdout - traceback.print_exc() - except: - print "[failed to get traceback]" - print "\n\n</PRE>" - - token = md5.new(SECRET + list_name + SECRET).digest() - token = base64.encodestring(token) - token = string.strip(token) - c = Cookie.Cookie() - cookie_key = list_name + "-admin" - c[cookie_key] = token - c[cookie_key]['expires'] = mm_cfg.ADMIN_COOKIE_LIFE - print c # Output the cookie - return 1 - if os.environ.has_key('HTTP_COOKIE'): - c = Cookie.Cookie( os.environ['HTTP_COOKIE'] ) - if c.has_key(list_name + "-admin"): - try: - inp = base64.decodestring(c[list_name + "-admin"].value) - check = md5.new(SECRET+list_name+SECRET).digest() - except Error: # the decodestring may return incorrect padding? - raise 'Decode failed' - return 0 - if inp == check: - return 1 - else: - return 0 - return 0 - - -def main(): - """Process and produce list options form. - - CGI input indicates that we're returning from submission of some new - settings, which is processed before producing the new version.""" - global list_name, list_info, doc - doc = Document() - - try: - path = os.environ['PATH_INFO'] - except KeyError: - path = "" - list_info = mm_utils.GetPathPieces(path) - # How many ../'s we need to get back to http://host/mailman - - if len(list_info) == 0: - FormatAdminOverview() - return - - list_name = string.lower(list_info[0]) - - lst = maillist.MailList(list_name) - - try: - if not (lst and lst._ready): - FormatAdminOverview(error="List <em>%s</em> not found." - % list_name) - return - - if len(list_info) == 1: - category = 'general' - category_suffix = '' - else: - category = list_info[1] - category_suffix = category - - if category not in map(lambda x: x[0], CATEGORIES): - category = 'general' - global cgi_data - cgi_data = cgi.FieldStorage() - is_auth = 0 - if cgi_data.has_key("adminpw"): - is_auth = isAuthenticated(lst, cgi_data["adminpw"].value) - message = FontAttr("Sorry, wrong password. Try again.", - color="ff5060", size="+1").Format() - else: - is_auth = isAuthenticated(lst) - message = "" - if not is_auth: - print "Content-type: text/html\n\n" - print LOGIN_PAGE % ({"listname": list_name, - "path": os.environ.get("REQUEST_URI", "/mailman/admin"), - "message": message}) - return - - if len(cgi_data.keys()): - if cgi_data.has_key('VARHELP'): - FormatOptionHelp(doc, cgi_data['VARHELP'].value, lst) - print doc.Format(bgcolor="#ffffff") - return - if (cgi_data.has_key('bounce_matching_headers')): - try: - pairs = lst.parse_matching_header_opt() - except mm_err.MMBadConfigError, line: - AddErrorMessage(doc, - 'Warning: bad matching-header line' - ' (does it have the colon?)<ul> %s </ul>', - line) - - if not lst.digestable and len(lst.digest_members): - AddErrorMessage(doc, - 'Warning: you have digest members,' - ' but digests are turned off.' - ' Those people will not receive mail.') - if not lst.nondigestable and len(lst.members): - AddErrorMessage(doc, - 'Warning: you have lst members,' - ' but non-digestified mail is turned' - ' off. They will receive mail until' - ' you fix this problem.') - if len(cgi_data.keys()): - ChangeOptions(lst, category, cgi_data, doc) - FormatConfiguration(doc, lst, category, category_suffix) - print doc.Format(bgcolor="#ffffff") - - finally: - lst.Unlock() - -# Form Production: - -def FormatAdminOverview(error=None): - "Present a general welcome and itemize the (public) lists." - doc = Document() - legend = "%s maillists - Admin Links" % mm_cfg.DEFAULT_HOST_NAME - doc.SetTitle(legend) - - table = Table(border=0, width="100%") - table.AddRow([Center(Header(2, legend))]) - table.AddCellInfo(max(table.GetCurrentRowIndex(), 0), 0, - colspan=2, bgcolor="#99ccff") - - advertised = [] - names = mm_utils.list_names() - names.sort() - for n in names: - l = maillist.MailList(n, lock=0) - if l.advertised: advertised.append(l) - - if error: - greeting = FontAttr(error, color="ff5060", size="+1") - else: - greeting = "Welcome!" - - if not advertised: - welcome_items = (greeting, - "<p>" - " There currently are no publicly-advertised ", - Link(mm_cfg.MAILMAN_URL, "mailman"), - " maillists on %s." % mm_cfg.DEFAULT_HOST_NAME, - ) - else: - - welcome_items = ( - greeting, - "<p>" - " Below is the collection of publicly-advertised ", - Link(mm_cfg.MAILMAN_URL, "mailman"), - " maillists on %s." % mm_cfg.DEFAULT_HOST_NAME, - (' Click on a list name to visit the configuration pages' - ' for that list.' - ) - ) - - welcome_items = (welcome_items + - (" To visit the administrators configuration page for" - " an unadvertised list, open a URL similar to this" - + - (" one, but with a '/' and the %slist name appended.<p>" - % ((error and "the right ") or "")) - + - " General list information can be found at ", - Link(os.path.join('../'* mm_utils.GetNestingLevel(), - "listinfo/"), "the maillist overview page"), - "." - "<p>(Send questions and comments to ", - Link("mailto:%s" % mm_cfg.MAILMAN_OWNER, - mm_cfg.MAILMAN_OWNER), - ".)<p>" - ) - ) - - table.AddRow([apply(Container, welcome_items)]) - table.AddCellInfo(max(table.GetCurrentRowIndex(), 0), 0, colspan=2) - - if advertised: - table.AddRow([Italic("List"), Italic("Description")]) - for l in advertised: - table.AddRow([Link(l.GetRelativeScriptURL('admin'), - Bold(l.real_name)),l.description]) - - doc.AddItem(table) - - print doc.Format(bgcolor="#ffffff") - -def FormatConfiguration(doc, lst, category, category_suffix): - """Produce the overall doc, *except* any processing error messages.""" - for k, v in CATEGORIES: - if k == category: label = v - - doc.SetTitle('%s Administration' % lst.real_name) - doc.AddItem(Center(Header(2, ('%s Maillist Configuration - %s Section' - % (lst.real_name, label))))) - doc.AddItem('<hr>') - - links_table = Table(valign="top") - - links_table.AddRow([Center(Bold("Configuration Categories")), - Center(Bold("Other Administrative Activities"))]) - other_links = UnorderedList() - link = Link(lst.GetRelativeScriptURL('admindb'), - 'Tend to pending administrative requests.') - other_links.AddItem(link) - link = Link(lst.GetRelativeScriptURL('listinfo'), - 'Go to the general list information page.') - other_links.AddItem(link) - link = Link(lst.GetRelativeScriptURL('edithtml'), - 'Edit the HTML for the public list pages.') - other_links.AddItem(link) - - these_links = UnorderedList() - for k, v in CATEGORIES: - if k == category: - these_links.AddItem("<b> => " + v + " <= </b>") - else: - these_links.AddItem(Link("%s/%s" % - (lst.GetRelativeScriptURL('admin'),k),v)) - - links_table.AddRow([these_links, other_links]) - links_table.AddRowInfo(max(links_table.GetCurrentRowIndex(), 0), - valign="top") - - doc.AddItem(links_table) - doc.AddItem('<hr>') - if category_suffix: - form = Form("%s/%s" % (lst.GetRelativeScriptURL('admin'), - category_suffix)) - else: - form = Form(lst.GetRelativeScriptURL('admin')) - doc.AddItem(form) - - form.AddItem("Make your changes, below, and then submit it all at the" - " bottom. (You can also change your password there," - " as well.)<p>") - - form.AddItem(FormatOptionsSection(category, lst)) - - form.AddItem(Center(FormatPasswordStuff())) - - form.AddItem(lst.GetMailmanFooter()) - -def FormatOptionsSection(category, lst): - """Produce the category-specific options table.""" - if category == 'members': - # Special case for members section. - return FormatMembershipOptions(lst) - - options = GetConfigOptions(lst, category) - - big_table = Table(cellspacing=3, cellpadding=4) - - # Get and portray the text label for the category. - for k, v in CATEGORIES: - if k == category: label = v - big_table.AddRow([Center(Header(2, label))]) - big_table.AddCellInfo(max(big_table.GetCurrentRowIndex(), 0), 0, - colspan=2, bgcolor="#99ccff") - - def ColHeader(big_table = big_table): - big_table.AddRow([Center(Bold('Description')), Center(Bold('Value'))]) - big_table.AddCellInfo(max(big_table.GetCurrentRowIndex(), 0), 0, - width="15%") - big_table.AddCellInfo(max(big_table.GetCurrentRowIndex(), 0), 1, - width="85%") - did_col_header = 0 - - for item in options: - if type(item) == types.StringType: - # The very first banner option (string in an options list) is - # treated as a general description, while any others are - # treated as section headers - centered and italicized... - if did_col_header: - item = "<center><i>" + item + "</i></center>" - big_table.AddRow([item]) - big_table.AddCellInfo(max(big_table.GetCurrentRowIndex(), 0), - 0, colspan=2) - if not did_col_header: - # Do col header after very first string descr, if any... - ColHeader() - did_col_header = 1 - else: - if not did_col_header: - # ... but do col header before anything else. - ColHeader() - did_col_header = 1 - AddOptionsTableItem(big_table, item, category, lst) - big_table.AddRow(['<br>']) - big_table.AddCellInfo(big_table.GetCurrentRowIndex(), 0, colspan=2) - return big_table - -def AddOptionsTableItem(table, item, category, lst, nodetails=0): - """Add a row to an options table with the item description and value.""" - try: - got = GetItemCharacteristics(item) - varname, kind, params, dependancies, descr, elaboration = got - except ValueError, msg: - lst.LogMsg("error", "admin: %s", msg) - return Italic("<malformed option>") - descr = GetItemGuiDescr(lst, category, varname, descr, - elaboration, nodetails) - val = GetItemGuiValue(lst, kind, varname, params) - table.AddRow([descr, val]) - table.AddCellInfo(max(table.GetCurrentRowIndex(), 0), 1, - bgcolor="#cccccc") - table.AddCellInfo(max(table.GetCurrentRowIndex(), 0), 0, - bgcolor="#cccccc") - -def FormatOptionHelp(doc, varref, lst): - item = bad = None - reflist = string.split(varref, '/') - if len(reflist) == 2: - category, varname = reflist - options = GetConfigOptions(lst, category) - for i in options: - if i and i[0] == varname: - item = i - break - if not item: - bad = ("Option %s/%s not found. %s" - % (category, varname, os.environ['PATH_INFO'])) - else: - try: - got = GetItemCharacteristics(item) - varname, kind, params, dependancies, descr, elaboration = got - except ValueError, msg: - bad = msg - if not bad and not elaboration: - bad = "Option %s has no extended help." % varname - if bad: - AddErrorMessage(doc, bad) - return - - header = Table(width="100%") - legend = ('%s Maillist Configuration Help<br><em>%s</em> Option' - % (lst.real_name, varname)) - header.AddRow([Center(Header(3, legend))]) - header.AddCellInfo(max(header.GetCurrentRowIndex(), 0), 0, - colspan=2, bgcolor="#99ccff") - doc.SetTitle("Mailman %s List Option Help" % varname) - doc.AddItem(header) - doc.AddItem("<b>%s</b> (%s): %s<p>" % (varname, category, item[4])) - doc.AddItem("%s<p>" % item[5]) - - form = Form(os.path.join(lst.GetRelativeScriptURL('admin'), category)) - valtab = Table(cellspacing=3, cellpadding=4) - AddOptionsTableItem(valtab, item, category, lst, nodetails=1) - form.AddItem(valtab) - # XXX I don't think we want to be able to set options from two places, - # since they'll go out of sync. - #form.AddItem(Center(FormatPasswordStuff())) - doc.AddItem(Center(form)) - -def GetItemCharacteristics(table_entry): - """Break out the components of an item description from its table entry: - 0 option-var name - 1 type - 2 entry size - 3 ?dependancies? - 4 Brief description - 5 Optional description elaboration""" - if len(table_entry) == 5: - elaboration = None - varname, kind, params, dependancies, descr = table_entry - elif len(table_entry) == 6: - varname, kind, params, dependancies, descr, elaboration = table_entry - else: - raise ValueError, ("Badly formed options entry:\n %s" - % table_entry) - return (varname, kind, params, dependancies, descr, elaboration) - -def GetItemGuiValue(lst, kind, varname, params): - """Return a representation of an item's settings.""" - if kind == mm_cfg.Radio or kind == mm_cfg.Toggle: - return RadioButtonArray(varname, params, getattr(lst, varname)) - elif (kind == mm_cfg.String or kind == mm_cfg.Email or - kind == mm_cfg.Host or kind == mm_cfg.Number): - return TextBox(varname, getattr(lst, varname), params) - elif kind == mm_cfg.Text: - if params: - r, c = params - else: - r, c = None, None - val = getattr(lst, varname) - if not val: - val = '' - return TextArea(varname, val, r, c) - elif kind == mm_cfg.EmailList: - if params: - r, c = params - else: - r, c = None, None - res = string.join(getattr(lst, varname), '\n') - return TextArea(varname, res, r, c, wrap='off') - -def GetItemGuiDescr(lst, category, varname, descr, elaboration, nodetails): - """Return a representation of an item's description, with link to - elaboration if any.""" - descr = '<div ALIGN="right">' + descr - if not nodetails and elaboration: - ref = "../" * (mm_utils.GetNestingLevel()-1) + list_name + "/" - ref = ref + '?VARHELP=' + category + "/" + varname - descr = Container(descr, - Link(ref, " (Details)", target="MMHelp"), - "</div>") - else: - descr = descr + "</div>" - return descr - -def FormatMembershipOptions(lst): - container = Container() - header = Table(width="100%") - header.AddRow([Center(Header(2, "Membership Management"))]) - header.AddCellInfo(max(header.GetCurrentRowIndex(), 0), 0, - colspan=2, bgcolor="#99ccff") - container.AddItem(header) - user_table = Table(width="90%") - user_table.AddRow([Center(Header(4, "Membership List"))]) - user_table.AddCellInfo(user_table.GetCurrentRowIndex(), - user_table.GetCurrentCellIndex(), - bgcolor="#cccccc", colspan=8) - - members = {} - digests = {} - for member in lst.members: - members[member] = 1 - for member in lst.digest_members: - digests[member] = 1 - all = lst.members + lst.digest_members - if len(all) > mm_cfg.ADMIN_MEMBER_CHUNKSIZE: - chunks = mm_utils.chunkify(all) - if not cgi_data.has_key("chunk"): - chunk = 0 - else: - chunk = string.atoi(cgi_data["chunk"].value) - all = chunks[chunk] - footer = ("<p><em>To View other sections, " - "click on the appropriate range listed below</em>") - chunk_indices = range(len(chunks)) - chunk_indices.remove(chunk) - buttons = [] - pi = os.environ["PATH_INFO"] - for ci in chunk_indices: - start, end = chunks[ci][0], chunks[ci][-1] - buttons.append("<a href=/mailman/admin%s?chunk=%d> from %s to %s </a>" % \ - ( pi, ci, start, end)) - buttons = apply(UnorderedList, tuple(buttons)) - footer = footer + buttons.Format() + "<p>" - else: - all.sort() - footer = "<p>" - for member in all: - cells = [member + "<input type=hidden name=user value=%s>" % (member), - "subscribed " +CheckBox(member + "_subscribed", "on", 1).Format(), - ] - if members.get(member): - cells.append("digest " + CheckBox(member + "_digest", "off", 0).Format()) - else: - cells.append("digest " + CheckBox(member + "_digest", "on", 1).Format()) - for opt in ("hide", "nomail", "ack", "norcv", "plain"): - if lst.GetUserOption(member, mm_mailcmd.option_info[opt]): - value = "on" - checked = 1 - else: - value = "off" - checked = 0 - box = CheckBox("%s_%s" % (member, opt), value, checked) - cells.append("%s %s" % (opt, box.Format())) - user_table.AddRow(cells) - container.AddItem(Center(user_table)) - container.AddItem(footer) - t = Table(width="90%") - t.AddRow([Center(Header(4, "Mass Subscribe Members"))]) - t.AddCellInfo(t.GetCurrentRowIndex(), - t.GetCurrentCellIndex(), - bgcolor="#cccccc", colspan=8) - container.AddItem(Center(t)) - container.AddItem(Center(TextArea(name='subscribees', rows=10,cols=60,wrap=None))) - container.AddItem(Center("<em> Enter One address per line</em><p>")) - return container - -def FormatPasswordStuff(): - submit = Table(bgcolor="#99ccff", - border=0, cellspacing=0, cellpadding=2, width="100%") - submit.AddRow([Bold(SubmitButton('submit', 'Submit Your Changes'))]) - submit.AddCellInfo(submit.GetCurrentRowIndex(), 0, align="middle") - change_pw_table = Table(bgcolor="#99cccc", border=0, - cellspacing=0, cellpadding=2, width="90%") - change_pw_table.AddRow([Bold(Center('To Change The Administrator Password')), - '<div ALIGN="right"> Enter the new password: </div>', - PasswordBox('newpw'),]) - change_pw_table.AddCellInfo(0, 0, align="middle", colspan=2) - change_pw_table.AddRow(['<div ALIGN="right"> Enter the current password </div>', - PasswordBox('adminpw'), - '<div ALIGN="right">Again to confirm it:</div>', - PasswordBox('confirmpw')]) - password_stuff = Container() - password_stuff.AddItem(change_pw_table) - password_stuff.AddItem("<p>") - password_stuff.AddItem(submit) - return password_stuff - -# XXX klm - looks like turn_on_moderation is orphaned. -turn_on_moderation = 0 - -# Options processing - -def GetValidValue(lst, prop, my_type, val, dependant): - if my_type == mm_cfg.Radio or my_type == mm_cfg.Toggle: - if type(val) <> types.IntType: - try: - # XXX Security!? - val = eval(val) - except: - pass - # Don't know what to do here... - return val - elif my_type == mm_cfg.String or my_type == mm_cfg.Text: - return val - elif my_type == mm_cfg.Email: - try: - valid = mm_utils.ValidEmail(val) - if valid: - return val - except: - pass - # Revert to the old value. - return getattr(lst, prop) - elif my_type == mm_cfg.EmailList: - def SafeValidAddr(addr): - import mm_utils - try: - valid = mm_utils.ValidEmail(addr) - if valid: - return 1 - else: - return 0 - except: - return 0 - - val = filter(SafeValidAddr, - map(string.strip, string.split(val, '\n'))) - if dependant and len(val): - # Wait till we've set everything to turn it on, - # as we don't want to clobber our special case. - # XXX klm - looks like turn_on_moderation is orphaned? - turn_on_moderation = 1 - return val - elif my_type == mm_cfg.Host: - return val -## -## This code is sendmail dependant, so we'll just live w/o -## the error checking for now. -## -## # Shouldn't have to read in the whole file. -## file = open('/etc/sendmail.cf', 'r') -## lines = string.split(file.read(), '\n') -## file.close() -## def ConfirmCWEntry(item): -## return item[0:2] == 'Cw' -## lines = filter(ConfirmCWEntry, lines) -## if not len(lines): -## # Revert to the old value. -## return getattr(list, prop) -## for line in lines: -## if string.lower(string.strip(line[2:])) == string.lower(val): -## return val -## return getattr(list, prop) - elif my_type == mm_cfg.Number: - try: - num = eval(val) - if num < 0: - return getattr(lst, prop) - return num - except: - return getattr(lst, prop) - else: - # Should never get here... - return val - - -def ChangeOptions(lst, category, cgi_info, document): - dirty = 0 - confirmed = 0 - if cgi_info.has_key('newpw'): - if cgi_info.has_key('confirmpw'): - if cgi_info.has_key('adminpw'): - try: - lst.ConfirmAdminPassword(cgi_info['adminpw'].value) - confirmed = 1 - except mm_err.MMBadPasswordError: - m = "Error: incorrect administrator password" - document.AddItem(Header(3, Italic(FontAttr(m, color="ff5060")))) - confirmed = 0 - if confirmed: - new = cgi_info['newpw'].value - confirm = cgi_info['confirmpw'].value - if new == confirm: - lst.password = crypt.crypt(new, mm_utils.GetRandomSeed()) - dirty = 1 - else: - m = 'Error: Passwords did not match.' - document.AddItem(Header(3, Italic(FontAttr(m, color="ff5060")))) - - else: - m = 'Error: You must type in your new password twice.' - document.AddItem( - Header(3, Italic(FontAttr(m, color="ff5060")))) - # - # for some reason, the login page mangles important values for the list - # such as .real_name so we only process these changes if the category - # is not "members" and the request is not from the login page - # -scott 19980515 - # - if category != 'members' and not cgi_info.has_key("request_login") and\ - len(cgi_info.keys()) > 1: - opt_list = GetConfigOptions(lst, category) - for item in opt_list: - if len(item) < 5: - continue - property, kind, args, deps, desc = (item[0], item[1], item[2], - item[3], item[4]) - if not cgi_info.has_key(property): - if (kind <> mm_cfg.Text and - kind <> mm_cfg.String and - kind <> mm_cfg.EmailList): - continue - else: - val = '' - else: - val = cgi_info[property].value - value = GetValidValue(lst, property, kind, val, deps) - if getattr(lst, property) != value: - setattr(lst, property, value) - dirty = 1 - # - # mass subscription processing for members category - # - if cgi_info.has_key('subscribees'): - name_text = cgi_info['subscribees'].value - name_text = string.replace(name_text, '\r', '') - names = string.split(name_text, '\n') - if '' in names: - names.remove('') - subscribe_success = [] - subscribe_errors = [] - for new_name in map(string.strip,names): - digest = 0 - if not lst.digestable: - digest = 0 - if not lst.nondigestable: - digest = 1 - try: - lst.ApprovedAddMember(new_name, (mm_utils.GetRandomSeed() + - mm_utils.GetRandomSeed()), digest) - subscribe_success.append(new_name) - except mm_err.MMAlreadyAMember: - subscribe_errors.append((new_name, 'Already a member')) - - except mm_err.MMBadEmailError: - subscribe_errors.append((new_name, "Bad/Invalid email address")) - except mm_err.MMHostileAddress: - subscribe_errors.append((new_name, "Hostile Address (illegal characters)")) - if subscribe_success: - document.AddItem(Header(5, "Successfully Subscribed:")) - document.AddItem(apply(UnorderedList, tuple((subscribe_success)))) - document.AddItem("<p>") - if subscribe_errors: - document.AddItem(Header(5, "Error Subscribing:")) - items = map(lambda x: "%s -- %s" % (x[0], x[1]), subscribe_errors) - document.AddItem(apply(UnorderedList, tuple((items)))) - document.AddItem("<p>") - # - # do the user options for members category - # - if cgi_info.has_key('user'): - user = cgi_info["user"] - if type(user) is type([]): - users = [] - for ui in range(len(user)): - users.append(user[ui].value) - else: - users = [user.value] - for user in users: - if not cgi_info.has_key('%s_subscribed' % (user)): - lst.DeleteMember(user) - dirty = 1 - continue - if not cgi_info.has_key("%s_digest" % (user)): - if user in lst.digest_members: - list.digest_members.remove(user) - dirty = 1 - if user not in lst.members: - lst.members.append(user) - dirty = 1 - else: - if user not in lst.digest_members: - lst.digest_members.append(user) - dirty = 1 - if user in lst.members: - lst.members.remove(user) - dirty = 1 - - for opt in ("hide", "nomail", "ack", "norcv", "plain"): - if cgi_info.has_key("%s_%s" % (user, opt)): - lst.SetUserOption(user, mm_mailcmd.option_info[opt], 1) - dirty = 1 - else: - lst.SetUserOption(user, mm_mailcmd.option_info[opt], 0) - dirty = 1 - - - if dirty: - lst.Save() - -def AddErrorMessage(doc, errmsg, *args): - doc.AddItem(Header(3, Italic(FontAttr(errmsg % args, - color="#ff66cc")))) - - -_config_info = None -def GetConfigOptions(lst, category): - global _config_info - if _config_info == None: - _config_info = lst.GetConfigInfo() - return _config_info[category] - -if __name__ == "__main__": - try: - main() - except KeyboardInterrupt: - print "Interrupted!" - raise SystemExit, 0 - except mm_err.MMUnknownListError, msg: - FormatAdminOverview(error="List <em>%s</em> not found." % list_name) - except: - print "Content-type: text/html\n" - - print "<p><h3>We're sorry, we hit a bug!</h3>\n" - print "If you would like to help us identify the problem, please " - print "email a copy of this page to the webmaster for this site" - print 'with a description of what happened. Thanks!' - print "\n<PRE>" - try: - import traceback - sys.stderr = sys.stdout - traceback.print_exc() - except: - print "[failed to get traceback]" - print "\n\n</PRE>" +
\ No newline at end of file diff --git a/cgi/admindb b/cgi/admindb index caefc4e27..c6b5bc25e 100755 --- a/cgi/admindb +++ b/cgi/admindb @@ -16,225 +16,10 @@ # along with this program; if not, write to the Free Software # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -"""Produce and process the pending-approval items for a list.""" +import paths -import sys -import os, cgi, string, crypt, types -import paths # path hacking -import mm_utils, maillist, mm_err, htmlformat +def admindb(): + import Mailman.Cgi.admindb -try: - sys.stderr = mm_utils.StampedLogger("error", label = 'admindb', - manual_reprime=1, nofail=0) -except IOError: - pass # Oh well - SOL on redirect, errors show thru. - - -doc = htmlformat.Document() - -path = os.environ['PATH_INFO'] -list_info = mm_utils.GetPathPieces(path) - - -if len(list_info) < 1: - doc.SetTitle("Admindb Error") - doc.AddItem(htmlformat.Header(2, "Invalid options to CGI script.")) - print doc.Format(bgcolor="#ffffff") - sys.exit(0) -list_name = string.lower(list_info[0]) - -try: - list = maillist.MailList(list_name) -except: - msg = "%s: No such list." % list_name - doc.SetTitle("Admindb Error - %s" % msg) - doc.AddItem(htmlformat.Header(2, msg)) - print doc.Format(bgcolor="#ffffff") - sys.exit(0) - -if not list._ready: - msg = "%s: No such list." % list_name - doc.SetTitle("Admindb Error - %s" % msg) - doc.AddItem(htmlformat.Header(2, msg)) - print doc.Format(bgcolor="#ffffff") - sys.exit(0) - -# Note, these 2 functions use i only to count the number of times to -# go around. We always operate on the first element of the list -# because we're going to delete the element after we operate on it. - -def SubscribeAll(): - for i in range(len(list.requests['add_member'])): - comment_key = 'comment-%d' % list.requests['add_member'][0][0] - if form.has_key(comment_key): - list.HandleRequest(('add_member', 0), 1, form[comment_key].value) - else: - list.HandleRequest(('add_member', 0), 1) - -def SubscribeNone(): - for i in range(len(list.requests['add_member'])): - comment_key = 'comment-%d' % list.requests['add_member'][0][0] - if form.has_key(comment_key): - list.HandleRequest(('add_member', 0), 0, form[comment_key].value) - else: - list.HandleRequest(('add_member', 0), 0) - -def PrintHeader(str, error=0): - if error: - it = htmlformat.FontAttr(str, color="ff5060") - else: - it = str - doc.AddItem(htmlformat.Header(3, htmlformat.Italic(it))) - doc.AddItem('<hr>') - -def HandleRequests(doc): - if not form.has_key('adminpw'): - PrintHeader('You need to supply the admin password ' - 'to answer requests.', error=1) - return - try: - list.ConfirmAdminPassword(form['adminpw'].value) - except: - PrintHeader('Incorrect admin password.', error=1) - return - ignore_subscribes = 0 - if form.has_key('subscribe_all'): - ignore_subscribes = 1 - SubscribeAll() - elif form.has_key('subscribe_none'): - ignore_subscribes = 1 - SubscribeNone() - for k in form.keys(): - try: - # XXX Security?! - v = eval(form[k].value) - request_id = eval(k) - except: # For stuff like adminpw - continue - if type(request_id) <> types.IntType: - continue - try: - request = list.GetRequest(request_id) - except mm_err.MMBadRequestId: - continue # You've already changed the database. No biggie. - if ignore_subscribes and request[0] == 'add_member': - # We already handled this request. - continue - comment_key = 'comment-%d' % request_id - if form.has_key(comment_key): - list.HandleRequest(request, v, form[comment_key].value) - else: - list.HandleRequest(request, v) - list.Save() - PrintHeader('Database Updated...') - - -def PrintAddMemberRequest(val, table): - table.AddRow([ - val[3], - htmlformat.RadioButtonArray(val[0], ("Refuse", "Subscribe")), - htmlformat.TextBox("comment-%d" % val[0], size=50) - ]) - -def PrintPostRequest(val, form): - t = htmlformat.Table(cellspacing=10) - t.AddRow([ - htmlformat.FontSize("+1", - htmlformat.Bold('Post held because: ')), - val[3]]) - t.AddRow([ - htmlformat.FontSize("+1", - htmlformat.Bold('Action to take on this post:')), - htmlformat.RadioButtonArray(val[0], ("Approve", "Reject", - "Discard (eg, spam)")), - htmlformat.SubmitButton('submit', 'Submit All Data') - ]) - t.AddRow([ - htmlformat.FontSize("+1", - htmlformat.Bold('If you reject this post, ' - 'explain (optional):')), - htmlformat.TextBox("comment-%d" % val[0], size=50)]) - - cur_row = t.GetCurrentRowIndex() - cur_col = t.GetCurrentCellIndex() - t.AddCellInfo(cur_row, cur_col, colspan=3) - - t.AddRow([ - htmlformat.FontSize("+1", - htmlformat.Bold('Contents:'))]) - form.AddItem(t) - form.AddItem(htmlformat.Preformatted(val[2][1])) - form.AddItem('<p>') - - -def PrintRequests(doc): - # The only types of requests we know about are add_member and post. - # Anything else that might have gotten in here somehow we'll just - # ignore (This should never happen unless someone is hacking at - # the code). - - doc.AddItem(htmlformat.Header(2, "Administrative requests for " - "'%s' mailing list" % list.real_name)) - doc.AddItem(htmlformat.FontSize("+1", htmlformat.Link( - list.GetRelativeScriptURL('admin'), htmlformat.Italic( - 'View or edit the list configuration information')))) - doc.AddItem('<p><hr>') - if not list.RequestsPending(): - doc.AddItem(htmlformat.Header(3,'There are no pending requests.')) - doc.AddItem(list.GetMailmanFooter()) - return - form = htmlformat.Form(list.GetRelativeScriptURL('admindb')) - doc.AddItem(form) - form.AddItem('Admin password: ') - form.AddItem(htmlformat.PasswordBox('adminpw')) - form.AddItem('<p>') - if list.requests.has_key('add_member'): -## form.AddItem('<hr>') -## t = htmlformat.Table(cellspacing=10) -## t.AddRow([ -## htmlformat.SubmitButton('submit', 'Submit All Data'), -## htmlformat.SubmitButton('subscribe_all', 'Subscribe Everybody'), -## htmlformat.SubmitButton('subscribe_none', 'Refuse Everybody') -## ]) -## form.AddItem(t) - form.AddItem('<hr>') - form.AddItem(htmlformat.Center( - htmlformat.Header(2, 'Subscription Requests'))) - t = htmlformat.Table(border=2) - t.AddRow([ - htmlformat.Bold('Email'), - htmlformat.Bold('Descision'), - htmlformat.Bold('Reasoning for subscription refusal (optional)')]) - for request in list.requests['add_member']: - PrintAddMemberRequest(request, t) - - form.AddItem(t) - t = htmlformat.Table(cellspacing=10) - t.AddRow([ - htmlformat.SubmitButton('submit', 'Submit All Data'), - htmlformat.SubmitButton('subscribe_all', 'Subscribe Everybody'), - htmlformat.SubmitButton('subscribe_none', 'Refuse Everybody') - ]) - form.AddItem(t) - - # Print submitit buttons... - if list.requests.has_key('post'): - for request in list.requests['post']: - form.AddItem('<hr>') - form.AddItem(htmlformat.Center(htmlformat.Header(2, "Held Message"))) - PrintPostRequest(request, form) - doc.AddItem(list.GetMailmanFooter()) - -try: - form = cgi.FieldStorage() - if len(form.keys()): - doc.SetTitle("%s Admindb Results" % list.real_name) - HandleRequests(doc) - else: - doc.SetTitle("%s Admindb" % list.real_name) - PrintRequests(doc) - text = doc.Format(bgcolor="#ffffff") - print text - sys.stdout.flush() -finally: - list.Unlock() +from Mailman.runcgi import * +wrap_func(admindb) diff --git a/cgi/archives b/cgi/archives index 3640e0166..782cdcd20 100755 --- a/cgi/archives +++ b/cgi/archives @@ -1,4 +1,4 @@ -#! /usr/bin/env/python +#! /usr/bin/env python # # Copyright (C) 1998 by the Free Software Foundation, Inc. # @@ -16,79 +16,10 @@ # along with this program; if not, write to the Free Software # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -# This script is being deprecated, in favor hookups for an external archiver. +import paths -# We don't need to lock in this script, because we're never going to change -# data. +def archives(): + import Mailman.Cgi.archives -import sys -import os, types, posix, string -import paths # path hacking -import mm_utils, maillist, htmlformat - -try: - sys.stderr = mm_utils.StampedLogger("error", label = 'archives', - manual_reprime=1, nofail=0) -except IOError: - pass # Oh well - SOL on redirect, errors show thru. - - -print "Content-type: text/html" -print - -path = os.environ['PATH_INFO'] -list_info = mm_utils.GetPathPieces(path) - -if len(list_info) < 1: - print "<h2>Invalid options to CGI script.</h2>" - sys.exit(0) - -list_name = string.lower(list_info[0]) - -try: - list = maillist.MailList(list_name) -except: - print "<h2>%s: No such list.</h2>" % list_name - sys.exit(0) - -if not list._ready: - print "<h2>%s: No such list.</h2>" % list_name - sys.exit(0) - -def GetArchiveList(list): - archive_list = htmlformat.UnorderedList() - - def ArchiveFilter(str): - if str[:7] <> 'volume_': - return 0 - try: - x = eval(str[7:]) - if type(x) <> types.IntType: - return 0 - if x < 1: - return 0 - return 1 - except: - return 0 - try: - dir_listing = filter(ArchiveFilter, os.listdir(list.archive_directory)) - except posix.error: - return "<h3><em>No archives are currently available.</em></h3>" - if not len(dir_listing): - return "<h3><em>No archives are currently available.</em></h3>" - for dir in dir_listing: - link = htmlformat.Link(os.path.join(list._base_archive_url, dir), - "Volume %s" % dir[7:]) - archive_list.AddItem(link) - - return archive_list.Format() - - - - -replacements = list.GetStandardReplacements() -replacements['<mm-archive-list>'] = GetArchiveList(list) - -# Just doing print list.ParseTags(...) calls ParseTags twice??? -text = list.ParseTags('archives.html', replacements) -print text +from Mailman.runcgi import * +wrap_func(archives) diff --git a/cgi/edithtml b/cgi/edithtml index 509bf25a7..7b6574da2 100755 --- a/cgi/edithtml +++ b/cgi/edithtml @@ -16,160 +16,10 @@ # along with this program; if not, write to the Free Software # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -"""Script which implements admin editing of the list's html templates.""" +import paths -import sys -import os, cgi, string, crypt, types -import paths # path hacking -import mm_utils, maillist, mm_cfg -import htmlformat +def edithtml(): + import Mailman.Cgi.edithtml -try: - sys.stderr = mm_utils.StampedLogger("error", label = 'edithtml', - manual_reprime=1, nofail=0) -except IOError: - pass # Oh well - SOL on redirect, errors show thru. - - -#Editable templates. We should also be able to edit the archive index, which -#currently isn't a working template, but will be soon. - -template_data = (('listinfo.html', 'General list information page'), - ('subscribe.html', 'Subscribe results page'), - ('options.html', 'User specific options page'), - ('handle_opts.html', 'Changing user options results page'), - ('archives.html', 'Archives index page') - ) - - -def InitDocument(): - return htmlformat.HeadlessDocument() - -doc = InitDocument() - -path = os.environ['PATH_INFO'] -list_info = mm_utils.GetPathPieces(path) - -if len(list_info) < 1: - doc.AddItem(htmlformat.Header(2, "Invalid options to CGI script.")) - print doc.Format() - sys.exit(0) - -list_name = string.lower(list_info[0]) - -try: - list = maillist.MailList(list_name, lock=0) -except: - doc.AddItem(htmlformat.Header(2, "%s : No such list" % list_name)) - print doc.Format() - sys.exit(0) - -if not list._ready: - doc.AddItem(htmlformat.Header(2, "%s : No such list" % list_name)) - print doc.Format() - sys.exit(0) - - -if len(list_info) > 1: - template_name = list_info[1] - for (template, info) in template_data: - if template == template_name: - template_info = info - doc.SetTitle('%s -- Edit html for %s' % - (list.real_name, template_info)) - break - else: - doc.SetTitle('Edit HTML : Error') - doc.AddItem(htmlformat.Header(2, "%s: Invalid template" % template_name)) - doc.AddItem(list.GetMailmanFooter()) - print doc.Format() - sys.exit(0) -else: - doc.SetTitle('%s -- HTML Page Editing' % list.real_name) - doc.AddItem(htmlformat.Header(1, '%s -- HTML Page Editing' % list.real_name)) - doc.AddItem(htmlformat.Header(2, 'Select page to edit:')) - template_list = htmlformat.UnorderedList() - for (template, info) in template_data: - l = htmlformat.Link(os.path.join(list.GetRelativeScriptURL('edithtml'), - template), info) - - template_list.AddItem(l) - doc.AddItem(htmlformat.FontSize("+2", template_list)) - doc.AddItem(list.GetMailmanFooter()) - print doc.Format() - sys.exit(0) - - -def FormatHTML(doc): - doc.AddItem(htmlformat.Header(1,'%s:' % list.real_name)) - doc.AddItem(htmlformat.Header(1, template_info)) - - doc.AddItem('<hr>') - - link = htmlformat.Link(list.GetRelativeScriptURL('admin'), - 'View or edit the list configuration information.') - doc.AddItem(htmlformat.FontSize("+1", link)) - doc.AddItem('<p>') - - doc.AddItem('<hr>') - - form = htmlformat.Form(os.path.join(list.GetRelativeScriptURL('edithtml'), - template_name)) - doc.AddItem(form) - - password_table = htmlformat.Table() - password_table.AddRow(['Enter the admin password to edit html:', - htmlformat.PasswordBox('adminpw')]) - password_table.AddRow(['When you are done making changes...', - htmlformat.SubmitButton('submit', 'Submit Changes')]) - - form.AddItem(password_table) - - text = mm_utils.QuoteHyperChars(list.SnarfHTMLTemplate(template_name)) - form.AddItem(htmlformat.TextArea('html_code', text, rows=40, cols=75)) - -def ChangeHTML(list, cgi_info, template_name, doc): - if not cgi_info.has_key('html_code'): - doc.AddItem(htmlformat.Header(3,"Can't have empty html page.")) - doc.AddItem(htmlformat.Header(3,"HTML Unchanged.")) - doc.AddItem('<hr>') - return - code = cgi_info['html_code'].value - f = open(os.path.join(list._template_dir, template_name), 'w') - f.write(code) - f.close() - doc.AddItem(htmlformat.Header(3, 'HTML successfully updated.')) - doc.AddItem('<hr>') - -try: - cgi_data = cgi.FieldStorage() - if len(cgi_data.keys()): - if not cgi_data.has_key('adminpw'): - m = 'Error: You must supply the admin password to edit html.' - doc.AddItem(htmlformat.Header(3, - htmlformat.Italic( - htmlformat.FontAttr( - m, color="ff5060")))) - doc.AddItem('<hr>') - else: - try: - list.ConfirmAdminPassword(cgi_data['adminpw'].value) - ChangeHTML(list, cgi_data, template_name, doc) - except: - m = 'Error: Incorrect admin password.' - doc.AddItem(htmlformat.Header(3, - htmlformat.Italic( - htmlformat.FontAttr( - m, color="ff5060")))) - doc.AddItem('<hr>') - - - - FormatHTML(doc) - -finally: - try: - doc.AddItem(list.GetMailmanFooter()) - print doc.Format() - except: - pass +from Mailman.runcgi import * +wrap_func(edithtml) diff --git a/cgi/handle_opts b/cgi/handle_opts index 45a98858c..f43fb99ef 100755 --- a/cgi/handle_opts +++ b/cgi/handle_opts @@ -16,199 +16,10 @@ # along with this program; if not, write to the Free Software # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -"""Process input to user options form.""" +import paths -import sys -import os, cgi, string -import paths # path hacking -import mm_utils, maillist, mm_err, mm_cfg, htmlformat +def handle_opts(): + import Mailman.Cgi.handle_opts -try: - sys.stderr = mm_utils.StampedLogger("error", label = 'handle_opts', - manual_reprime=1, nofail=0) -except IOError: - pass # Oh well - SOL on redirect, errors show thru. - - -doc = htmlformat.Document() - -path = os.environ['PATH_INFO'] -list_info = mm_utils.GetPathPieces(path) - -if len(list_info) < 2: - doc.AddItem(htmlformat.Header(2, "Error")) - doc.AddItem(htmlformat.Bold("Invalid options to CGI script.")) - print doc.Format(bgcolor="#ffffff") - sys.exit(0) - -list_name = string.lower(list_info[0]) -user = list_info[1] - -if len(list_info) < 2: - doc.AddItem(htmlformat.Header(2, "Error")) - doc.AddItem(htmlformat.Bold("Invalid options to CGI script.")) - print doc.Format(bgcolor="#ffffff") - sys.exit(0) - -try: - list = maillist.MailList(list_name) -except: - doc.AddItem(htmlformat.Header(2, "Error")) - doc.AddItem(htmlformat.Bold("%s: No such list." % list_name)) - print doc.Format(bgcolor="#ffffff") - sys.exit(0) - -if not list._ready: - doc.AddItem(htmlformat.Header(2, "Error")) - doc.AddItem(htmlformat.Bold("%s: No such list." % list_name)) - print doc.Format(bgcolor="#ffffff") - list.Unlock() - sys.exit(0) - - -def PrintResults(results): - replacements = list.GetStandardReplacements() - replacements['<mm-results>'] = results - replacements['<mm-operation>'] = operation - output = list.ParseTags('handle_opts.html', replacements) - - doc.AddItem(output) - print doc.Format(bgcolor="#ffffff") - list.Unlock() - sys.exit(0) - -form = cgi.FieldStorage() - -error = 0 -operation = "" - -if string.lower(user) not in list.members + list.digest_members: - PrintResults("%s not a member!<p>" % user) - -if form.has_key("unsub"): - operation = "Unsubscribe" - if not form.has_key("upw"): - PrintResults("You must give your password to unsubscribe.<p>") - else: - try: - pw = form["upw"].value - if list.ConfirmUserPassword(user, pw): - list.DeleteMember(user, "web cmd") - except mm_err.MMListNotReady: - PrintResults("List is not functional.") - except mm_err.MMNoSuchUserError: - PrintResults("You seem to already be not a member.<p>") - except mm_err.MMBadUserError: - PrintResults("Your account has gone awry - " - "please contact the list administrator!<p>") - except mm_err.MMBadPasswordError: - PrintResults("That password was incorrect.<p>") -# except: -# PrintResults('''An unknown error occured. <p> -#Please send mail to <a href=%s>%s</a> explaining -#exactly what you did to get this error.<p>''' % (mm_cfg.MAILMAN_OWNER, -# mm_cfg.MAILMAN_OWNER)) - - PrintResults("You have been unsubscribed.<p>") -elif form.has_key("emailpw"): - try: - list.MailUserPassword(user) - PrintResults("A reminder of your password " - "has been emailed to you.<p>") - except mm_err.MMBadUserError: - PrintResults("Your password entry has not been found. The list " - "manager is being notified.<p>") - -elif form.has_key("changepw"): - if (form.has_key('opw') - and form.has_key('newpw') - and form.has_key('confpw')): - try: - list.ConfirmUserPassword(user, form['opw'].value) - list.ChangeUserPassword(user, - form['newpw'].value, form['confpw'].value) - except mm_err.MMListNotReady: - PrintResults("The list is currently not funcitonal.") - except mm_err.MMNotAMemberError: - PrintResults("You seem to no longer be a list member.") - except mm_err.MMBadPasswordError: - PrintResults("The old password you supplied was incorrect.") - except mm_err.MMPasswordsMustMatch: - PrintResults("Passwords must match.") - except: - PrintResults('''An unknown error occured. <p> -Please send mail to <a href=%s>%s</a> explaining -exactly what you did to get this error.<p>''' % (mm_cfg.MAILMAN_OWNER, mm_cfg.MAILMAN_OWNER)) - - - PrintResults("Your password has been changed.") - else: - PrintResults("You must supply your old password," - " and your new password twice.") - -else: - # If keys don't exist, set them to whatever they were. (essentially a noop) - if form.has_key("digest"): - digest_value = eval(form["digest"].value) - else: - digest_value = list.GetUserOption(user, mm_cfg.Digests) - if form.has_key("mime"): - mime = eval(form["mime"].value) - else: - mime = list.GetUserOption(user, mm_cfg.DisableMime) - if form.has_key("dontreceive"): - dont_receive = eval(form["dontreceive"].value) - else: - dont_receive = list.GetUserOption(user, mm_cfg.DontReceiveOwnPosts) - if form.has_key("ackposts"): - ack_posts = eval(form["ackposts"].value) - else: - ack_posts = list.GetUserOption(user, mm_cfg.AcknowlegePosts) - if form.has_key("disablemail"): - disable_mail = eval(form["disablemail"].value) - else: - disable_mail = list.GetUserOption(user, mm_cfg.DisableDelivery) - if form.has_key("conceal"): - conceal = eval(form["conceal"].value) - else: - conceal = list.GetUserOption(user, mm_cfg.ConcealSubscription) - - if not form.has_key("digpw"): - PrintResults("You must supply a password to change options.") - try: - list.ConfirmUserPassword(user, form['digpw'].value) - except mm_err.MMAlreadyDigested: - pass - except mm_err.MMAlreadyUndigested: - pass - except mm_err.MMMustDigestError: - PrintResults("List only accepts digest members.") - except mm_err.MMCantDigestError: - PrintResults("List doesn't accept digest members.") - except mm_err.MMNotAMemberError: - PrintResults("%s isn't subscribed to this list." % mail.GetSender()) - except mm_err.MMListNotReady: - PrintResults("List is not functional.") - except mm_err.MMNoSuchUserError: - PrintResults("%s is not subscribed to this list." %mail.GetSender()) - except mm_err.MMBadPasswordError: - PrintResults("You gave the wrong password.") - except: - PrintResults('''An unknown error occured. <p> -Please send mail to <a href=%s>%s</a> explaining -exactly what you did to get this error.<p>''' % (mm_cfg.MAILMAN_OWNER)) - - - list.SetUserOption(user, mm_cfg.DisableDelivery, disable_mail) - list.SetUserOption(user, mm_cfg.DontReceiveOwnPosts, dont_receive) - list.SetUserOption(user, mm_cfg.AcknowlegePosts, ack_posts) - list.SetUserOption(user, mm_cfg.DisableMime, mime) - try: - list.SetUserDigest(user, digest_value) - except (mm_err.MMAlreadyDigested, mm_err.MMAlreadyUndigested): - pass - list.SetUserOption(user, mm_cfg.ConcealSubscription, conceal) - PrintResults("You have successfully set your options.") - - -list.Unlock()
\ No newline at end of file +from Mailman.runcgi import * +wrap_func(handle_opts) diff --git a/cgi/listinfo b/cgi/listinfo index b32cfbfd1..cdb6976a6 100755 --- a/cgi/listinfo +++ b/cgi/listinfo @@ -16,171 +16,11 @@ # along with this program; if not, write to the Free Software # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -"""Produce listinfo page, primary web entry-point to maillists. +import paths -Errors are redirected to logs/errors.""" +def listinfo(): + import Mailman.Cgi.listinfo + Mailman.Cgi.listinfo.main() -# No lock needed in this script, because we don't change data. - -import sys -import os, string -from regsub import gsub -import paths # path hacking -import mm_utils, maillist, mm_cfg -from htmlformat import * - -try: - sys.stderr = mm_utils.StampedLogger("error", label = 'listinfo', - manual_reprime=1, nofail=0) -except IOError: - pass # Oh well - SOL on redirect, errors show thru. - -def main(): - try: - path = os.environ['PATH_INFO'] - except KeyError: - path = "" - - list_info = mm_utils.GetPathPieces(path) - - if len(list_info) == 0: - FormatListinfoOverview() - return - - list_name = string.lower(list_info[0]) - - try: - list = maillist.MailList(list_name, lock=0) - except: - list = None - - if not (list and list._ready): - FormatListinfoOverview(error="List <em>%s</em> not found." % list_name) - return - - FormatListListinfo(list) - -def FormatListinfoOverview(error=None): - "Present a general welcome and itemize the (public) lists for this host." - doc = Document() - legend = "%s maillists" % mm_cfg.DEFAULT_HOST_NAME - doc.SetTitle(legend) - - table = Table(border=0, width="100%") - table.AddRow([Center(Header(2, legend))]) - table.AddCellInfo(max(table.GetCurrentRowIndex(), 0), 0, - colspan=2, bgcolor="#99ccff") - - advertised = [] - names = mm_utils.list_names() - names.sort() - - # XXX We need a portable way to determine the host by which we are being - # visited! An absolute URL would do... - if os.environ.has_key('HTTP_HOST'): - http_host = os.environ['HTTP_HOST'] - else: - http_host = None - - for n in names: - l = maillist.MailList(n, lock = 0) - if l.advertised: - if (http_host - and (string.find(http_host, l.host_name) == -1 - and string.find(l.host_name, http_host) == -1)): - # List is for different identity for this host - skip it. - continue - else: - advertised.append(l) - - if error: - greeting = FontAttr(error, color="ff5060", size="+1") - else: - greeting = "Welcome!" - - if not advertised: - welcome_items = (greeting, - "<p>" - " There currently are no publicly-advertised ", - Link(mm_cfg.MAILMAN_URL, "mailman"), - " maillists on %s." % mm_cfg.DEFAULT_HOST_NAME, - ) - else: - - welcome_items = ( - greeting, - "<p>" - " Below is the collection of publicly-advertised ", - Link(mm_cfg.MAILMAN_URL, "mailman"), - " maillists on %s." % mm_cfg.DEFAULT_HOST_NAME, - (' Click on a list name to visit the info page' - ' for that list. There you can learn more about the list,' - ' subscribe to it, or find the roster of current subscribers.'), - ) - - welcome_items = (welcome_items + - (" To visit the info page for an unadvertised list," - " open a URL similar to this one, but with a '/' and" - + - (" the %slist name appended." - % ((error and "right ") or "")) - + - '<p> List administrators, you can visit ', - Link(os.path.join('../' * mm_utils.GetNestingLevel(), - 'admin/'), "the list admin overview page"), - " to find the management interface for your list." - "<p>(Send questions or comments to ", - Link("mailto:%s" % mm_cfg.MAILMAN_OWNER, - mm_cfg.MAILMAN_OWNER), - ".)<p>")) - - table.AddRow([apply(Container, welcome_items)]) - table.AddCellInfo(max(table.GetCurrentRowIndex(), 0), 0, colspan=2) - - if advertised: - table.AddRow([Italic("List"), Italic("Description")]) - for l in advertised: - table.AddRow([Link(l.GetRelativeScriptURL('listinfo'), - Bold(l.real_name)), l.description]) - - doc.AddItem(table) - - print doc.Format(bgcolor="#ffffff") - -def FormatListListinfo(list): - "Expand the listinfo template against the list's settings, and print." - - doc = HeadlessDocument() - - replacements = list.GetStandardReplacements() - - if not list.digestable or not list.nondigestable: - replacements['<mm-digest-radio-button>'] = "" - replacements['<mm-undigest-radio-button>'] = "" - else: - replacements['<mm-digest-radio-button>'] = list.FormatDigestButton() - replacements['<mm-undigest-radio-button>'] = \ - list.FormatUndigestButton() - replacements['<mm-plain-digests-button>'] = list.FormatPlainDigestsButton() - replacements['<mm-mime-digests-button>'] = list.FormatMimeDigestsButton() - replacements['<mm-subscribe-box>'] = list.FormatBox('email') - replacements['<mm-subscribe-button>'] = list.FormatButton('email-button', - text='Subscribe') - replacements['<mm-new-password-box>'] = list.FormatSecureBox('pw') - replacements['<mm-confirm-password>'] = list.FormatSecureBox('pw-conf') - replacements['<mm-subscribe-form-start>'] = \ - list.FormatFormStart('subscribe') - replacements['<mm-roster-form-start>'] = list.FormatFormStart('roster') - replacements['<mm-editing-options>'] = list.FormatEditingOption() - replacements['<mm-info-button>'] = SubmitButton('UserOptions', - 'Edit Options').Format() - replacements['<mm-roster-option>'] = list.FormatRosterOptionForUser() - - # Do the expansion. - doc.AddItem(list.ParseTags('listinfo.html', replacements)) - - print doc.Format() - - -if __name__ == "__main__": - main() +from Mailman.runcgi import * +wrap_func(listinfo) diff --git a/cgi/options b/cgi/options index 2dcf3d666..60cabfd9d 100755 --- a/cgi/options +++ b/cgi/options @@ -16,120 +16,10 @@ # along with this program; if not, write to the Free Software # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -"""Produce user options form, from list options.html template. +import paths -Takes listname/userid in PATH_INFO, expecting an `obscured' userid. Depending -on the mm_utils.{O,Uno}bscureEmail utilities tolerance, will work fine with an -unobscured ids as well. +def options(): + import Mailman.Cgi.options -""" - -# We don't need to lock in this script, because we're never going to change -# data. - -import sys -import os, string -import paths # path hacking -import mm_utils, maillist, htmlformat, mm_cfg - -try: - sys.stderr = mm_utils.StampedLogger("error", label = 'options', - manual_reprime=1, nofail=0) -except IOError: - pass # Oh well - SOL on redirect, errors show thru. - -doc = htmlformat.HeadlessDocument() - -try: - path = os.environ['PATH_INFO'] -except KeyError: - path = "" -list_info = mm_utils.GetPathPieces(path) - -if len(list_info) < 2: - doc.AddItem(htmlformat.Header(2, "Error")) - doc.AddItem(htmlformat.Bold("Invalid options to CGI script.")) - print doc.Format() - sys.exit(0) - -list_name = string.lower(list_info[0]) -user = mm_utils.UnobscureEmail(list_info[1]) - -try: - list = maillist.MailList(list_name) -except: - doc.AddItem(htmlformat.Header(2, "Error")) - doc.AddItem(htmlformat.Bold("%s: No such list." % list_name )) - print doc.Format() - sys.exit(0) - -if not list._ready: - doc.AddItem(htmlformat.Header(2, "Error")) - doc.AddItem(htmlformat.Bold("%s: No such list." % list_name )) - print doc.Format() - list.Unlock() - sys.exit(0) - -if string.lower(user) not in list.members + list.digest_members: - doc.AddItem(htmlformat.Header(2, "Error")) - doc.AddItem(htmlformat.Bold("%s: No such member %s." - % (list_name, `user`))) - doc.AddItem(list.GetMailmanFooter()) - print doc.Format() - list.Unlock() - sys.exit(0) - -# Re-obscure the user's address for the page banner if obscure_addresses set. -if list.obscure_addresses: - presentable_user = mm_utils.ObscureEmail(user, for_text=1) -else: - presentable_user = user - -replacements = list.GetStandardReplacements() -replacements['<mm-digest-radio-button>'] = list.FormatOptionButton( - mm_cfg.Digests, 1, user) -replacements['<mm-undigest-radio-button>'] = list.FormatOptionButton( - mm_cfg.Digests, 0, user) -replacements['<mm-plain-digests-button>'] = list.FormatOptionButton( - mm_cfg.DisableMime, 1, user) -replacements['<mm-mime-digests-button>'] = list.FormatOptionButton( - mm_cfg.DisableMime, 0, user) -replacements['<mm-delivery-enable-button>'] = list.FormatOptionButton( - mm_cfg.DisableDelivery, 0, user) -replacements['<mm-delivery-disable-button>'] = list.FormatOptionButton( - mm_cfg.DisableDelivery, 1, user) -replacements['<mm-disabled-notice>'] = list.FormatDisabledNotice(user) -replacements['<mm-dont-ack-posts-button>'] = list.FormatOptionButton( - mm_cfg.AcknowlegePosts, 0, user) -replacements['<mm-ack-posts-button>'] = list.FormatOptionButton( - mm_cfg.AcknowlegePosts, 1, user) -replacements['<mm-receive-own-mail-button>'] = list.FormatOptionButton( - mm_cfg.DontReceiveOwnPosts, 0, user) -replacements['<mm-dont-receive-own-mail-button>'] = list.FormatOptionButton( - mm_cfg.DontReceiveOwnPosts, 1, user) -replacements['<mm-public-subscription-button>'] = list.FormatOptionButton( - mm_cfg.ConcealSubscription, 0, user) -replacements['<mm-hide-subscription-button>'] = list.FormatOptionButton( - mm_cfg.ConcealSubscription, 1, user) - -replacements['<mm-digest-submit>'] = list.FormatButton('setdigest', - 'Submit My Changes') -replacements['<mm-unsubscribe-button>'] = list.FormatButton('unsub', 'Unsubscribe') -replacements['<mm-digest-pw-box>'] = list.FormatSecureBox('digpw') -replacements['<mm-unsub-pw-box>'] = list.FormatSecureBox('upw') -replacements['<mm-old-pw-box>'] = list.FormatSecureBox('opw') -replacements['<mm-new-pass-box>'] = list.FormatSecureBox('newpw') -replacements['<mm-confirm-pass-box>'] = list.FormatSecureBox('confpw') -replacements['<mm-change-pass-button>'] = list.FormatButton('changepw', - "Change My Password") -replacements['<mm-form-start>'] = list.FormatFormStart('handle_opts', user) -replacements['<mm-user>'] = user -replacements['<mm-presentable-user>'] = presentable_user -replacements['<mm-email-my-pw>'] = list.FormatButton('emailpw', - 'Email My Password To Me') - - -doc.AddItem(list.ParseTags('options.html', replacements)) -print doc.Format() - -list.Unlock()
\ No newline at end of file +from Mailman.runcgi import * +wrap_func(options) diff --git a/cgi/private b/cgi/private index facca81bc..b2c4301ac 100755 --- a/cgi/private +++ b/cgi/private @@ -1,4 +1,4 @@ -#! /usr/bin/env python -u +#! /usr/bin/env python # # Copyright (C) 1998 by the Free Software Foundation, Inc. # @@ -16,219 +16,11 @@ # 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 a hierarchy of web pages. +import paths -Currently this is organized to obtain passwords for mailman maillist -subscribers. +def private(): + import Mailman.Cgi.private + Mailman.Cgi.private.main() - - Set the ROOT variable to point to the root of your archives private - hierarchy. The script will look there for the private archive files. - - Put the ../misc/Cookie.py script in ../../cgi-bin (where the wrapper - executables are). -""" - -import sys, os, string, re -import paths # path hacking -import maillist, mm_err, mm_utils -import Cookie - -sys.stderr = sys.stdout - -ROOT = "/local/pipermail/private/" -SECRET = "secret" # XXX used for hashing - -PAGE = ''' -<html> -<head> - <title>%(listname)s Private Archives Authentication</title> -</head> -<body> -<FORM METHOD=POST ACTION="%(basepath)s/%(path)s"> - <TABLE WIDTH="100%" BORDER="0" CELLSPACING="4" CELLPADDING="5"> - <TR> - <TD COLSPAN="2" WIDTH="100%" BGCOLOR="#99CCFF" ALIGN="CENTER"> - <B><FONT COLOR="#000000" SIZE="+1">%(listname)s Private Archives - Authentication</FONT></B> - </TD> - </TR> - <tr> - <td COLSPAN="2"> <P>%(message)s </td> - <tr> - </tr> - <TD> <div ALIGN="Right">Address: </div></TD> - <TD> <INPUT TYPE=TEXT NAME=username SIZE=30> </TD> - <tr> - </tr> - <TD> <div ALIGN="Right"> Password: </div> </TD> - <TD> <INPUT TYPE=password NAME=password SIZE=30></TD> - <tr> - </tr> - <td></td> - <td> <INPUT TYPE=SUBMIT> - </td> - </tr> - </TABLE> -</FORM> -''' - -login_attempted = 0 -_list = None - -name_pat = re.compile(r""" -(?: / (?: \d{4} q \d\. )? # Match "/", and, optionally, 1998q1." - ( [^/]* ) /? # The SIG name - /[^/]*$ # The trailing 12345.html portion -) | (?: - / ( [^/.]* ) # Match matrix-sig - (?:\.html)? # Optionally match .html - /? # Optionally match a trailing slash - $ # Must match to end of string - -) -""", re.VERBOSE) - -def getListName(path): - match = name_pat.search(path) - if match is None: return - if match.group(1): return match.group(1) - if match.group(2): return match.group(2) - raise ValueError, "Can't identify SIG name" - - -def GetListobj(list_name): - """Return an unlocked instance of the named maillist, if found.""" - global _list - if _list: - return _list - try: - _list = maillist.MailList(list_name) - except mm_err.MMUnknownListError: - _list = None - return None - if _list.Locked(): - _list.Unlock() - return _list - -def isAuthenticated(list_name): - if os.environ.has_key('HTTP_COOKIE'): - c = Cookie.Cookie( os.environ['HTTP_COOKIE'] ) - if c.has_key(list_name): - # The user has a token like 'c++-sig=AE23446AB...'; verify - # that it's correct. - token = c[list_name].value - import base64, md5 - if base64.decodestring(token) != md5.new(SECRET - + list_name - + SECRET).digest(): - return 0 - return 1 - - # No corresponding cookie. OK, then check for username, password - # CGI variables - import cgi - v = cgi.FieldStorage() - username = password = None - if v.has_key('username'): - username = v['username'] - if type(username) == type([]): username = username[0] - username = username.value - if v.has_key('password'): - password = v['password'] - if type(password) == type([]): password = password[0] - password = password.value - - if username is None or password is None: return 0 - - # Record that this is a login attempt, so if it fails the form can - # be displayed with an appropriate message. - global login_attempted - login_attempted=1 - - listobj = GetListobj(list_name) - if not listobj: - print '\n<P>A list named,', repr(list_name), "was not found." - return 0 - - try: - listobj.ConfirmUserPassword( username, password) - except (mm_err.MMBadUserError, mm_err.MMBadPasswordError): - return 1 - - import base64, md5 - token = md5.new(SECRET + list_name + SECRET).digest() - token = base64.encodestring(token) - token = string.strip(token) - c = Cookie.Cookie() - c[list_name] = token - print c # Output the cookie - return 1 - - -def true_path(path): - "Ensure that the path is safe by removing .." - path = string.split(path, '/') - for i in range(len(path)): - if path[i] == ".": path[i] = "" # ./ is just redundant - elif path[i] == "..": - # Remove any .. components - path[i] = "" - j=i-1 - while j>0 and path[j] == "": j=j-1 - path[j] = "" - - path = filter(None, path) - return string.join(path, '/') - -def processPage(page): - """Change any URLs that start with ../ to work properly when output from - /cgi-bin/private""" - # Escape any % signs not followed by ( - page = re.sub('%([^(])', r'%%\1', page) - - # Convert references like HREF="../doc" to just /doc. - page = re.sub('([\'="])../', r'\1/', page) - - return page - -def main(): - path = os.environ.get('PATH_INFO', "/index.html") - true_filename = os.path.join(ROOT, true_path(path) ) - list_name = getListName(path) - - if os.path.isdir(true_filename): - true_filename = true_filename + '/index.html' - - if not isAuthenticated(list_name): - # Output the password form - page = processPage( PAGE ) - - listobj = GetListobj(list_name) - if login_attempted: - message = ("Your email address or password were incorrect." - " Please try again.") - else: - message = ("Please enter your %s subscription email address." - " and password " % listobj.real_name) - while path and path[0] == '/': path=path[1:] # Remove leading /'s - basepath = os.path.split(listobj.GetBaseArchiveURL())[0] - listname = listobj.real_name - print '\n\n', page % vars() - sys.exit(0) - - print '\n\n' - # Authorization confirmed... output the desired file - try: - f = open(true_filename, 'r') - except IOError: - print "<H3>Archive File Not Found</H3>" - print "No file", path - else: - while (1): - data = f.read(16384) - if data == "": break - sys.stdout.write(data) - f.close() - -if __name__ == '__main__': - print 'Content-type: text/html' - main() +from Mailman.runcgi import * +wrap_func(private) diff --git a/cgi/roster b/cgi/roster index 65435e914..56944f24a 100755 --- a/cgi/roster +++ b/cgi/roster @@ -16,107 +16,11 @@ # along with this program; if not, write to the Free Software # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -"""Produce subscriber roster, using listinfo form data, roster.html template. +import paths -Takes listname in PATH_INFO.""" +def roster(): + import Mailman.Cgi.roster + Mailman.Cgi.roster.main() - -# We don't need to lock in this script, because we're never going to change -# data. - -import sys -import os, string -import cgi -import paths # path hacking -import mm_utils, maillist, htmlformat, mm_cfg, mm_err - -try: - sys.stderr = mm_utils.StampedLogger("error", label = 'roster', - manual_reprime=1, nofail=0) -except IOError: - pass # Oh well - SOL on redirect, errors show thru. - - -def main(): - doc = htmlformat.HeadlessDocument() - form = cgi.FieldStorage() - list = get_list() - - bad = "" - # These nested conditionals constituted a cascading authentication - # check, yielding a - if not list.private_roster: - # No privacy. - bad = "" - else: - auth_req = ("%s subscriber list requires authentication." - % list.real_name) - if not form.has_key("roster-pw"): - bad = auth_req - else: - pw = form['roster-pw'].value - # Just the admin password is sufficient - check it early. - if not list.ValidAdminPassword(pw): - if not form.has_key('roster-email'): - # No admin password and no user id, nogo. - bad = auth_req - else: - id = form['roster-email'].value - if list.private_roster == 1: - # Private list - members visible. - try: - list.ConfirmUserPassword(id, pw) - except (mm_err.MMBadUserError, - mm_err.MMBadPasswordError): - bad = ("%s subscriber authentication failed." - % list.real_name) - else: - # Anonymous list - admin-only visible - # - and we already tried admin password, above. - bad = ("%s admin authentication failed." - % list.real_name) - if bad: - doc = error_page_doc(bad) - doc.AddItem(list.GetMailmanFooter()) - print doc.Format() - sys.exit(0) - - replacements = list.GetStandardReplacements() - - doc.AddItem(list.ParseTags('roster.html', replacements)) - print doc.Format() - -def get_list(): - "Return list or bail out with error page." - - list_info = mm_utils.GetPathPieces(os.environ['PATH_INFO']) - if len(list_info) != 1: - error_page("Invalid options to CGI script.") - sys.exit(0) - list_name = string.lower(list_info[0]) - try: - list = maillist.MailList(list_name, lock = 0) - except mm_err.MMUnknownListError: - error_page("%s: No such list.", list_name) - sys.exit(0) - if not list._ready: - error_page("%s: No such list.", list_name) - sys.exit(0) - list.Unlock() - return list - -def error_page(errmsg, *args): - print apply(error_page_doc, (errmsg,) + args).Format() - -def error_page_doc(errmsg, *args): - """Produce a simple error-message page on stdout and exit. - - Optional arg justreturn means just return the doc, don't print it.""" - doc = htmlformat.Document() - doc.SetTitle("Error") - doc.AddItem(htmlformat.Header(2, "Error")) - doc.AddItem(htmlformat.Bold(errmsg % args)) - return doc - -if __name__ == "__main__": - main() +from Mailman.runcgi import * +wrap_func(roster) diff --git a/cgi/subscribe b/cgi/subscribe index 38c1601bf..6fe5a7c68 100755 --- a/cgi/subscribe +++ b/cgi/subscribe @@ -16,180 +16,12 @@ # along with this program; if not, write to the Free Software # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -"""Process listinfo form submission, ie subscriptions or roster requests.""" +import paths -import sys -import os, cgi, string -from regsub import gsub -import paths # path hacking -import mm_utils, maillist, mm_err, mm_message, mm_cfg, mm_pending, htmlformat +def subscribe(): + import Mailman.Cgi.subscribe -try: - sys.stderr = mm_utils.StampedLogger("error", label = 'subscribe', - manual_reprime=1, nofail=0) -except IOError: - pass # Oh well - SOL on redirect, errors show thru. +from Mailman.runcgi import * +wrap_func(subscribe) -doc = htmlformat.Document() - -path = os.environ['PATH_INFO'] -list_info = mm_utils.GetPathPieces(path) -list_name = string.lower(list_info[0]) - -if len(list_info) < 1: - doc.AddItem(htmlformat.Header(2, "Error")) - doc.AddItem(htmlformat.Bold("Invalid options to CGI script.")) - print doc.Format() - sys.exit(0) - -try: - list = maillist.MailList(list_name) -except: - doc.AddItem(htmlformat.Header(2, "Error")) - doc.AddItem(htmlformat.Bold("%s: No such list." % list_name )) - print doc.Format() - sys.exit(0) - - -if not list._ready: - doc.AddItem(htmlformat.Header(2, "Error")) - doc.AddItem(htmlformat.Bold("%s: No such list." % list_name )) - print doc.Format() - list.Unlock() - sys.exit(0) - -form = cgi.FieldStorage() - -error = 0 -results = '' - -def call_script(which, pathinfo): - "A little bit of a hack to call one of the scripts..." - os.environ['PATH_INFO'] = string.join(pathinfo, '/') - file = os.path.join(mm_cfg.SCRIPTS_DIR, which) - list.Unlock() - execfile(file) - sys.exit(0) - -####### -# Preliminaries done, actual processing of the form input below. - -if (form.has_key("UserOptions") - or (form.has_key("info") and not form.has_key("email"))): - # Go to user options section. - if not form.has_key("info"): - doc.AddItem(htmlformat.Header(2, "Error")) - doc.AddItem(htmlformat.Bold("You must supply your email address.")) - doc.AddItem(list.GetMailmanFooter()) - print doc.Format() - list.Unlock() - sys.exit(0) - addr = form['info'].value - member = list.FindUser(addr) - if not list.FindUser(addr): - doc.AddItem(htmlformat.Header(2, "Error")) - doc.AddItem(htmlformat.Bold("%s has no subscribed addr <i>%s</i>." - % (list.real_name, addr))) - doc.AddItem(list.GetMailmanFooter()) - print doc.Format() - list.Unlock() - sys.exit(0) - call_script('options', [list._internal_name, member]) -if not form.has_key("email"): - error = 1 - results = results + "You must supply a valid email address.<br>" -else: - email = form["email"].value -if not form.has_key("pw") or not form.has_key("pw-conf"): - error = 1 - results = results + "You must supply a valid password, and confirm it.<br>" -else: - pw = form["pw"].value - pwc = form["pw-conf"].value - -if not error and (pw <> pwc): - error = 1 - results = results + "Your passwords did not match.<br>" - -if form.has_key("digest"): - digest = eval(form["digest"].value) - -if not list.digestable: - digest = 0 -elif not list.nondigestable: - digest = 1 - - -def PrintResults(): - replacements = list.GetStandardReplacements() - replacements['<mm-results>'] = results - output = list.ParseTags('subscribe.html', replacements) - - doc.AddItem(output) - print doc.Format() - list.Unlock() - sys.exit(0) - -if error: - PrintResults() - -else: - try: - results = results + ("Confirmation from your email address is " - "required, to prevent anyone from covertly " - "subscribing you. Instructions are being " - "sent to you at %s." % email) - if os.environ.has_key('REMOTE_HOST'): - remote = os.environ['REMOTE_HOST'] - elif os.environ.has_key('REMOTE_ADDR'): - remote = os.environ['REMOTE_ADDR'] - else: - remote = "." - if digest: - digesting = " digest" - else: - digesting = "" - cookie = mm_pending.gencookie() - mm_pending.add2pending(email, pw, digest, cookie) - list.SendTextToUser(subject = "%s -- confirmation of subscription -- request %d" % \ - (list.real_name, cookie), - recipient = email, - sender = list.GetRequestEmail(), - text = mm_pending.VERIFY_FMT % ({"email": email, - "listaddress": list.GetListEmail(), - "listname": list.real_name, - "cookie": cookie, - "requestor": remote, - "request_addr": list.GetRequestEmail()}), - - add_headers = ["Reply-to: %s" - % list.GetRequestEmail(), - "Errors-To: %s" - % list.GetAdminEmail()]) - except mm_err.MMBadEmailError: - results = results + ("Mailman won't accept the given email " - "address as a valid address. (Does it " - "have an @ in it???)<p>") - except mm_err.MMListNotReady: - results = results + ("The list is not fully functional, and " - "can not accept subscription requests.<p>") -# -# deprecating this, it might be useful if we decide to -# allow approved based subscriptions without confirmation -# -## except mm_err.MMNeedApproval, x: -## results = results + ("Subscription was <em>deferred</em> " -## "because:<br> %s<p>Your request must " -## "be approved by the list admin. " -## "You will receive email informing you " -## "of the moderator's descision when they " -## "get to your request.<p>" % x) - except mm_err.MMHostileAddress: - results = results + ("Your subscription is not allowed because " - "the email address you gave is insecure.<p>") - except mm_err.MMAlreadyAMember: - results = results + "You are already subscribed!<p>" - - -PrintResults() -list.Unlock()
\ No newline at end of file +
\ No newline at end of file |
