#!/usr/local/bin/python
"""Produce the list-administration web page on stdout.
We need the environment var PATH_INFO to name the list."""
import sys, os, cgi, string, crypt, types
f = open('/tmp/quick', 'a+')
#sys.stderr = sys.stdout
sys.stderr = f
sys.path.append('/home/mailman/mailman/modules')
import mm_utils, maillist, mm_cfg, htmlformat
def InitDocument():
return htmlformat.Document()
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 = list_info[0]
try:
list = maillist.MailList(list_name)
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)
def GetGuiItem(table_entry):
varname, type, params, dependancies, descr = table_entry
if type == mm_cfg.Radio or type == mm_cfg.Toggle:
gui_part = htmlformat.RadioButtonArray(varname, params,
getattr(list, varname))
elif (type == mm_cfg.String or type == mm_cfg.Email or type == mm_cfg.Host
or type == mm_cfg.Number):
gui_part = htmlformat.TextBox(varname, getattr(list, varname), params)
elif type == mm_cfg.Text:
if params:
r, c = params
else:
r, c = None, None
val = getattr(list, varname)
if not val:
val = ''
gui_part = htmlformat.TextArea(varname, val, r, c)
elif type == mm_cfg.EmailList:
if params:
r, c = params
else:
r, c = None, None
res = string.join(getattr(list, varname), '\n')
gui_part = htmlformat.TextArea(varname, res, r, c, wrap='off')
return gui_part
def FormatConfiguration(doc):
doc.SetTitle('%s Administration' % list.real_name)
doc.AddItem(htmlformat.Header(2, 'Configuration for %s' % list.real_name))
doc.AddItem('
')
link = htmlformat.Link(list.GetScriptURL('admindb'),
'View or edit the administrative requests database.')
doc.AddItem(htmlformat.FontSize("+1", link))
doc.AddItem('')
link = htmlformat.Link(list.GetScriptURL('listinfo'),
'Go to the general list information page.')
doc.AddItem(htmlformat.FontSize("+1", link))
doc.AddItem('
')
link = htmlformat.Link(list.GetScriptURL('edithtml'),
'Edit the HTML for the public list pages.')
doc.AddItem(htmlformat.FontSize("+1", link))
doc.AddItem('
')
doc.AddItem('
')
form = htmlformat.Form(list.GetScriptURL('admin'))
doc.AddItem(form)
password_table = htmlformat.Table()
password_table.AddRow(['Enter the admin password to change options:',
htmlformat.PasswordBox('adminpw')])
password_table.AddRow(['When you are done...',
htmlformat.SubmitButton('submit', 'Submit Changes')])
form.AddItem(password_table)
big_table = htmlformat.Table(border=2)
big_table.AddRow([htmlformat.Center(htmlformat.Header(2, 'General Options'))])
big_table.AddCellInfo(0,0,colspan=2)
big_table.AddRow([htmlformat.Bold('Option'), htmlformat.Bold('Value')])
for item in general:
gui_item = GetGuiItem(item)
big_table.AddRow([item[4], gui_item])
# This wasn't handled too well.
if item[1] == mm_cfg.Toggle:
big_table.AddRow([htmlformat.Header(2, "If so:")])
big_table.AddCellInfo(big_table.GetCurrentRowIndex(), 0, colspan=2)
big_table.AddRow(['
'])
big_table.AddCellInfo(big_table.GetCurrentRowIndex(), 0, colspan=2)
big_table.AddRow([htmlformat.Center(htmlformat.Header(2, 'Digest Options'))])
big_table.AddCellInfo(big_table.GetCurrentRowIndex(), 0, colspan=2)
big_table.AddRow([htmlformat.Bold('Option'), htmlformat.Bold('Value')])
for item in digest:
gui_item = GetGuiItem(item)
big_table.AddRow([item[4], gui_item])
# Yuck.
if item[1] == mm_cfg.Toggle:
big_table.AddRow([htmlformat.Header(2, "If so:")])
big_table.AddCellInfo(big_table.GetCurrentRowIndex(), 0, colspan=2)
big_table.AddRow(['
'])
big_table.AddCellInfo(big_table.GetCurrentRowIndex(), 0, colspan=2)
big_table.AddRow([htmlformat.Center(htmlformat.Header(2,
'Non-Digested Options'))])
big_table.AddCellInfo(big_table.GetCurrentRowIndex(), 0, colspan=2)
big_table.AddRow([htmlformat.Bold('Option'), htmlformat.Bold('Value')])
for item in nodigest:
gui_item = GetGuiItem(item)
big_table.AddRow([item[4], gui_item])
# *sigh*
if item[1] == mm_cfg.Toggle:
big_table.AddRow([htmlformat.Header(2, "If so:")])
big_table.AddCellInfo(big_table.GetCurrentRowIndex(), 0, colspan=2)
big_table.AddRow(['
'])
big_table.AddCellInfo(big_table.GetCurrentRowIndex(), 0, colspan=2)
big_table.AddRow([htmlformat.Center(htmlformat.Header(2, 'Bounce Administration Options'))])
big_table.AddCellInfo(big_table.GetCurrentRowIndex(), 0, colspan=2)
for item in bounce:
gui_item = GetGuiItem(item)
big_table.AddRow([item[4], gui_item])
# This code sux...
if item[1] == mm_cfg.Toggle:
big_table.AddRow([htmlformat.Header(2, "If so:")])
big_table.AddCellInfo(big_table.GetCurrentRowIndex(), 0, colspan=2)
big_table.AddRow(['
'])
big_table.AddCellInfo(big_table.GetCurrentRowIndex(), 0, colspan=2)
big_table.AddRow([htmlformat.Center(htmlformat.Header(2, 'Archival Options'))])
big_table.AddCellInfo(big_table.GetCurrentRowIndex(), 0, colspan=2)
big_table.AddRow([htmlformat.Bold('Option'), htmlformat.Bold('Value')])
for item in archives:
gui_item = GetGuiItem(item)
big_table.AddRow([item[4], gui_item])
# This code sux...
if item[1] == mm_cfg.Toggle:
big_table.AddRow([htmlformat.Header(2, "If so:")])
big_table.AddCellInfo(big_table.GetCurrentRowIndex(), 0, colspan=2)
form.AddItem(big_table)
form.AddItem('')
change_pw_table = htmlformat.Table(border=2)
change_pw_table.AddRow([htmlformat.Header(2,
htmlformat.Center(
'Change Your Password:'))])
change_pw_table.AddCellInfo(change_pw_table.GetCurrentRowIndex(), 0,
colspan=2)
change_pw_table.AddRow(['Enter your new password:',
htmlformat.PasswordBox('newpw')])
change_pw_table.AddRow(['And also confirm it:',
htmlformat.PasswordBox('confirmpw')])
form.AddItem(htmlformat.Center(change_pw_table))
# Improve the html here...
form.AddItem('
')
form.AddItem('Mass Subscribe People
')
form.AddItem('enter one email address per line
')
form.AddItem(htmlformat.TextArea(name='subscribees',rows=20,cols=60,wrap=None))
form.AddItem(list.GetMailmanFooter())
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.
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 the options to subscribe w/
list.AddMember(new_name, 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:
document.AddItem(htmlformat.Header(3, htmlformat.Italic(
'Error: Passwords did not match.')))
else:
document.AddItem(htmlformat.Header(3, htmlformat.Italic(
'Error: You must type in your new password twice.')))
list.Save()
try:
info = list.GetConfigInfo()
general = info['general']
nodigest = info['nondigest']
digest = info['digest']
archives = info['archive']
if len(list._internal_name) < 3 or 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('
')
doc.AddItem(
htmlformat.Header(3, htmlformat.Italic('Error: '
'You must supply the admin password to change options.')))
else:
try:
list.ConfirmAdminPassword(cgi_data['adminpw'].value)
ChangeOptions(list, general + nodigest + digest + archives + bounce,
cgi_data, doc)
# Yuck. This shouldn't need to be here.
if not list.digestable and not list.nondigestable:
list.nondigestable = 1
except:
doc.AddItem('
')
doc.AddItem(
htmlformat.Header(3, htmlformat.Italic(
'Error: Incorrect admin password.')))
if not list.digestable and len(list.digest_members):
doc.AddItem('
')
doc.AddItem(htmlformat.Header(3, 'Warning: you have digest members, '
'but digests are turned off. Those people will not receive mail.'))
if not list.nondigestable and len(list.members):
doc.AddItem('
')
doc.AddItem(htmlformat.Header(3, 'Warning: you have list members, but '
'non-digestified mail is turned off. They will receive mail until '
'you fix this problem.'))
FormatConfiguration(doc)
finally:
try:
print doc.Format()
except:
pass
list.Unlock()