[Mailman-i18n] Example marking file
Juan Carlos Rey Anaya
jcrey@uma.es
Fri, 10 Nov 2000 20:59:20 +0100
This is a multi-part message in MIME format.
--------------BFB93F3D3F601EC069B326B6
Content-Type: text/plain; charset=iso-8859-1
Content-Transfer-Encoding: quoted-printable
I send you a piece of file with marking already done, in order
contributors can note how to do markings.
I have tried (where possible) to take apart HTML code.
Cheers
PD:
There may be errors, I have done it in a hurry.
-- =
___
/ F \
[[[]]]]
( O O )
#----------------0000--(_)--0000---------------#
| Juan Carlos Rey Anaya (jcrey@uma.es) |
| Servicio Central de inform=E1tica |
| Universidad de M=E1laga - Espa=F1a |
#----------------------------------------------#
# Solo se que cada vez se menos :-| #
#----------------------------------------------#
--------------BFB93F3D3F601EC069B326B6
Content-Type: text/plain; charset=iso-8859-1;
name="admin.py"
Content-Transfer-Encoding: quoted-printable
Content-Disposition: inline;
filename="admin.py"
if category not in map(lambda x: x[0], CATEGORIES):
category =3D 'general'
# is the request for variable details?
varhelp =3D None
if cgidata.has_key('VARHELP'):
varhelp =3D cgidata['VARHELP'].value
elif cgidata.has_key('request_login') and \
os.environ.get('QUERY_STRING'):
# POST methods, even if their actions have a query string, do=
n't
# get put into FieldStorage's keys :-(
qs =3D cgi.parse_qs(os.environ['QUERY_STRING']).get('VARHELP'=
)
if qs and type(qs) =3D=3D types.ListType:
varhelp =3D qs[0]
if varhelp:
FormatOptionHelp(doc, varhelp, mlist)
print doc.Format(bgcolor=3D"#ffffff")
return
if cgidata.has_key('bounce_matching_headers'):
pairs =3D mlist.parse_matching_header_opt()
if len(cgidata.keys()):
ChangeOptions(mlist, category, cgidata, doc)
mlist.CheckValues()
# Sanity checks
if not mlist.digestable and not mlist.nondigestable:
AddErrorMessage(doc, _('''You have turned off delivery of
both digest and non-digest messages. This is an incompatible=
state of affairs. You must turn on either digest delivery or=
non-digest delivery or your mailing list will basically be
unusable.'''))
if not mlist.digestable and len(mlist.GetDigestMembers()):
AddErrorMessage(doc, _('''You have digest members,
but digests are turned off. Those people will not receive
mail.'''))
if not mlist.nondigestable and len(mlist.GetMembers()):
AddErrorMessage(doc, _('''You have regular list members
but non-digestified mail is turned off. They will receive ma=
il
until you fix this problem.'''))
FormatConfiguration(doc, mlist, category, category_suffix, cgidata)
print doc.Format(bgcolor=3D"#ffffff")
finally:
mlist.Save()
mlist.Unlock()
=0C
# Form Production:
def FormatAdminOverview(error=3DNone):
"Present a general welcome and itemize the (public) lists."
doc =3D Document()
legend =3D _("%s mailing lists - Admin Links") % mm_cfg.DEFAULT_HOST_=
NAME
doc.SetTitle(legend)
table =3D Table(border=3D0, width=3D"100%")
table.AddRow([Center(Header(2, legend))])
table.AddCellInfo(max(table.GetCurrentRowIndex(), 0), 0,
colspan=3D2, bgcolor=3D"#99ccff")
advertised =3D []
names =3D Utils.list_names()
names.sort()
for n in names:
l =3D MailList.MailList(n, lock=3D0)
if l.advertised:
advertised.append(l)
if error:
greeting =3D FontAttr(error, color=3D"ff5060", size=3D"+1")
else:
greeting =3D _("Welcome!")
if not advertised:
welcome_items =3D (greeting,
_("<p>"
" There currently are no publicly-advertised "),
Link(mm_cfg.MAILMAN_URL, "mailman"),
_(" mailing lists on %s.") % mm_cfg.DEFAULT_HOST_NAME,
)
else:
welcome_items =3D (
greeting,
_("<p>"
" Below is the collection of publicly-advertised "),
Link(mm_cfg.MAILMAN_URL, "mailman"),
_(" mailing lists on %s.") % mm_cfg.DEFAULT_HOST_NAME,
(_(' Click on a list name to visit the configuration pages'
' for that list.')
)
)
welcome_items =3D (welcome_items +
(_(" To visit the administrators configuration page =
for"
" an unadvertised list, open a URL similar to thi=
s")
+
(_(" one, but with a '/' and the %slist name append=
ed.<p>")
% ((error and _("right ")) or ""))
+
_(" General list information can be found at "),
Link(Utils.ScriptURL('listinfo'),
_('the mailing list 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=3D2)=
if advertised:
table.AddRow([' ', ' '])
table.AddRow([Bold(_("List")), Bold(_("Description"))])
for l in advertised:
table.AddRow(
[Link(l.GetScriptURL('admin'), Bold(l.real_name)),
l.description or Italic(_('[no description available]'))=
,
])
doc.AddItem(table)
doc.AddItem('<hr>')
doc.AddItem(MailmanLogo())
print doc.Format(bgcolor=3D"#ffffff")
=0C
def FormatConfiguration(doc, mlist, category, category_suffix, cgi_data):=
"""Produce the overall doc, *except* any processing error messages.""=
"
for k, v in CATEGORIES:
if k =3D=3D category:
label =3D v
doc.SetTitle('%s Administration (%s)' % (mlist.real_name, label))
doc.AddItem(Center(Header(2, _('%s mailing list administration<br>%s =
Section')
% (mlist.real_name, label))))
doc.AddItem('<hr>')
linktable =3D Table(valign=3D"top")
linktable.AddRow([Center(Bold(_("Configuration Categories"))),
Center(Bold(_("Other Administrative Activities")))]=
)
adminurl =3D mlist.GetScriptURL('admin')
otherlinks =3D UnorderedList()
otherlinks.AddItem(Link(mlist.GetScriptURL('admindb'), =
_('Tend to pending administrative requests'))=
)
otherlinks.AddItem(Link(mlist.GetScriptURL('listinfo'),
_('Go to the general list information page'))=
)
otherlinks.AddItem(Link(mlist.GetScriptURL('edithtml'),
_('Edit the HTML for the public list pages'))=
)
otherlinks.AddItem(Link(mlist.GetBaseArchiveURL(), 'Go to list archiv=
es'))
otherlinks.AddItem(Link('%s/logout' % adminurl,
# TBD: What I really want is a blank line :/
'<FONT SIZE=3D"+2"><b>Logout</b></FONT>'))
categorylinks =3D UnorderedList()
for k, v in CATEGORIES:
if k =3D=3D category:
categorylinks.AddItem("<em>%s</em>" % v)
else:
categorylinks.AddItem(Link("%s/%s" % (adminurl, k), v))
linktable.AddRow([categorylinks, otherlinks])
linktable.AddRowInfo(max(linktable.GetCurrentRowIndex(), 0),
valign=3D"top")
doc.AddItem(linktable)
doc.AddItem('<hr>')
if category_suffix:
encoding =3D None
if category_suffix =3D=3D 'autoreply':
# these have file uploads
encoding =3D 'multipart/form-data'
form =3D Form('%s/%s' % (adminurl, category_suffix), encoding=3De=
ncoding)
else:
form =3D Form(adminurl)
doc.AddItem(form)
if category =3D=3D 'general':
andpassmsg =3D _(" (You can change your password there, too.)")
else:
andpassmsg =3D ""
form.AddItem(_("Make your changes below, and then submit them"
" using the button at the bottom.%s<p>")
% andpassmsg)
form.AddItem(FormatOptionsSection(category, mlist, cgi_data))
if category =3D=3D 'general':
form.AddItem(Center(FormatPasswordStuff()))
form.AddItem("<p>")
form.AddItem(Center(FormatSubmit()))
form.AddItem(mlist.GetMailmanFooter())
=0C
def FormatOptionsSection(category, mlist, cgi_data):
"""Produce the category-specific options table."""
if category =3D=3D 'members':
# Special case for members section.
return FormatMembershipOptions(mlist, cgi_data)
options =3D GetConfigOptions(mlist, category)
big_table =3D Table(cellspacing=3D3, cellpadding=3D4)
# Get and portray the text label for the category.
for k, v in CATEGORIES:
if k =3D=3D category:
label =3D v
big_table.AddRow([Center(Header(2, label))])
big_table.AddCellInfo(max(big_table.GetCurrentRowIndex(), 0), 0,
colspan=3D2, bgcolor=3D"#99ccff")
def ColHeader(big_table =3D big_table):
big_table.AddRow([Center(Bold(_('Description'))), Center(Bold(_('=
Value')))])
big_table.AddCellInfo(max(big_table.GetCurrentRowIndex(), 0), 0,
width=3D"15%")
big_table.AddCellInfo(max(big_table.GetCurrentRowIndex(), 0), 1,
width=3D"85%")
did_col_header =3D 0
for item in options:
if type(item) =3D=3D 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 =3D "<center><i>" + item + "</i></center>"
big_table.AddRow([item])
big_table.AddCellInfo(max(big_table.GetCurrentRowIndex(), 0),
0, colspan=3D2)
if not did_col_header:
# Do col header after very first string descr, if any...
ColHeader()
did_col_header =3D 1
else:
if not did_col_header:
# ... but do col header before anything else.
ColHeader()
did_col_header =3D 1
AddOptionsTableItem(big_table, item, category, mlist)
big_table.AddRow(['<br>'])
big_table.AddCellInfo(big_table.GetCurrentRowIndex(), 0, colspan=3D2)=
return big_table
=0C
def AddOptionsTableItem(table, item, category, mlist, detailsp=3D1):
"""Add a row to an options table with the item description and value.=
"""
try:
got =3D GetItemCharacteristics(item)
varname, kind, params, dependancies, descr, elaboration =3D got
except ValueError, msg:
syslog('error', 'admin: %s' % msg)
return Italic(_("<malformed option>"))
descr =3D GetItemGuiDescr(mlist, category, varname, descr, detailsp)
val =3D GetItemGuiValue(mlist, kind, varname, params)
table.AddRow([descr, val])
table.AddCellInfo(max(table.GetCurrentRowIndex(), 0), 1,
bgcolor=3D"#cccccc")
table.AddCellInfo(max(table.GetCurrentRowIndex(), 0), 0,
bgcolor=3D"#cccccc")
=0C
def FormatOptionHelp(doc, varref, mlist):
item =3D None
reflist =3D string.split(varref, '/')
if len(reflist) =3D=3D 2:
category, varname =3D reflist
options =3D GetConfigOptions(mlist, category)
for i in options:
if i and i[0] =3D=3D varname:
item =3D i
break
if not item:
bad =3D _('Option %s/%s not found: %s') % (
category, varname, os.environ.get('PATH_INFO'))
AddErrorMessage(doc, bad)
return
got =3D GetItemCharacteristics(item)
try:
varname, kind, params, dependancies, descr, elaboration =3D got
if elaboration is None:
elaboration =3D ''
except ValueError, msg:
varname, kind, params, dependancies, descr =3D got
elaboration =3D descr
header =3D Table(width=3D"100%")
legend =3D (_('%s Mailing list Configuration Help<br><em>%s</em> Opti=
on')
% (mlist.real_name, varname))
header.AddRow([Center(Header(3, legend))])
header.AddCellInfo(max(header.GetCurrentRowIndex(), 0), 0,
colspan=3D2, bgcolor=3D"#99ccff")
doc.SetTitle(_("Mailman %s List Option Help") % varname)
doc.AddItem(header)
doc.AddItem("<b>%s</b> (%s): %s<p>" % (varname, category, descr))
doc.AddItem("%s<p>" % elaboration)
form =3D Form("%s/%s" % (mlist.GetScriptURL('admin'), category))
valtab =3D Table(cellspacing=3D3, cellpadding=3D4)
AddOptionsTableItem(valtab, item, category, mlist, detailsp=3D0)
form.AddItem(valtab)
form.AddItem('<p>')
form.AddItem(Center(FormatSubmit()))
doc.AddItem(Center(form))
doc.AddItem(_("""<em><strong>Warning:</strong> changing this option h=
ere
could cause other screens to be out-of-sync. Be sure to reload any o=
ther
pages that are displaying this option for this mailing list. You can=
also """))
doc.AddItem(Link('%s/%s' % (mlist.GetScriptURL('admin'), category),
_('return to the %s options page.') % category ))
doc.AddItem('</em>')
doc.AddItem(mlist.GetMailmanFooter())
=0C
def GetItemCharacteristics(table_entry):
"""Break out the components of an item description from its table ent=
ry:
0 option-var name
1 type
2 entry size
3 ?dependancies?
4 Brief description
5 Optional description elaboration""" =
if len(table_entry) =3D=3D 5:
elaboration =3D None
varname, kind, params, dependancies, descr =3D table_entry
elif len(table_entry) =3D=3D 6:
varname, kind, params, dependancies, descr, elaboration =3D table=
_entry
else:
raise ValueError, (_("Badly formed options entry:\n %s")
% table_entry)
return (varname, kind, params, dependancies, descr, elaboration)
=0C
def GetItemGuiValue(mlist, kind, varname, params):
"""Return a representation of an item's settings."""
if kind =3D=3D mm_cfg.Radio or kind =3D=3D mm_cfg.Toggle:
#
# if we are sending returning the option for subscribe
# policy and this site doesn't allow open subscribes,
# then we have to alter the value of mlist.subscribe_policy
# as passed to RadioButtonArray in order to compensate
# for the fact that there is one fewer option. correspondingly,
# we alter the value back in the change options function -scott
#
# TBD: this is an ugly ugly hack.
if varname[0] =3D=3D '_':
checked =3D 0
else:
checked =3D getattr(mlist, varname)
if varname =3D=3D 'subscribe_policy' and not mm_cfg.ALLOW_OPEN_SU=
BSCRIBE:
checked =3D checked - 1
return RadioButtonArray(varname, params, checked)
elif (kind =3D=3D mm_cfg.String or kind =3D=3D mm_cfg.Email or
kind =3D=3D mm_cfg.Host or kind =3D=3D mm_cfg.Number):
return TextBox(varname, getattr(mlist, varname), params)
elif kind =3D=3D mm_cfg.Text:
if params:
r, c =3D params
else:
r, c =3D None, None
val =3D getattr(mlist, varname)
if not val:
val =3D ''
return TextArea(varname, val, r, c)
elif kind =3D=3D mm_cfg.EmailList:
if params:
r, c =3D params
else:
r, c =3D None, None
res =3D string.join(getattr(mlist, varname), '\n')
return TextArea(varname, res, r, c, wrap=3D'off')
elif kind =3D=3D mm_cfg.FileUpload:
# like a text area, but also with uploading
if params:
r, c =3D params
else:
r, c =3D None, None
val =3D getattr(mlist, varname)
if not val:
val =3D ''
container =3D Container()
container.AddItem(_('<em>Enter the text below, or...</em><br>'))
container.AddItem(TextArea(varname, val, r, c))
container.AddItem(_('<br><em>...specify a file to upload</em><br>=
'))
container.AddItem(FileUpload(varname+'_upload', r, c))
return container
=0C
def GetItemGuiDescr(mlist, category, varname, descr, detailsp):
"""Return the item's description, with link to details.
Details are not included if this is a VARHELP page, because that /is/=
the
details page!
"""
if detailsp:
text =3D Container('<div ALIGN=3D"right">' + descr + ' ',
Link(mlist.GetScriptURL('admin')
+ '/?VARHELP=3D' + category + '/' + varname=
,
'(Details)'),
'</div>').Format()
else:
text =3D '<div ALIGN=3D"right">' + descr + '</div>'
if varname[0] =3D=3D '_':
text =3D text + _('''<div ALIGN=3D"right"><br><em><strong>Note:</=
strong>
setting this value performs an immediate action but does not modi=
fy
permanent state.</em></div>''')
return text
=0C
def FormatMembershipOptions(mlist, cgi_data):
container =3D Container()
header =3D Table(width=3D"100%")
header.AddRow([Center(Header(2, _("Membership Management")))])
header.AddCellInfo(max(header.GetCurrentRowIndex(), 0), 0,
colspan=3D2, bgcolor=3D"#99ccff")
container.AddItem(header)
user_table =3D Table(width=3D"90%", border=3D'2')
user_table.AddRow([Center(Header(4, _("Membership List")))])
user_table.AddCellInfo(user_table.GetCurrentRowIndex(),
user_table.GetCurrentCellIndex(),
bgcolor=3D"#cccccc", colspan=3D8)
user_table.AddRow(
[Center(Italic(_("(%s members total, max. %s at a time displayed)=
") %
(len(mlist.members)
+ len(mlist.digest_members),
mlist.admin_member_chunksize)))])
user_table.AddCellInfo(user_table.GetCurrentRowIndex(),
user_table.GetCurrentCellIndex(),
bgcolor=3D"#cccccc", colspan=3D8)
user_table.AddRow(map(Center, [_('member address'), _('subscr'),
_('hide'), _('nomail'), _('ack'), _('n=
ot metoo'),
_('digest'), _('plain')]))
rowindex =3D user_table.GetCurrentRowIndex()
for i in range(8):
user_table.AddCellInfo(rowindex, i, bgcolor=3D'#cccccc')
all =3D mlist.GetMembers() + mlist.GetDigestMembers()
if len(all) > mlist.admin_member_chunksize:
chunks =3D Utils.chunkify(all, mlist.admin_member_chunksize)
if not cgi_data.has_key("chunk"):
chunk =3D 0
else:
chunk =3D string.atoi(cgi_data["chunk"].value)
all =3D chunks[chunk]
footer =3D (_("<p><em>To View other sections, "
"click on the appropriate range listed below</em>"))
chunk_indices =3D range(len(chunks))
chunk_indices.remove(chunk)
buttons =3D []
for ci in chunk_indices:
start, end =3D chunks[ci][0], chunks[ci][-1]
url =3D mlist.GetScriptURL('admin')
buttons.append("<a href=3D%s/members?chunk=3D%d>" + _("from %=
s to %s") + "</a>"
% (url, ci, start, end))
buttons =3D apply(UnorderedList, tuple(buttons))
footer =3D footer + buttons.Format() + "<p>"
else:
all.sort()
footer =3D "<p>"
for member in all:
mtext =3D '<a href=3D"%s">%s</a>' % (
mlist.GetOptionsURL(member, obscure=3D1),
mlist.GetUserSubscribedAddress(member))
cells =3D [mtext + "<input type=3Dhidden name=3Duser value=3D%s>"=
% (member),
Center(CheckBox(member + "_subscribed", "on", 1).Format(=
))]
for opt in ("hide", "nomail", "ack", "notmetoo"):
if mlist.GetUserOption(member,MailCommandHandler.option_info[=
opt]):
value =3D "on"
checked =3D 1
else:
value =3D "off"
checked =3D 0
box =3D CheckBox("%s_%s" % (member, opt), value, checked)
cells.append(Center(box.Format()))
if mlist.members.has_key(member):
cells.append(Center(CheckBox(member + "_digest",
"off", 0).Format()))
else:
cells.append(Center(CheckBox(member + "_digest",
"on", 1).Format()))
if mlist.GetUserOption(member,MailCommandHandler.option_info['pla=
in']):
value =3D 'on'
checked =3D 1
else:
value =3D 'off'
checked =3D 0
cells.append(Center(CheckBox('%s_plain' % member, value, checked)=
))
user_table.AddRow(cells)
container.AddItem(Center(user_table))
legend =3D UnorderedList()
legend.AddItem(_('<b>subscr</b> -- Is the member subscribed?'))
legend.AddItem(_("<b>hide</b> -- Is the member's address "
"concealed on the list of subscribers?"))
legend.AddItem(_('<b>nomail</b> -- Is delivery to the member disabled=
?'))
legend.AddItem(_('<b>ack</b> -- '
'Does the member get acknowledgements of their posts=
?'))
legend.AddItem(_('<b>not metoo</b> -- '
'Does the member avoid copies of their own posts?'))=
legend.AddItem(_('<b>digest</b> -- '
'Does the member get messages in digests? '
'(otherwise, individual messages)'))
legend.AddItem(
_('<b>plain</b> -- '
'If getting digests, does the member get plain text digests? '
'(otherwise, MIME)'))
container.AddItem(legend.Format())
container.AddItem(footer)
t =3D Table(width=3D"90%")
t.AddRow([Center(Header(4, _("Mass Subscribe Members")))])
t.AddCellInfo(t.GetCurrentRowIndex(),
t.GetCurrentCellIndex(),
bgcolor=3D"#cccccc", colspan=3D8)
if mlist.send_welcome_msg:
nochecked =3D 0
yeschecked =3D 1
else:
nochecked =3D 1
yeschecked =3D 0
t.AddRow([("<b>1.</b>" + _("Send Welcome message to this batch? ")
+ RadioButton("send_welcome_msg_to_this_batch", 0,
nochecked).Format()
+ _(" no ")
+ RadioButton("send_welcome_msg_to_this_batch", 1,
yeschecked).Format()
+ _(" yes "))])
t.AddRow(["<b>2.</b>" + _("Enter one address per line:") + "<p>"])
container.AddItem(Center(t))
container.AddItem(Center(TextArea(name=3D'subscribees',
rows=3D10,cols=3D60,wrap=3DNone)))
return container
=0C
def FormatPasswordStuff():
change_pw_table =3D Table(bgcolor=3D"#99cccc", border=3D0,
cellspacing=3D0, cellpadding=3D2,
valign=3D"top")
change_pw_table.AddRow(
[Bold(Center(_('To Change The Administrator Password')))])
change_pw_table.AddCellInfo(0, 0, align=3D"left", colspan=3D2)
old =3D Table(bgcolor=3D"#99cccc", border=3D1,
cellspacing=3D0, cellpadding=3D2, valign=3D"top")
old.AddRow(['<div ALIGN=3D"right">' + _(" Enter current password:") +=
'</div>',
PasswordBox('adminpw')])
new =3D Table(bgcolor=3D"#99cccc", border=3D1,
cellspacing=3D0, cellpadding=3D2, valign=3D"top")
new.AddRow(['<div ALIGN=3D"right">' + _(" Enter new password:") + '</=
div>',
PasswordBox('newpw')])
new.AddRow(['<div ALIGN=3D"right">' + _("Confirm new password:") + '<=
/div>',
PasswordBox('confirmpw')])
change_pw_table.AddRow([old, new])
change_pw_table.AddCellInfo(1, 0, align=3D"left", valign=3D"top")
#change_pw_table.AddCellInfo(1, 1, align=3D"left", valign=3D"top")
return change_pw_table
=0C
def FormatSubmit():
submit =3D Table(bgcolor=3D"#99ccff",
border=3D0, cellspacing=3D0, cellpadding=3D2)
submit.AddRow([Bold(SubmitButton('submit', _('Submit Your Changes')))=
])
submit.AddCellInfo(submit.GetCurrentRowIndex(), 0, align=3D"middle")
return submit
=0C
# XXX klm - looks like turn_on_moderation is orphaned.
#turn_on_moderation =3D 0
# Options processing
def GetValidValue(mlist, prop, my_type, val, dependant):
if my_type =3D=3D mm_cfg.Radio or my_type =3D=3D mm_cfg.Toggle:
if type(val) <> types.IntType:
try:
val =3D int(val)
except ValueError:
pass
# Don't know what to do here...
return val
elif my_type =3D=3D mm_cfg.String or my_type =3D=3D mm_cfg.Text:
return val
elif my_type =3D=3D mm_cfg.Email:
try:
Utils.ValidateEmail(val)
return val
except Errors.EmailAddressError:
# TBD: should have a way of displaying the results of the
# operation.
pass
# Revert to the old value.
return getattr(mlist, prop)
elif my_type =3D=3D mm_cfg.EmailList:
def SafeValidAddr(addr):
try:
Utils.ValidateEmail(addr)
return 1
except Errors.EmailAddressError:
return 0
val =3D 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 =3D 1
return val
elif my_type =3D=3D 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 =3D open('/etc/sendmail.cf', 'r')
## lines =3D string.split(file.read(), '\n')
## file.close()
## def ConfirmCWEntry(item):
## return item[0:2] =3D=3D 'Cw'
## lines =3D 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:])) =3D=3D string.lower(val):=
## return val
## return getattr(list, prop)
elif my_type =3D=3D mm_cfg.Number:
num =3D -1
try:
num =3D int(val)
except ValueError:
# TBD: a float???
try:
num =3D float(val)
except ValueError:
pass
if num < 0:
return getattr(mlist, prop)
return num
else:
# Should never get here...
return val
=0C
def ChangeOptions(mlist, category, cgi_info, document):
confirmed =3D 0
if cgi_info.has_key('newpw'):
if cgi_info.has_key('confirmpw'):
if cgi_info.has_key('adminpw') and cgi_info['adminpw'].value:=
try:
mlist.ConfirmAdminPassword(cgi_info['adminpw'].value)=
confirmed =3D 1
except Errors.MMBadPasswordError:
AddErrorMessage(document,
_('Incorrect administrator password')=
,
tag=3D'Error: ')
if confirmed:
new =3D string.strip(cgi_info['newpw'].value)
confirm =3D string.strip(cgi_info['confirmpw'].value)
if new =3D=3D '' and confirm =3D=3D '':
AddErrorMessage(document,
_('Empty admin passwords are not allo=
wed'),
tag=3D'Error: ')
elif new =3D=3D confirm:
mlist.password =3D crypt(new, Utils.GetRandomSeed())
# Re-authenticate (to set new cookie)
mlist.WebAuthenticate(password=3Dnew, cookie=3D'admin=
')
else:
AddErrorMessage(document, _('Passwords did not match'=
),
tag=3D'Error: ')
else:
AddErrorMessage(document,
_('You must type in your new password twice')=
,
tag=3D'Error: ')
#
# for some reason, the login page mangles important values for the li=
st
# 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 !=3D 'members' and \
not cgi_info.has_key("request_login") and \
len(cgi_info.keys()) > 1:
# then
if cgi_info.has_key("subscribe_policy"):
if not mm_cfg.ALLOW_OPEN_SUBSCRIBE:
#
# we have to add one to the value because the
# page didn't present an open list as an option
#
page_setting =3D string.atoi(cgi_info["subscribe_policy"]=
=2Evalue)
cgi_info["subscribe_policy"].value =3D str(page_setting +=
1)
opt_list =3D GetConfigOptions(mlist, category)
for item in opt_list:
if type(item) <> types.TupleType or len(item) < 5:
continue
property, kind, args, deps, desc =3D item[0:5]
if cgi_info.has_key(property+'_upload') and \
cgi_info[property+'_upload'].value:
val =3D cgi_info[property+'_upload'].value
elif not cgi_info.has_key(property):
continue
else:
val =3D cgi_info[property].value
value =3D GetValidValue(mlist, property, kind, val, deps)
#
# This is an ugly, ugly hack
if property[0] =3D=3D '_':
# TBD: When turning on usenet->mail gating we want to
# automatically catch up the newsgroup otherwise the mail=
ing
# list will suddently get flooded. There should be a muc=
h
# better way to do this (or for the admin to specify they=
want
# this).
if property =3D=3D '_mass_catchup' and value:
mlist.usenet_watermark =3D None
elif getattr(mlist, property) <> value:
# TBD: Ensure that mlist.real_name differs only in letter=
# case. Otherwise a security hole can potentially be ope=
ned
# when using an external archiver. This seems ad-hoc and=
# could use a more general security policy.
if property =3D=3D 'real_name' and \
string.lower(value) <> string.lower(mlist._internal_na=
me):
# then don't install this value.
document.AddItem(_("""<p><b>real_name</b> attribute n=
ot
changed! It must differ from the list's name by case=
only.<p>"""))
continue
setattr(mlist, property, value)
#
# mass subscription processing for members category
#
if cgi_info.has_key('subscribees'):
name_text =3D cgi_info['subscribees'].value
name_text =3D string.replace(name_text, '\r', '')
names =3D filter(None, map(string.strip, string.split(name_text, '\n')))=
send_welcome_msg =3D string.atoi(
cgi_info["send_welcome_msg_to_this_batch"].value)
digest =3D 0
if not mlist.digestable:
digest =3D 0
if not mlist.nondigestable:
digest =3D 1
subscribe_errors =3D []
subscribe_success =3D []
result =3D mlist.ApprovedAddMembers(names, None,
digest, send_welcome_msg)
for name in result.keys():
if result[name] is None:
subscribe_success.append(name)
else:
# `name' was not subscribed, find out why. On failures,
# result[name] is set from sys.exc_info()[:2]
e, v =3D result[name]
if e is Errors.MMAlreadyAMember:
subscribe_errors.append((name, _('Already a member'))=
)
elif e is Errors.MMBadEmailError:
if name =3D=3D '':
name =3D '<blank line>'
subscribe_errors.append(
(name, _("Bad/Invalid email address")))
elif e is Errors.MMHostileAddress:
subscribe_errors.append(
(name, _("Hostile Address (illegal characters)"))=
)
if subscribe_success:
document.AddItem(Header(5, _("Successfully Subscribed:")))
document.AddItem(apply(UnorderedList, tuple((subscribe_succes=
s))))
document.AddItem("<p>")
# ApprovedAddMembers will already have saved the list for us.=
if subscribe_errors:
document.AddItem(Header(5, _("Error Subscribing:")))
items =3D 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 =3D cgi_info["user"]
if type(user) is type([]):
users =3D []
for ui in range(len(user)):
users.append(user[ui].value)
else:
users =3D [user.value]
errors =3D []
for user in users:
if not cgi_info.has_key('%s_subscribed' % (user)):
try:
mlist.DeleteMember(user)
except Errors.MMNoSuchUserError:
errors.append((user, _('Not subscribed')))
continue
value =3D cgi_info.has_key('%s_digest' % user)
try:
mlist.SetUserDigest(user, value, force=3D1)
except (Errors.MMNotAMemberError,
Errors.MMAlreadyDigested,
Errors.MMAlreadyUndigested):
pass
for opt in ("hide", "nomail", "ack", "notmetoo", "plain"):
opt_code =3D MailCommandHandler.option_info[opt]
if cgi_info.has_key("%s_%s" % (user, opt)):
mlist.SetUserOption(user, opt_code, 1, save_list=3D0)=
else:
mlist.SetUserOption(user, opt_code, 0, save_list=3D0)=
if errors:
document.AddItem(Header(5, _("Error Unsubscribing:")))
items =3D map(lambda x: "%s -- %s" % (x[0], x[1]), errors)
document.AddItem(apply(UnorderedList, tuple((items))))
document.AddItem("<p>")
=0C
def AddErrorMessage(doc, errmsg, tag=3D'Warning: ', *args):
doc.AddItem(Header(3, Bold(FontAttr(
tag, color=3D"#ff0000", size=3D"+2")).Format() +
Italic(errmsg % args).Format()))
=0C
def GetConfigOptions(mlist, category):
return mlist.GetConfigInfo()[category]
--------------BFB93F3D3F601EC069B326B6--