aboutsummaryrefslogtreecommitdiffstats
path: root/Mailman/Cgi/admindb.py
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--Mailman/Cgi/admindb.py136
1 files changed, 98 insertions, 38 deletions
diff --git a/Mailman/Cgi/admindb.py b/Mailman/Cgi/admindb.py
index d1873321..d3350ea7 100644
--- a/Mailman/Cgi/admindb.py
+++ b/Mailman/Cgi/admindb.py
@@ -1,4 +1,4 @@
-# Copyright (C) 1998-2011 by the Free Software Foundation, Inc.
+# Copyright (C) 1998-2013 by the Free Software Foundation, Inc.
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
@@ -50,16 +50,38 @@ i18n.set_language(mm_cfg.DEFAULT_SERVER_LANGUAGE)
EXCERPT_HEIGHT = 10
EXCERPT_WIDTH = 76
+SSENDER = mm_cfg.SSENDER
+SSENDERTIME = mm_cfg.SSENDERTIME
+STIME = mm_cfg.STIME
+if mm_cfg.DISPLAY_HELD_SUMMARY_SORT_BUTTONS in (SSENDERTIME, STIME):
+ ssort = mm_cfg.DISPLAY_HELD_SUMMARY_SORT_BUTTONS
+else:
+ ssort = SSENDER
-def helds_by_sender(mlist):
+def helds_by_skey(mlist, ssort=SSENDER):
heldmsgs = mlist.GetHeldMessageIds()
- bysender = {}
+ byskey = {}
for id in heldmsgs:
+ ptime = mlist.GetRecord(id)[0]
sender = mlist.GetRecord(id)[1]
- bysender.setdefault(sender, []).append(id)
- return bysender
+ if ssort in (SSENDER, SSENDERTIME):
+ skey = (0, sender)
+ else:
+ skey = (ptime, sender)
+ byskey.setdefault(skey, []).append((ptime, id))
+ # Sort groups by time
+ for k, v in byskey.items():
+ if len(v) > 1:
+ v.sort()
+ byskey[k] = v
+ if ssort == SSENDERTIME:
+ # Rekey with time
+ newkey = (v[0][0], k[1])
+ del byskey[k]
+ byskey[newkey] = v
+ return byskey
def hacky_radio_buttons(btnname, labels, values, defaults, spacing=3):
@@ -76,6 +98,7 @@ def hacky_radio_buttons(btnname, labels, values, defaults, spacing=3):
def main():
+ global ssort
# Figure out which list is being requested
parts = Utils.GetPathPieces()
if not parts:
@@ -253,7 +276,7 @@ def main():
raw=1, mlist=mlist))
num = show_pending_subs(mlist, form)
num += show_pending_unsubs(mlist, form)
- num += show_helds_overview(mlist, form)
+ num += show_helds_overview(mlist, form, ssort)
addform = num > 0
# Finish up the document, adding buttons to the form
if addform:
@@ -314,10 +337,10 @@ def show_pending_subs(mlist, form):
for id in pendingsubs:
addr = mlist.GetRecord(id)[1]
byaddrs.setdefault(addr, []).append(id)
- addrs = byaddrs.keys()
+ addrs = byaddrs.items()
addrs.sort()
num = 0
- for addr, ids in byaddrs.items():
+ for addr, ids in addrs:
# Eliminate duplicates
for id in ids[1:]:
mlist.HandleRequest(id, mm_cfg.DISCARD)
@@ -365,10 +388,10 @@ def show_pending_unsubs(mlist, form):
for id in pendingunsubs:
addr = mlist.GetRecord(id)
byaddrs.setdefault(addr, []).append(id)
- addrs = byaddrs.keys()
+ addrs = byaddrs.items()
addrs.sort()
num = 0
- for addr, ids in byaddrs.items():
+ for addr, ids in addrs:
# Eliminate duplicates
for id in ids[1:]:
mlist.HandleRequest(id, mm_cfg.DISCARD)
@@ -402,20 +425,29 @@ def show_pending_unsubs(mlist, form):
-def show_helds_overview(mlist, form):
- # Sort the held messages by sender
- bysender = helds_by_sender(mlist)
- if not bysender:
+def show_helds_overview(mlist, form, ssort=SSENDER):
+ # Sort the held messages.
+ byskey = helds_by_skey(mlist, ssort)
+ if not byskey:
return 0
form.AddItem('<hr>')
form.AddItem(Center(Header(2, _('Held Messages'))))
+ # Add the sort sequence choices if wanted
+ if mm_cfg.DISPLAY_HELD_SUMMARY_SORT_BUTTONS:
+ form.AddItem(Center(_('Show this list grouped/sorted by')))
+ form.AddItem(Center(hacky_radio_buttons(
+ 'summary_sort',
+ (_('sender/sender'), _('sender/time'), _('ungrouped/time')),
+ (SSENDER, SSENDERTIME, STIME),
+ (ssort == SSENDER, ssort == SSENDERTIME, ssort == STIME))))
# Add the by-sender overview tables
admindburl = mlist.GetScriptURL('admindb', absolute=1)
table = Table(border=0)
form.AddItem(table)
- senders = bysender.keys()
- senders.sort()
- for sender in senders:
+ skeys = byskey.keys()
+ skeys.sort()
+ for skey in skeys:
+ sender = skey[1]
qsender = quote_plus(sender)
esender = Utils.websafe(sender)
senderurl = admindburl + '?sender=' + qsender
@@ -499,7 +531,7 @@ def show_helds_overview(mlist, form):
right.AddCellInfo(right.GetCurrentRowIndex(), 0, colspan=2)
right.AddRow(['&nbsp;', '&nbsp;'])
counter = 1
- for id in bysender[sender]:
+ for ptime, id in byskey[skey]:
info = mlist.GetRecord(id)
ptime, sender, subject, reason, filename, msgdata = info
# BAW: This is really the size of the message pickle, which should
@@ -540,13 +572,14 @@ def show_helds_overview(mlist, form):
def show_sender_requests(mlist, form, sender):
- bysender = helds_by_sender(mlist)
- if not bysender:
+ byskey = helds_by_skey(mlist, SSENDER)
+ if not byskey:
return
- sender_ids = bysender.get(sender)
+ sender_ids = byskey.get((0, sender))
if sender_ids is None:
# BAW: should we print an error message?
return
+ sender_ids = [x[1] for x in sender_ids]
total = len(sender_ids)
count = 1
for id in sender_ids:
@@ -709,7 +742,9 @@ def show_post_requests(mlist, id, info, total, count, form):
def process_form(mlist, doc, cgidata):
+ global ssort
senderactions = {}
+ badaddrs = []
# Sender-centric actions
for k in cgidata.keys():
for prefix in ('senderaction-', 'senderpreserve-', 'senderforward-',
@@ -729,6 +764,8 @@ def process_form(mlist, doc, cgidata):
discardalldefersp = cgidata.getvalue('discardalldefersp', 0)
except ValueError:
discardalldefersp = 0
+ # Get the summary sequence
+ ssort = int(cgidata.getvalue('summary_sort', SSENDER))
for sender in senderactions.keys():
actions = senderactions[sender]
# Handle what to do about all this sender's held messages
@@ -743,8 +780,8 @@ def process_form(mlist, doc, cgidata):
preserve = actions.get('senderpreserve', 0)
forward = actions.get('senderforward', 0)
forwardaddr = actions.get('senderforwardto', '')
- bysender = helds_by_sender(mlist)
- for id in bysender.get(sender, []):
+ byskey = helds_by_skey(mlist, SSENDER)
+ for ptime, id in byskey.get((0, sender), []):
if id not in senderactions[sender]['message_ids']:
# It arrived after the page was displayed. Skip it.
continue
@@ -762,20 +799,27 @@ def process_form(mlist, doc, cgidata):
# Now see if this sender should be added to one of the nonmember
# sender filters.
if actions.get('senderfilterp', 0):
+ # Check for an invalid sender address.
try:
- which = int(actions.get('senderfilter'))
- except ValueError:
- # Bogus form
- which = 'ignore'
- if which == mm_cfg.ACCEPT:
- mlist.accept_these_nonmembers.append(sender)
- elif which == mm_cfg.HOLD:
- mlist.hold_these_nonmembers.append(sender)
- elif which == mm_cfg.REJECT:
- mlist.reject_these_nonmembers.append(sender)
- elif which == mm_cfg.DISCARD:
- mlist.discard_these_nonmembers.append(sender)
- # Otherwise, it's a bogus form, so ignore it
+ Utils.ValidateEmail(sender)
+ except Errors.EmailAddressError:
+ # Don't check for dups. Report it once for each checked box.
+ badaddrs.append(sender)
+ else:
+ try:
+ which = int(actions.get('senderfilter'))
+ except ValueError:
+ # Bogus form
+ which = 'ignore'
+ if which == mm_cfg.ACCEPT:
+ mlist.accept_these_nonmembers.append(sender)
+ elif which == mm_cfg.HOLD:
+ mlist.hold_these_nonmembers.append(sender)
+ elif which == mm_cfg.REJECT:
+ mlist.reject_these_nonmembers.append(sender)
+ elif which == mm_cfg.DISCARD:
+ mlist.discard_these_nonmembers.append(sender)
+ # Otherwise, it's a bogus form, so ignore it
# And now see if we're to clear the member's moderation flag.
if actions.get('senderclearmodp', 0):
try:
@@ -785,8 +829,15 @@ def process_form(mlist, doc, cgidata):
pass
# And should this address be banned?
if actions.get('senderbanp', 0):
- if sender not in mlist.ban_list:
- mlist.ban_list.append(sender)
+ # Check for an invalid sender address.
+ try:
+ Utils.ValidateEmail(sender)
+ except Errors.EmailAddressError:
+ # Don't check for dups. Report it once for each checked box.
+ badaddrs.append(sender)
+ else:
+ if sender not in mlist.ban_list:
+ mlist.ban_list.append(sender)
# Now, do message specific actions
banaddrs = []
erroraddrs = []
@@ -836,6 +887,8 @@ def process_form(mlist, doc, cgidata):
if cgidata.getvalue(bankey):
sender = mlist.GetRecord(request_id)[1]
if sender not in mlist.ban_list:
+ # We don't need to validate the sender. An invalid address
+ # can't get here.
mlist.ban_list.append(sender)
# Handle the request id
try:
@@ -854,7 +907,14 @@ def process_form(mlist, doc, cgidata):
doc.AddItem(Header(2, _('Database Updated...')))
if erroraddrs:
for addr in erroraddrs:
+ addr = Utils.websafe(addr)
doc.AddItem(`addr` + _(' is already a member') + '<br>')
if banaddrs:
for addr, patt in banaddrs:
+ addr = Utils.websafe(addr)
doc.AddItem(_('%(addr)s is banned (matched: %(patt)s)') + '<br>')
+ if badaddrs:
+ for addr in badaddrs:
+ addr = Utils.websafe(addr)
+ doc.AddItem(`addr` + ': ' + _('Bad/Invalid email address') +
+ '<br>')