#!/usr/local/bin/python """Produce the list-administration web page on stdout. To run stand-alone for debugging, set env var PATH_INFO to name of list.""" import sys sys.path.append('/home/mailman/mailman/modules') import os, cgi, string, crypt, types import mm_utils, maillist, mm_cfg, htmlformat, mm_err try: sys.stderr = mm_utils.StampedLogger("error", label = 'mmroster', manual_reprime=1, nofail=0) except IOError: pass # Oh well - SOL on redirect, errors show thru. def main(): global doc, list_name # For encompassing try/except. doc = htmlformat.Document() 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]) list = maillist.MailList(list_name) try: if not (list and list._ready): doc.AddItem(htmlformat.Header(3, "%s: No such list" % list_name)) print doc.Format() sys.exit(0) info = list.GetConfigInfo() general = info['general'] nodigest = info['nondigest'] digest = info['digest'] archives = info['archive'] # XXX klm - looks like john distinguished some special '.jp' lists if list._internal_name[-3:] <> '.jp': bounce = info['bounce'] else: bounce = [] cgi_data = cgi.FieldStorage() if len(cgi_data.keys()): if not cgi_data.has_key('adminpw'): doc.AddItem('
Note that you can also use the subscriber option to inhibit their
delivery of messages, if you figure the bounces are transient.""" %
list.GetScriptURL('listinfo'))
form.AddItem(list.GetMailmanFooter())
def FormatOptionsSection(name, options, big_table, list):
big_table.AddRow([htmlformat.Center(
htmlformat.Header(2, name))])
big_table.AddCellInfo(max(big_table.GetCurrentRowIndex(), 0), 0,
colspan=2)
big_table.AddRow([htmlformat.Bold('Option'),
htmlformat.Bold('Value')])
item = options[0]
gui_item = GetGuiItem(item, list)
big_table.AddRow([item[4], gui_item])
if len(options) > 1:
if options[0][1] == mm_cfg.Toggle:
big_table.AddRow([htmlformat.Header(2, "If so:")])
big_table.AddCellInfo(big_table.GetCurrentRowIndex(),
0, colspan=2)
for item in options[1:]:
gui_item = GetGuiItem(item, list)
big_table.AddRow([item[4], gui_item])
big_table.AddRow(['
'])
big_table.AddCellInfo(big_table.GetCurrentRowIndex(), 0,
colspan=2)
# XXX klm - looks like turn_on_moderation is orphaned.
turn_on_moderation = 0
def GetValidValue(list, prop, my_type, val, dependant):
if my_type == mm_cfg.Radio or my_type == mm_cfg.Toggle:
if type(val) <> types.IntType:
try:
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(list, 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(list, prop)
return num
except:
return getattr(list, prop)
else:
# Should never get here...
return val
def ChangeOptions(list, opt_list, cgi_info, document):
for item in opt_list:
property, type, args, dependancies, desc = item
if not cgi_info.has_key(property):
if (type <> mm_cfg.Text and
type <> mm_cfg.String and
type <> mm_cfg.EmailList):
continue
else:
val = ''
else:
val = cgi_info[property].value
value = GetValidValue(list, property, type, val,
dependancies)
setattr(list, property, value)
if cgi_info.has_key('subscribees'):
name_text = cgi_info['subscribees'].value
names = string.split(name_text, '\r\n')
for new_name in names:
try:
#FIXME: The admin needs to be able to specify subscribe options
list.AddMember(new_name, (mm_utils.GetRandomSeed() +
mm_utils.GetRandomSeed()))
#FIXME: Give some sort of an indication of which names didn't work,
# and why they didn't work...
except:
pass
if cgi_info.has_key('newpw'):
if cgi_info.has_key('confirmpw'):
new = cgi_info['newpw'].value
confirm = cgi_info['confirmpw'].value
if new == confirm:
list.password = crypt.crypt(new,
mm_utils.GetRandomSeed())
else:
m = 'Error: Passwords did not match.'
document.AddItem(
htmlformat.Header(3,
htmlformat.Italic(
htmlformat.FontAttr(
m, color="ff5060"))))
else:
m = 'Error: You must type in your new password twice.'
document.AddItem(
htmlformat.Header(3,
htmlformat.Italic(
htmlformat.FontAttr(
m, color="ff5060"))))
list.Save()
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.AddItem(htmlformat.Header(2, "Error"))
doc.AddItem(htmlformat.Bold(errmsg % args))
return doc
if __name__ == "__main__":
try:
main()
except KeyboardInterrupt:
print "Interrupted!"
raise SystemExit, 0
except mm_err.MMUnknownListError, msg:
error_page("%s: %s", list_name, msg)
raise SystemExit, 0
except:
print "Content-type: text/html\n"
print "
" try: import traceback sys.stderr = sys.stdout traceback.print_exc() except: print "[failed to get traceback]" print "\n\n"