summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorbwarsaw2001-03-01 05:36:43 +0000
committerbwarsaw2001-03-01 05:36:43 +0000
commit18c7a072f89614ae65907f10246ecc15877704ce (patch)
treeb11b52a236d7fd1c2f587ff3b5664daff4649c76
parentd347017d0fd1b37116da1651489473a8036656b5 (diff)
downloadmailman-18c7a072f89614ae65907f10246ecc15877704ce.tar.gz
mailman-18c7a072f89614ae65907f10246ecc15877704ce.tar.zst
mailman-18c7a072f89614ae65907f10246ecc15877704ce.zip
More i18n changes.
At module scope, set the system language to the server's default, until we know which list this is a request on. main(): Don't lock the list until absolutely necessary. Also, once the list is instantiated, set the system language to the list's preferred language. Once the html results document object is created, set its language to the list's preferred language too. HandleRequests() -> process_form() PrintRequests() -> show_requests() handle_no_list(): Be sure to set the document's language to the server's default (since there is no instantiated list at this point). show_requests(): Support DEFER and DISCARD on subscription requests, just like as for held posts. PrintAddMemberRequest(): Inlined and removed. PrintPostRequest() -> show_post_requests() show_post_requests(): Convert to using the mimelib interface (it's a minor shame that we have to reparse the message object to display it on this page). Watch for mimelib.Errors.MessageParseError's which could result if the held message is corrupted. If this occurs, we discard the message, but that may not be the right thing to do. process_form(): Don't save the MailList object here; that happens in the finally: clause in main(). Also some minor verbiage and formatting changes.
-rw-r--r--Mailman/Cgi/admindb.py258
1 files changed, 152 insertions, 106 deletions
diff --git a/Mailman/Cgi/admindb.py b/Mailman/Cgi/admindb.py
index 1c1e76786..d5d08b2f6 100644
--- a/Mailman/Cgi/admindb.py
+++ b/Mailman/Cgi/admindb.py
@@ -19,152 +19,170 @@
import os
import types
import cgi
-from errno import ENOENT
+import errno
from mimelib.Parser import Parser
+from mimelib.MsgReader import MsgReader
+import mimelib.Errors
from Mailman import mm_cfg
from Mailman import Utils
from Mailman import MailList
from Mailman import Errors
from Mailman import Message
+from Mailman import i18n
from Mailman.Cgi import Auth
from Mailman.htmlformat import *
from Mailman.Logging.Syslog import syslog
-from Mailman.i18n import _
NL = '\n'
-
-
-def handle_no_list(doc, extra=''):
- doc.SetTitle(_('Mailman Admindb Error'))
- doc.AddItem(Header(2, _('Mailman Admindb Error')))
- doc.AddItem(extra)
- doc.AddItem(_('You must specify a list name. Here is the '))
- link = mm_cfg.DEFAULT_URL
- if link[-1] <> '/':
- link = link + '/'
- link = link + 'admin'
- doc.AddItem(Link(link, _('list of available mailing lists.')))
- print doc.Format(bgcolor="#ffffff")
+# Set up i18n. Until we know which list is being requested, we use the
+# server's default.
+_ = i18n._
+i18n.set_language(mm_cfg.DEFAULT_SERVER_LANGUAGE)
def main():
- doc = Document()
- # figure out which list we're going to process
+ # Figure out which list is being requested
parts = Utils.GetPathPieces()
if not parts:
- handle_no_list(doc)
- return
- # get URL components. the list name should be the zeroth part
- try:
- listname = parts[0].lower()
- except IndexError:
- handle_no_list(doc)
+ handle_no_list()
return
- # now that we have the list name, create the list object
+
+ listname = parts[0].lower()
try:
- mlist = MailList.MailList(listname)
+ mlist = MailList.MailList(listname, lock=0)
except Errors.MMListError, e:
- handle_no_list(doc, _('No such list <em>%(listname)s</em><p>'))
+ handle_no_list(doc, _('No such list <em>%(listname)s</em>'))
syslog('error', 'No such list "%s": %s\n' % (listname, e))
return
- os.environ['LANG'] = mlist.preferred_language
+ # Now that we know which list to use, set the system's language to it.
+ i18n.set_language(mlist.preferred_language)
- #
- # now we must authorize the user to view this page, and if they are, to
- # handle both the printing of the current outstanding requests, and the
- # selected actions
+ # Make sure the user is authorized to see this page.
+ cgidata = cgi.FieldStorage()
try:
- cgidata = cgi.FieldStorage()
- try:
- Auth.authenticate(mlist, cgidata)
- except Auth.NotLoggedInError, e:
- Auth.loginpage(mlist, 'admindb', e.message)
- return
+ Auth.authenticate(mlist, cgidata)
+ except Auth.NotLoggedInError, e:
+ Auth.loginpage(mlist, 'admindb', e.message)
+ return
- # If this is a form submission, then we'll process the requests and
- # print the results. otherwise (there are no keys in the form), we'll
- # print out the list of pending requests
- #
+ # Set up the results document
+ doc = Document()
+ doc.set_language(mlist.preferred_language)
+
+ # Lock the list for the next operation. BAW: Strictly speaking, the list
+ # should not need to be locked just to read the request database. However
+ # the request database asserts that the list is locked in order to load
+ # it and it's not worth complicating that logic.
+ mlist.Lock()
+ try:
realname = mlist.real_name
- if len(cgidata.keys()):
- doc.SetTitle(_("%(realname)s Admindb Results"))
- HandleRequests(mlist, doc, cgidata)
+ if not cgidata.keys():
+ # If this is not a form submission (i.e. there are no keys in the
+ # form), then all we don't need to do much special.
+ doc.SetTitle(_('%(realname)s Administrative Database'))
else:
- doc.SetTitle(_("%(realname)s Admindb"))
- PrintRequests(mlist, doc)
- text = doc.Format(bgcolor="#ffffff")
- print text
+ # This is a form submission
+ doc.SetTitle(_('%(realname)s Administrative Database Results'))
+ process_form(mlist, doc, cgidata)
+ # Now print the results and we're done
+ show_requests(mlist, doc)
finally:
mlist.Save()
mlist.Unlock()
+ print doc.Format(bgcolor='#ffffff')
+
-def PrintRequests(mlist, 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(Header(2, _('Administrative requests for mailing list:') + ' <em>' +
- mlist.real_name + '</em>'))
- # short circuit for when there are no pending requests
+def handle_no_list(msg=''):
+ # Print something useful if no list was given.
+ doc = Document()
+ doc.set_language(mm_cfg.DEFAULT_SERVER_LANGUAGE)
+
+ header = _('Mailman Administrative Database Error')
+ doc.SetTitle(header)
+ doc.AddItem(Header(2, header))
+ doc.AddItem(msg)
+ doc.AddItem(_('You must specify a list name. Here is the '))
+ # Server's top level URL -- it must end in a slash!
+ link = mm_cfg.DEFAULT_URL
+ if not link.endswith('/'):
+ link += '/'
+ link += 'admin'
+ doc.AddItem(Link(link, _('list of available mailing lists.')))
+ print doc.Format(bgcolor="#ffffff")
+
+
+
+def show_requests(mlist, doc):
+ # Print all the requests outstanding in the database. The only ones we
+ # know about are subscription and post requests. 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(Header(2, _('Administrative requests for mailing list:')
+ + ' <em>%s</em>' % mlist.real_name))
+ # Short circuit for when there are no pending requests
if not mlist.NumRequestsPending():
doc.AddItem(_('There are no pending requests.'))
doc.AddItem(mlist.GetMailmanFooter())
return
+ # Add the preamble template
doc.AddItem(Utils.maketext(
- 'admindbpreamble.html', {'listname': mlist.real_name},
+ 'admindbpreamble.html',
+ {'listname': mlist.real_name},
lang=mlist.preferred_language, raw=1))
- doc.AddItem('.<p>')
+
+ # Form submits back to this script
form = Form(mlist.GetScriptURL('admindb'))
doc.AddItem(form)
form.AddItem(SubmitButton('submit', _('Submit All Data')))
- #
# Add the subscription request section
subpendings = mlist.GetSubscriptionIds()
if subpendings:
form.AddItem('<hr>')
form.AddItem(Center(Header(2, _('Subscription Requests'))))
- t = Table(border=2)
- t.AddRow([
- Bold(_('Address')),
- Bold(_('Your Decision')),
- Bold(_('If you refuse this subscription, please explain (optional)'))
- ])
+ table = Table(border=2)
+ table.AddRow([Center(Bold(_('Address'))),
+ Center(Bold(_('Your Decision'))),
+ Center(Bold(_('Reason for refusal')))
+ ])
for id in subpendings:
- PrintAddMemberRequest(mlist, id, t)
- form.AddItem(t)
- # Post holds are now handled differently
+ time, addr, passwd, digest, lang = mlist.GetRecord(id)
+ table.AddRow([addr,
+ RadioButtonArray(id, (_('Defer'),
+ _('Approve'),
+ _('Reject'),
+ _('Discard')),
+ values=(mm_cfg.DEFER,
+ mm_cfg.SUBSCRIBE,
+ mm_cfg.REJECT,
+ mm_cfg.DISCARD),
+ checked=0),
+ TextBox('comment-%d' % id, size=45)
+ ])
+ form.AddItem(table)
+ # Post holds are handled differently
heldmsgs = mlist.GetHeldMessageIds()
total = len(heldmsgs)
if total:
count = 1
for id in heldmsgs:
info = mlist.GetRecord(id)
- PrintPostRequest(mlist, id, info, total, count, form)
- count = count + 1
+ show_post_requests(mlist, id, info, total, count, form)
+ count += 1
form.AddItem('<hr>')
form.AddItem(SubmitButton('submit', _('Submit All Data')))
doc.AddItem(mlist.GetMailmanFooter())
-def PrintAddMemberRequest(mlist, id, table):
- time, addr, passwd, digest, lang = mlist.GetRecord(id)
- table.AddRow([addr,
- RadioButtonArray(id, (_('Subscribe'), _('Refuse')),
- values=(mm_cfg.SUBSCRIBE, mm_cfg.REJECT)),
- TextBox('comment-%d' % id, size=60)
- ])
-
-
-
-def PrintPostRequest(mlist, id, info, total, count, form):
+def show_post_requests(mlist, id, info, total, count, form):
# For backwards compatibility with pre 2.0beta3
if len(info) == 5:
ptime, sender, subject, reason, filename = info
@@ -172,28 +190,58 @@ def PrintPostRequest(mlist, id, info, total, count, form):
else:
ptime, sender, subject, reason, filename, msgdata = info
form.AddItem('<hr>')
+ # Header shown on each held posting (including count of total)
msg = _('Posting Held for Approval')
if total <> 1:
- msg = msg + _(' (%d of %d)') % (count, total)
+ msg += _(' (%d of %d)') % (count, total)
form.AddItem(Center(Header(2, msg)))
+ # We need to get the headers and part of the textual body of the message
+ # being held. The best way to do this is to use the mimelib Parser to get
+ # an actual object, which will be easier to deal with. We probably could
+ # just do raw reads on the file.
p = Parser(Message.Message)
try:
fp = open(os.path.join(mm_cfg.DATA_DIR, filename))
msg = p.parse(fp)
fp.close()
- text = msg.get_text()[:mm_cfg.ADMINDB_PAGE_TEXT_LIMIT]
- except IOError, (code, msg):
- if code == ENOENT:
- form.AddItem(_('<em>Message with id #%d was lost.') % id)
- form.AddItem('<p>')
- # TBD: kludge to remove id from requests.db. value==2 means
- # discard the message.
- try:
- mlist.HandleRequest(id, mm_cfg.DISCARD)
- except Errors.LostHeldMessage:
- pass
- return
- raise
+ except IOError, e:
+ if e.code <> errno.ENOENT:
+ raise
+ form.AddItem(_('<em>Message with id #%(id)d was lost.'))
+ form.AddItem('<p>')
+ # BAW: kludge to remove id from requests.db.
+ try:
+ mlist.HandleRequest(id, mm_cfg.DISCARD)
+ except Errors.LostHeldMessage:
+ pass
+ return
+ except mimelib.Errors.MessageParseError:
+ form.AddItem(_('<em>Message with id #%(id)d is corrupted.'))
+ # BAW: Should we really delete this, or shuttle it off for site admin
+ # to look more closely at?
+ form.AddItem('<p>')
+ # BAW: kludge to remove id from requests.db.
+ try:
+ mlist.HandleRequest(id, mm_cfg.DISCARD)
+ except Errors.LostHeldMessage:
+ pass
+ return
+ # Get the header text and the message body excerpt
+ lines = []
+ chars = 0
+ reader = MsgReader(msg)
+ while 1:
+ line = reader.readline()
+ if not line:
+ break
+ lines.append(line)
+ chars += len(line)
+ if chars > mm_cfg.ADMINDB_PAGE_TEXT_LIMIT:
+ break
+ body = NL.join(lines)[:mm_cfg.ADMINDB_PAGE_TEXT_LIMIT]
+ hdrtxt = NL.join(['%s: %s' % (k, v) for k, v in msg.items()])
+
+ # Okay, we've reconstituted the message just fine. Now for the fun part!
t = Table(cellspacing=0, cellpadding=0, width='100%')
t.AddRow([Bold(_('From:')), sender])
row, col = t.GetCurrentRowIndex(), t.GetCurrentCellIndex()
@@ -237,21 +285,21 @@ def PrintPostRequest(mlist, id, info, total, count, form):
])
row, col = t.GetCurrentRowIndex(), t.GetCurrentCellIndex()
t.AddCellInfo(row, col-1, align='right')
- hdrtxt = NL.join(['%s: %s' % (k, v) for k, v in msg.items()])
t.AddRow([Bold(_('Message Headers:')),
TextArea('headers-%d' % id, hdrtxt,
rows=10, cols=80)])
row, col = t.GetCurrentRowIndex(), t.GetCurrentCellIndex()
t.AddCellInfo(row, col-1, align='right')
- t.AddRow ([Bold(_('Message Excerpt:')),
- TextArea('fulltext-%d' % id, text, rows=10, cols=80)])
+ t.AddRow([Bold(_('Message Excerpt:')),
+ TextArea('fulltext-%d' % id, body, rows=10, cols=80)])
t.AddCellInfo(row+1, col-1, align='right')
form.AddItem(t)
form.AddItem('<p>')
-def HandleRequests(mlist, doc, cgidata):
+def process_form(mlist, doc, cgidata):
+ # Process the form and make updates to the admin database.
erroraddrs = []
for k in cgidata.keys():
formv = cgidata[k]
@@ -262,12 +310,12 @@ def HandleRequests(mlist, doc, cgidata):
request_id = int(k)
except ValueError:
continue
- # get the action comment and reasons if present
+ # Get the action comment and reasons if present.
commentkey = 'comment-%d' % request_id
preservekey = 'preserve-%d' % request_id
forwardkey = 'forward-%d' % request_id
forwardaddrkey = 'forward-addr-%d' % request_id
- # defaults
+ # Defaults
comment = _('[No reason given]')
preserve = 0
forward = 0
@@ -280,19 +328,17 @@ def HandleRequests(mlist, doc, cgidata):
forward = cgidata[forwardkey].value
if cgidata.has_key(forwardaddrkey):
forwardaddr = cgidata[forwardaddrkey].value
- #
- # handle the request id
+ # Handle the request id
try:
mlist.HandleRequest(request_id, v, comment,
preserve, forward, forwardaddr)
except (KeyError, Errors.LostHeldMessage):
- # that's okay, it just means someone else has already updated the
- # database, so just ignore this id
+ # That's okay, it just means someone else has already updated the
+ # database while we were staring at the page, so just ignore it
continue
except Errors.MMAlreadyAMember, v:
erroraddrs.append(v)
# save the list and print the results
- mlist.Save()
doc.AddItem(Header(2, _('Database Updated...')))
if erroraddrs:
for addr in erroraddrs: