Index: ACKNOWLEDGMENTS =================================================================== RCS file: /cvsroot/mailman/mailman/ACKNOWLEDGMENTS,v retrieving revision 1.35 retrieving revision 1.35.2.1 diff -u -r1.35 -r1.35.2.1 --- ACKNOWLEDGMENTS 16 Nov 2000 21:57:06 -0000 1.35 +++ ACKNOWLEDGMENTS 3 Apr 2002 05:07:52 -0000 1.35.2.1 @@ -39,6 +39,7 @@ Stan Bubrouski Ted Cabeen David Champion + Rob Ellis Fil Erik Forsberg Darrell Fuhriman @@ -50,6 +51,7 @@ Andrew Kuchling Ricardo Kustner J C Lawrence + Greg Lindahl Christopher P. Lindsey Tanner Lovelace Gergely Madarasz Index: NEWS =================================================================== RCS file: /cvsroot/mailman/mailman/NEWS,v retrieving revision 1.25.2.11 retrieving revision 1.25.2.13 diff -u -r1.25.2.11 -r1.25.2.13 --- NEWS 27 Nov 2001 22:52:39 -0000 1.25.2.11 +++ NEWS 3 Apr 2002 22:50:10 -0000 1.25.2.13 @@ -4,6 +4,26 @@ Here is a history of user visible changes to Mailman. +2.0.9 (02-Apr-2002) + + - Closed a race condition which could, under rare circumstances, + cause the occasional message to get lost. + + - HTML escape message excerpts and headers on the admindb page so + JavaScript and other evil tags can't mess up the display. + + - Some additional Python 2.2 compatibility fixes. + + - Unlink the footer logos so as not to bug the python.org and + gnu.org maintainers as much. :( + + - Fix a crash in the DSN bounce detection module, which could + cause some bounce messages to remain in the queue. + + - Add the RFC-2822 mandated Date: header on internally generated + outgoing messages. Not all MTAs add this field if missing + (read: Qmail). + 2.0.8 (27-Nov-2001) Security fix release to prevent cross-site scripting exploits. Index: Mailman/Message.py =================================================================== RCS file: /cvsroot/mailman/mailman/Mailman/Message.py,v retrieving revision 1.40 retrieving revision 1.40.2.2 diff -u -r1.40 -r1.40.2.2 --- Mailman/Message.py 2 Aug 2000 02:00:13 -0000 1.40 +++ Mailman/Message.py 3 Apr 2002 22:40:41 -0000 1.40.2.2 @@ -177,11 +177,14 @@ marshal.dump(msgdata, dbfp) dbfp.close() # If it doesn't already exist, or if the text of the message has - # changed, write the message file to disk. + # changed, write the message file to disk, but do it atomically so as + # not to hit a race condition with the qrunner. if not existsp or dirty: - msgfp = Utils.open_ex(msgfile, 'w') + tmpfile = msgfile + '.tmp' + msgfp = Utils.open_ex(tmpfile, 'w') msgfp.write(text) msgfp.close() + os.rename(tmpfile, msgfile) @@ -192,6 +195,10 @@ # also begin with the body of the message but in that case you better # make sure that the first line does NOT contain a colon! Message.__init__(self, StringIO(text)) + # RFC 2822 requires a Date: header, and while most MTAs add one if + # it's missing, Qmail does not. + if not self.get('date'): + self['Date'] = Utils.formatdate(localtime=1) Index: Mailman/Utils.py =================================================================== RCS file: /cvsroot/mailman/mailman/Mailman/Utils.py,v retrieving revision 1.104.2.4 retrieving revision 1.104.2.5 diff -u -r1.104.2.4 -r1.104.2.5 --- Mailman/Utils.py 25 Jul 2001 18:06:46 -0000 1.104.2.4 +++ Mailman/Utils.py 3 Apr 2002 22:47:12 -0000 1.104.2.5 @@ -27,6 +27,7 @@ import os import string import re +import time from UserDict import UserDict from types import StringType import random @@ -690,3 +691,49 @@ if kws: raise TypeError('unexpected keywords') file.write(string.join(map(str, args), sep) + end) + + + +def formatdate(timeval=None, localtime=0): + """Returns a date string as specified by RFC 2822, e.g.: + + Fri, 09 Nov 2001 01:08:47 -0000 + + Optional timeval if given is a floating point time value as accepted by + gmtime() and localtime(), otherwise the current time is used. + + Optional localtime is a flag that when true, interprets timeval, and + returns a date relative to the local timezone instead of UTC, properly + taking daylight savings time into account. + """ + # Note: we cannot use strftime() because that honors the locale and RFC + # 2822 requires that day and month names be the English abbreviations. + if timeval is None: + timeval = time.time() + if localtime: + now = time.localtime(timeval) + # Calculate timezone offset, based on whether the local zone has + # daylight savings time, and whether DST is in effect. + if time.daylight and now[-1]: + offset = time.altzone + else: + offset = time.timezone + hours, minutes = divmod(abs(offset), 3600) + # Remember offset is in seconds west of UTC, but the timezone is in + # minutes east of UTC, so the signs differ. + if offset > 0: + sign = '-' + else: + sign = '+' + zone = '%s%02d%02d' % (sign, hours, minutes / 60) + else: + now = time.gmtime(timeval) + # Timezone offset is always -0000 + zone = '-0000' + return '%s, %02d %s %04d %02d:%02d:%02d %s' % ( + ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun'][now[6]], + now[2], + ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', + 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'][now[1] - 1], + now[0], now[3], now[4], now[5], + zone) Index: Mailman/Version.py =================================================================== RCS file: /cvsroot/mailman/mailman/Mailman/Version.py,v retrieving revision 1.20.2.8 retrieving revision 1.20.2.9 diff -u -r1.20.2.8 -r1.20.2.9 --- Mailman/Version.py 27 Nov 2001 22:47:00 -0000 1.20.2.8 +++ Mailman/Version.py 2 Apr 2002 23:36:35 -0000 1.20.2.9 @@ -15,7 +15,7 @@ # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. # Mailman version -VERSION = "2.0.8" +VERSION = "2.0.9" # And as a hex number in the manner of PY_VERSION_HEX ALPHA = 0xa @@ -27,7 +27,7 @@ MAJOR_REV = 2 MINOR_REV = 0 -MICRO_REV = 8 +MICRO_REV = 9 REL_LEVEL = FINAL # at most 15 beta releases! REL_SERIAL = 0 Index: Mailman/htmlformat.py =================================================================== RCS file: /cvsroot/mailman/mailman/Mailman/htmlformat.py,v retrieving revision 1.31 retrieving revision 1.31.2.1 diff -u -r1.31 -r1.31.2.1 --- Mailman/htmlformat.py 12 Sep 2000 04:02:36 -0000 1.31 +++ Mailman/htmlformat.py 2 Apr 2002 22:28:59 -0000 1.31.2.1 @@ -519,23 +519,13 @@ if mm_cfg.IMAGE_LOGOS: def logo(file): return mm_cfg.IMAGE_LOGOS + file - mmlink = Link(MAILMAN_URL, - 'Delivered by Mailman' - '
version %s' - % (logo(DELIVERED_BY), mm_cfg.VERSION)) - pylink = Link(PYTHON_URL, - 'Python Powered' % - logo(PYTHON_POWERED)) - gnulink = Link(GNU_URL, - 'GNU\'s Not Unix' % - logo(GNU_HEAD)) - text = Container(Link(MAILMAN_URL, 'Mailman home page'), - '
', - Link(PYTHON_URL, 'Python home page'), - '
', - Link(GNU_URL, 'GNU home page'), - ) - t.AddRow([mmlink, pylink, gnulink, text]) + mmlink = 'Delivered by Mailman' \ + '
version %s' % (logo(DELIVERED_BY), mm_cfg.VERSION) + pylink = 'Python Powered' % \ + logo(PYTHON_POWERED) + gnulink = 'GNU\'s Not Unix' % \ + logo(GNU_HEAD) + t.AddRow([mmlink, pylink, gnulink]) else: # use only textual links mmlink = Link(MAILMAN_URL, Index: Mailman/Archiver/HyperArch.py =================================================================== RCS file: /cvsroot/mailman/mailman/Mailman/Archiver/HyperArch.py,v retrieving revision 1.46 retrieving revision 1.46.2.1 diff -u -r1.46 -r1.46.2.1 --- Mailman/Archiver/HyperArch.py 13 Nov 2000 21:50:05 -0000 1.46 +++ Mailman/Archiver/HyperArch.py 2 Apr 2002 23:39:35 -0000 1.46.2.1 @@ -39,11 +39,12 @@ import time import pickle import os -import posixfile import HyperDatabase import pipermail -from Mailman import mm_cfg, EncWord +from Mailman import mm_cfg +from Mailman import LockFile +from Mailman import EncWord from Mailman.Logging.Syslog import syslog from Mailman.Utils import mkdir, open_ex @@ -699,27 +700,18 @@ def GetArchLock(self): if self._lock_file: return 1 - # TBD: This needs to be rewritten to use the generalized locking - # mechanism (when that exists). -baw - ou = os.umask(0) + self._lock_file = LockFile.LockFile( + os.path.join(mm_cfg.LOCK_DIR, + self.maillist.internal_name() + '-arch.lock')) try: - self._lock_file = posixfile.open( - os.path.join(mm_cfg.LOCK_DIR, '%s@arch.lock' - % self.maillist.internal_name()), 'a+') - finally: - os.umask(ou) - # minor race condition here, there is no way to atomicly - # check & get a lock. That shouldn't matter here tho' -ddm - if not self._lock_file.lock('w?', 1): - self._lock_file.lock('w|', 1) - else: + self._lock_file.lock(timeout=0.5) + except LockFile.TimeOutError: return 0 return 1 def DropArchLock(self): if self._lock_file: - self._lock_file.lock('u') - self._lock_file.close() + self._lock_file.unlock(unconditionally=1) self._lock_file = None def processListArch(self): Index: Mailman/Bouncers/DSN.py =================================================================== RCS file: /cvsroot/mailman/mailman/Mailman/Bouncers/DSN.py,v retrieving revision 1.7.2.2 retrieving revision 1.7.2.4 diff -u -r1.7.2.2 -r1.7.2.4 --- Mailman/Bouncers/DSN.py 6 Nov 2001 04:27:30 -0000 1.7.2.2 +++ Mailman/Bouncers/DSN.py 29 Mar 2002 18:44:05 -0000 1.7.2.4 @@ -43,7 +43,7 @@ def process(msg): - ctype = msg.gettype() + ctype = msg.gettype() or '' param = msg.getparam('report-type') or '' if string.lower(ctype) <> 'multipart/report' or \ string.lower(param) <> 'delivery-status': @@ -59,6 +59,11 @@ more = mfile.next() except multifile.Error: # the message *looked* like a DSN, but it really wasn't :( + return None + except TypeError: + # This message has serious problems, pass it on. Seen in the + # wild: it is a MIME document with no boundary parameter in its + # Content-Type: header. return None if not more: # we didn't find it Index: Mailman/Cgi/admindb.py =================================================================== RCS file: /cvsroot/mailman/mailman/Mailman/Cgi/admindb.py,v retrieving revision 1.36.2.5 retrieving revision 1.36.2.7 diff -u -r1.36.2.5 -r1.36.2.7 --- Mailman/Cgi/admindb.py 27 Nov 2001 20:23:53 -0000 1.36.2.5 +++ Mailman/Cgi/admindb.py 1 Apr 2002 18:47:46 -0000 1.36.2.7 @@ -207,7 +207,7 @@ return raise t = Table(cellspacing=0, cellpadding=0, width='100%') - t.AddRow([Bold('From:'), sender]) + t.AddRow([Bold('From:'), cgi.escape(sender)]) row, col = t.GetCurrentRowIndex(), t.GetCurrentCellIndex() t.AddCellInfo(row, col-1, align='right') t.AddRow([Bold('Subject:'), cgi.escape(subject)]) @@ -247,12 +247,14 @@ row, col = t.GetCurrentRowIndex(), t.GetCurrentCellIndex() t.AddCellInfo(row, col-1, align='right') t.AddRow([Bold('Message Headers:'), - TextArea('headers-%d' % id, string.join(msg.headers, ''), + TextArea('headers-%d' % id, + cgi.escape(string.join(msg.headers, '')), 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)]) + TextArea('fulltext-%d' % id, cgi.escape(text), + rows=10, cols=80)]) t.AddCellInfo(row+1, col-1, align='right') form.AddItem(t) form.AddItem('

') Index: admin/www/download.ht =================================================================== RCS file: /cvsroot/mailman/mailman/admin/www/download.ht,v retrieving revision 1.5.2.9 retrieving revision 1.5.2.10 diff -u -r1.5.2.9 -r1.5.2.10 --- admin/www/download.ht 27 Nov 2001 22:27:42 -0000 1.5.2.9 +++ admin/www/download.ht 3 Apr 2002 05:11:22 -0000 1.5.2.10 @@ -65,9 +65,9 @@

Downloading

Version -(2.0.8, +(2.0.9, released on -Nov 27 2001) +Apr 3 2002) is the current GNU release. It is available from the following mirror sites: