diff -r eab6243607cb -r 5443cb9b550a mailman/mailman.patch --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/mailman/mailman.patch Wed Dec 17 15:02:08 2008 +0100 @@ -0,0 +1,247 @@ +Index: Mailman/Archiver/pipermail.py +--- Mailman/Archiver/pipermail.py.orig 2008-06-30 18:29:46 +0200 ++++ Mailman/Archiver/pipermail.py 2008-07-01 20:48:10 +0200 +@@ -122,9 +122,9 @@ + parentID = article.parentID + if parentID is not None and self.articleIndex.has_key(parentID): + parent = self.getArticle(archive, parentID) +- myThreadKey = parent.threadKey + article.date + '-' ++ myThreadKey = parent.threadKey + article.date + '/' + article.msgid + '-' + else: +- myThreadKey = article.date + '-' ++ myThreadKey = article.date + '/' + article.msgid + '-' + article.threadKey = myThreadKey + key = myThreadKey, article.msgid + self.setThreadKey(archive, key, article.msgid) +@@ -418,7 +418,7 @@ + else: + parent = self.database.getArticle(self.archive, + article.parentID) +- article.threadKey = parent.threadKey+article.date+'-' ++ article.threadKey = parent.threadKey + article.date + '/' + article.msgid + '-' + self.database.setThreadKey(self.archive, + (article.threadKey, article.msgid), + msgid) +@@ -632,9 +632,9 @@ + article.parentID = parentID = self.get_parent_info(arch, article) + if parentID: + parent = self.database.getArticle(arch, parentID) +- article.threadKey = parent.threadKey + article.date + '-' ++ article.threadKey = parent.threadKey + article.date + '/' + article.msgid + '-' + else: +- article.threadKey = article.date + '-' ++ article.threadKey = article.date + '/' + article.msgid + '-' + key = article.threadKey, article.msgid + + self.database.setThreadKey(arch, key, article.msgid) +Index: Mailman/Commands/cmd_subscribe.py +--- Mailman/Commands/cmd_subscribe.py.orig 2008-06-30 18:29:46 +0200 ++++ Mailman/Commands/cmd_subscribe.py 2008-07-01 20:48:10 +0200 +@@ -84,6 +84,7 @@ + if password is None: + password = Utils.MakeRandomPassword() + if address is None: ++ h = None + realname, address = parseaddr(res.msg['from']) + if not address: + # Fall back to the sender address +Index: Mailman/HTMLFormatter.py +--- Mailman/HTMLFormatter.py.orig 2008-06-30 18:29:46 +0200 ++++ Mailman/HTMLFormatter.py 2008-07-01 20:48:10 +0200 +@@ -44,7 +44,7 @@ + realname = self.real_name + hostname = self.host_name + listinfo_link = Link(self.GetScriptURL('listinfo'), realname).Format() +- owner_link = Link('mailto:' + self.GetOwnerEmail(), ownertext).Format() ++ owner_link = Link('mailto:' + self.GetOwnerEmail(), realname + '-owner').Format() + innertext = _('%(listinfo_link)s list run by %(owner_link)s') + return Container( + '
', +Index: Mailman/Handlers/Decorate.py +--- Mailman/Handlers/Decorate.py.orig 2008-06-30 18:29:46 +0200 ++++ Mailman/Handlers/Decorate.py 2008-07-01 20:48:10 +0200 +@@ -197,6 +197,7 @@ + del msg['content-transfer-encoding'] + del msg['content-disposition'] + msg['Content-Type'] = 'multipart/mixed' ++ msg['Mime-version'] = '1.0' + + + +Index: Mailman/Handlers/Scrubber.py +--- Mailman/Handlers/Scrubber.py.orig 2008-06-30 18:29:46 +0200 ++++ Mailman/Handlers/Scrubber.py 2008-07-01 20:48:10 +0200 +@@ -385,6 +385,8 @@ + t = unicode(t, 'ascii', 'replace') + try: + # Should use HTML-Escape, or try generalizing to UTF-8 ++ if len(charset) == 0: ++ charset = 'us-ascii' + t = t.encode(charset, 'replace') + except (UnicodeError, LookupError, ValueError, + AssertionError): +Index: Mailman/Queue/OutgoingRunner.py +--- Mailman/Queue/OutgoingRunner.py.orig 2008-06-30 18:29:46 +0200 ++++ Mailman/Queue/OutgoingRunner.py 2008-07-01 20:48:10 +0200 +@@ -89,6 +89,7 @@ + syslog('error', 'Cannot connect to SMTP server %s on port %s', + mm_cfg.SMTPHOST, port) + self.__logged = True ++ self._snooze(0) + return True + except Errors.SomeRecipientsFailed, e: + # Handle local rejects of probe messages differently. +Index: Mailman/htmlformat.py +--- Mailman/htmlformat.py.orig 2008-06-30 18:29:46 +0200 ++++ Mailman/htmlformat.py 2008-07-01 20:48:10 +0200 +@@ -300,7 +300,8 @@ + charset = 'us-ascii' + if self.language: + charset = Utils.GetCharSet(self.language) +- output = ['Content-Type: text/html; charset=%s\n' % charset] ++ output = ['Content-Type: text/html; charset=%s' % charset] ++ output.append('Cache-control: no-cache\n') + if not self.suppress_head: + kws.setdefault('bgcolor', self.bgcolor) + tab = ' ' * indent +Index: bin/check_perms +--- bin/check_perms.orig 2008-06-30 18:29:46 +0200 ++++ bin/check_perms 2008-07-01 20:48:10 +0200 +@@ -82,7 +82,7 @@ + return os.stat(path)[ST_MODE] + + def statgidmode(path): +- stat = os.stat(path) ++ stat = os.lstat(path) + return stat[ST_MODE], stat[ST_GID] + + seen = {} +Index: bin/config_list +--- bin/config_list.orig 2008-06-30 18:29:46 +0200 ++++ bin/config_list 2008-07-01 20:48:10 +0200 +@@ -307,6 +307,11 @@ + in mm_cfg.OPTINFO.items() + if validval & bitval] + gui._setValue(mlist, k, validval, fakedoc) ++ # Ugly hack, but seems to be needed since ++ # new_member_options isn't really a number in gui. ++ # -- tfheen, 2003-12-06 ++ if k == "new_member_options": ++ mlist.new_member_options = validval + # BAW: when to do gui._postValidate()??? + finally: + if savelist and not checkonly: +Index: bin/mailmanctl +--- bin/mailmanctl.orig 2008-06-30 18:29:46 +0200 ++++ bin/mailmanctl 2008-07-01 20:48:10 +0200 +@@ -417,6 +417,13 @@ + # won't be opening any terminal devices, don't do the ultra-paranoid + # suggestion of doing a second fork after the setsid() call. + os.setsid() ++ ++ # Be sure to close any open std{in,out,err} ++ devnull = os.open('/dev/null', 0) ++ os.dup2(devnull, 0) ++ os.dup2(devnull, 1) ++ os.dup2(devnull, 2) ++ + # Instead of cd'ing to root, cd to the Mailman installation home + os.chdir(mm_cfg.PREFIX) + # Set our file mode creation umask +Index: bin/newlist +--- bin/newlist.orig 2008-06-30 18:29:46 +0200 ++++ bin/newlist 2008-07-01 20:48:10 +0200 +@@ -87,6 +87,9 @@ + defined in your Defaults.py file or overridden by settings in mm_cfg.py). + + Note that listnames are forced to lowercase. ++ ++The list admin address need to be a fully-qualified address, like ++owner@example.com, not just owner. + """ + + import sys +@@ -94,6 +97,7 @@ + import getpass + import getopt + import sha ++import grp + + import paths + from Mailman import mm_cfg +@@ -122,6 +126,9 @@ + + + def main(): ++ gid = grp.getgrnam(mm_cfg.MAILMAN_GROUP)[2] ++ if os.getgid() != mm_cfg.MAILMAN_GROUP: ++ os.setgid(gid) + try: + opts, args = getopt.getopt(sys.argv[1:], 'hql:u:e:', + ['help', 'quiet', 'language=', +@@ -203,7 +210,7 @@ + except Errors.BadListNameError, s: + usage(1, _('Illegal list name: %(s)s')) + except Errors.EmailAddressError, s: +- usage(1, _('Bad owner email address: %(s)s')) ++ usage(1, _('Bad owner email address: %(s)s. Owner addresses need to be fully-qualified names, like "owner@example.com", not just "owner".')) + except Errors.MMListAlreadyExistsError: + usage(1, _('List already exists: %(listname)s')) + +Index: bin/update +--- bin/update.orig 2008-06-30 18:29:46 +0200 ++++ bin/update 2008-07-01 20:48:10 +0200 +@@ -552,9 +552,11 @@ + file20 = os.path.join(mm_cfg.DATA_DIR, 'pending_subscriptions.db') + file214 = os.path.join(mm_cfg.DATA_DIR, 'pending.pck') + db = None ++ ver = None + # Try to load the Mailman 2.0 file + try: + fp = open(file20) ++ ver = "20" + except IOError, e: + if e.errno <> errno.ENOENT: raise + else: +@@ -566,6 +568,7 @@ + # Try to load the Mailman 2.1.x where x < 5, file + try: + fp = open(file214) ++ ver = "214" + except IOError, e: + if e.errno <> errno.ENOENT: raise + else: +@@ -599,8 +602,12 @@ + # data[0] is the address being unsubscribed + addrops_by_address.setdefault(data[0], []).append((key, val)) + elif op == Pending.SUBSCRIPTION: +- # data[0] is a UserDesc object +- addr = data[0].address ++ if ver == "20": ++ # data is tuple (emailaddr, password, digest) ++ addr = data[0] ++ else: ++ # data[0] is a UserDesc object ++ addr = data[0].address + subs_by_address.setdefault(addr, []).append((key, val)) + elif op == Pending.RE_ENABLE: + # data[0] is the mailing list's internal name +Index: scripts/driver +--- scripts/driver.orig 2008-06-30 18:29:46 +0200 ++++ scripts/driver 2008-07-01 20:48:10 +0200 +@@ -95,6 +95,15 @@ + module = getattr(pkg, scriptname) + main = getattr(module, 'main') + try: ++ import os ++ request_method = os.environ.get('REQUEST_METHOD') ++ if not request_method in ['GET', 'POST', 'HEAD']: ++ print "Status: 405 Method not allowed" ++ print "Content-type: text/plain" ++ print ++ print "The method is not allowed" ++ sys.exit() ++ + try: + sys.stderr = logger + sys.stdout = tempstdout