1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/mailman/mailman.patch Wed Dec 17 15:02:08 2008 +0100 1.3 @@ -0,0 +1,247 @@ 1.4 +Index: Mailman/Archiver/pipermail.py 1.5 +--- Mailman/Archiver/pipermail.py.orig 2008-06-30 18:29:46 +0200 1.6 ++++ Mailman/Archiver/pipermail.py 2008-07-01 20:48:10 +0200 1.7 +@@ -122,9 +122,9 @@ 1.8 + parentID = article.parentID 1.9 + if parentID is not None and self.articleIndex.has_key(parentID): 1.10 + parent = self.getArticle(archive, parentID) 1.11 +- myThreadKey = parent.threadKey + article.date + '-' 1.12 ++ myThreadKey = parent.threadKey + article.date + '/' + article.msgid + '-' 1.13 + else: 1.14 +- myThreadKey = article.date + '-' 1.15 ++ myThreadKey = article.date + '/' + article.msgid + '-' 1.16 + article.threadKey = myThreadKey 1.17 + key = myThreadKey, article.msgid 1.18 + self.setThreadKey(archive, key, article.msgid) 1.19 +@@ -418,7 +418,7 @@ 1.20 + else: 1.21 + parent = self.database.getArticle(self.archive, 1.22 + article.parentID) 1.23 +- article.threadKey = parent.threadKey+article.date+'-' 1.24 ++ article.threadKey = parent.threadKey + article.date + '/' + article.msgid + '-' 1.25 + self.database.setThreadKey(self.archive, 1.26 + (article.threadKey, article.msgid), 1.27 + msgid) 1.28 +@@ -632,9 +632,9 @@ 1.29 + article.parentID = parentID = self.get_parent_info(arch, article) 1.30 + if parentID: 1.31 + parent = self.database.getArticle(arch, parentID) 1.32 +- article.threadKey = parent.threadKey + article.date + '-' 1.33 ++ article.threadKey = parent.threadKey + article.date + '/' + article.msgid + '-' 1.34 + else: 1.35 +- article.threadKey = article.date + '-' 1.36 ++ article.threadKey = article.date + '/' + article.msgid + '-' 1.37 + key = article.threadKey, article.msgid 1.38 + 1.39 + self.database.setThreadKey(arch, key, article.msgid) 1.40 +Index: Mailman/Commands/cmd_subscribe.py 1.41 +--- Mailman/Commands/cmd_subscribe.py.orig 2008-06-30 18:29:46 +0200 1.42 ++++ Mailman/Commands/cmd_subscribe.py 2008-07-01 20:48:10 +0200 1.43 +@@ -84,6 +84,7 @@ 1.44 + if password is None: 1.45 + password = Utils.MakeRandomPassword() 1.46 + if address is None: 1.47 ++ h = None 1.48 + realname, address = parseaddr(res.msg['from']) 1.49 + if not address: 1.50 + # Fall back to the sender address 1.51 +Index: Mailman/HTMLFormatter.py 1.52 +--- Mailman/HTMLFormatter.py.orig 2008-06-30 18:29:46 +0200 1.53 ++++ Mailman/HTMLFormatter.py 2008-07-01 20:48:10 +0200 1.54 +@@ -44,7 +44,7 @@ 1.55 + realname = self.real_name 1.56 + hostname = self.host_name 1.57 + listinfo_link = Link(self.GetScriptURL('listinfo'), realname).Format() 1.58 +- owner_link = Link('mailto:' + self.GetOwnerEmail(), ownertext).Format() 1.59 ++ owner_link = Link('mailto:' + self.GetOwnerEmail(), realname + '-owner').Format() 1.60 + innertext = _('%(listinfo_link)s list run by %(owner_link)s') 1.61 + return Container( 1.62 + '<hr>', 1.63 +Index: Mailman/Handlers/Decorate.py 1.64 +--- Mailman/Handlers/Decorate.py.orig 2008-06-30 18:29:46 +0200 1.65 ++++ Mailman/Handlers/Decorate.py 2008-07-01 20:48:10 +0200 1.66 +@@ -197,6 +197,7 @@ 1.67 + del msg['content-transfer-encoding'] 1.68 + del msg['content-disposition'] 1.69 + msg['Content-Type'] = 'multipart/mixed' 1.70 ++ msg['Mime-version'] = '1.0' 1.71 + 1.72 + 1.73 + 1.74 +Index: Mailman/Handlers/Scrubber.py 1.75 +--- Mailman/Handlers/Scrubber.py.orig 2008-06-30 18:29:46 +0200 1.76 ++++ Mailman/Handlers/Scrubber.py 2008-07-01 20:48:10 +0200 1.77 +@@ -385,6 +385,8 @@ 1.78 + t = unicode(t, 'ascii', 'replace') 1.79 + try: 1.80 + # Should use HTML-Escape, or try generalizing to UTF-8 1.81 ++ if len(charset) == 0: 1.82 ++ charset = 'us-ascii' 1.83 + t = t.encode(charset, 'replace') 1.84 + except (UnicodeError, LookupError, ValueError, 1.85 + AssertionError): 1.86 +Index: Mailman/Queue/OutgoingRunner.py 1.87 +--- Mailman/Queue/OutgoingRunner.py.orig 2008-06-30 18:29:46 +0200 1.88 ++++ Mailman/Queue/OutgoingRunner.py 2008-07-01 20:48:10 +0200 1.89 +@@ -89,6 +89,7 @@ 1.90 + syslog('error', 'Cannot connect to SMTP server %s on port %s', 1.91 + mm_cfg.SMTPHOST, port) 1.92 + self.__logged = True 1.93 ++ self._snooze(0) 1.94 + return True 1.95 + except Errors.SomeRecipientsFailed, e: 1.96 + # Handle local rejects of probe messages differently. 1.97 +Index: Mailman/htmlformat.py 1.98 +--- Mailman/htmlformat.py.orig 2008-06-30 18:29:46 +0200 1.99 ++++ Mailman/htmlformat.py 2008-07-01 20:48:10 +0200 1.100 +@@ -300,7 +300,8 @@ 1.101 + charset = 'us-ascii' 1.102 + if self.language: 1.103 + charset = Utils.GetCharSet(self.language) 1.104 +- output = ['Content-Type: text/html; charset=%s\n' % charset] 1.105 ++ output = ['Content-Type: text/html; charset=%s' % charset] 1.106 ++ output.append('Cache-control: no-cache\n') 1.107 + if not self.suppress_head: 1.108 + kws.setdefault('bgcolor', self.bgcolor) 1.109 + tab = ' ' * indent 1.110 +Index: bin/check_perms 1.111 +--- bin/check_perms.orig 2008-06-30 18:29:46 +0200 1.112 ++++ bin/check_perms 2008-07-01 20:48:10 +0200 1.113 +@@ -82,7 +82,7 @@ 1.114 + return os.stat(path)[ST_MODE] 1.115 + 1.116 + def statgidmode(path): 1.117 +- stat = os.stat(path) 1.118 ++ stat = os.lstat(path) 1.119 + return stat[ST_MODE], stat[ST_GID] 1.120 + 1.121 + seen = {} 1.122 +Index: bin/config_list 1.123 +--- bin/config_list.orig 2008-06-30 18:29:46 +0200 1.124 ++++ bin/config_list 2008-07-01 20:48:10 +0200 1.125 +@@ -307,6 +307,11 @@ 1.126 + in mm_cfg.OPTINFO.items() 1.127 + if validval & bitval] 1.128 + gui._setValue(mlist, k, validval, fakedoc) 1.129 ++ # Ugly hack, but seems to be needed since 1.130 ++ # new_member_options isn't really a number in gui. 1.131 ++ # -- tfheen, 2003-12-06 1.132 ++ if k == "new_member_options": 1.133 ++ mlist.new_member_options = validval 1.134 + # BAW: when to do gui._postValidate()??? 1.135 + finally: 1.136 + if savelist and not checkonly: 1.137 +Index: bin/mailmanctl 1.138 +--- bin/mailmanctl.orig 2008-06-30 18:29:46 +0200 1.139 ++++ bin/mailmanctl 2008-07-01 20:48:10 +0200 1.140 +@@ -417,6 +417,13 @@ 1.141 + # won't be opening any terminal devices, don't do the ultra-paranoid 1.142 + # suggestion of doing a second fork after the setsid() call. 1.143 + os.setsid() 1.144 ++ 1.145 ++ # Be sure to close any open std{in,out,err} 1.146 ++ devnull = os.open('/dev/null', 0) 1.147 ++ os.dup2(devnull, 0) 1.148 ++ os.dup2(devnull, 1) 1.149 ++ os.dup2(devnull, 2) 1.150 ++ 1.151 + # Instead of cd'ing to root, cd to the Mailman installation home 1.152 + os.chdir(mm_cfg.PREFIX) 1.153 + # Set our file mode creation umask 1.154 +Index: bin/newlist 1.155 +--- bin/newlist.orig 2008-06-30 18:29:46 +0200 1.156 ++++ bin/newlist 2008-07-01 20:48:10 +0200 1.157 +@@ -87,6 +87,9 @@ 1.158 + defined in your Defaults.py file or overridden by settings in mm_cfg.py). 1.159 + 1.160 + Note that listnames are forced to lowercase. 1.161 ++ 1.162 ++The list admin address need to be a fully-qualified address, like 1.163 ++owner@example.com, not just owner. 1.164 + """ 1.165 + 1.166 + import sys 1.167 +@@ -94,6 +97,7 @@ 1.168 + import getpass 1.169 + import getopt 1.170 + import sha 1.171 ++import grp 1.172 + 1.173 + import paths 1.174 + from Mailman import mm_cfg 1.175 +@@ -122,6 +126,9 @@ 1.176 + 1.177 + 1.178 + def main(): 1.179 ++ gid = grp.getgrnam(mm_cfg.MAILMAN_GROUP)[2] 1.180 ++ if os.getgid() != mm_cfg.MAILMAN_GROUP: 1.181 ++ os.setgid(gid) 1.182 + try: 1.183 + opts, args = getopt.getopt(sys.argv[1:], 'hql:u:e:', 1.184 + ['help', 'quiet', 'language=', 1.185 +@@ -203,7 +210,7 @@ 1.186 + except Errors.BadListNameError, s: 1.187 + usage(1, _('Illegal list name: %(s)s')) 1.188 + except Errors.EmailAddressError, s: 1.189 +- usage(1, _('Bad owner email address: %(s)s')) 1.190 ++ usage(1, _('Bad owner email address: %(s)s. Owner addresses need to be fully-qualified names, like "owner@example.com", not just "owner".')) 1.191 + except Errors.MMListAlreadyExistsError: 1.192 + usage(1, _('List already exists: %(listname)s')) 1.193 + 1.194 +Index: bin/update 1.195 +--- bin/update.orig 2008-06-30 18:29:46 +0200 1.196 ++++ bin/update 2008-07-01 20:48:10 +0200 1.197 +@@ -552,9 +552,11 @@ 1.198 + file20 = os.path.join(mm_cfg.DATA_DIR, 'pending_subscriptions.db') 1.199 + file214 = os.path.join(mm_cfg.DATA_DIR, 'pending.pck') 1.200 + db = None 1.201 ++ ver = None 1.202 + # Try to load the Mailman 2.0 file 1.203 + try: 1.204 + fp = open(file20) 1.205 ++ ver = "20" 1.206 + except IOError, e: 1.207 + if e.errno <> errno.ENOENT: raise 1.208 + else: 1.209 +@@ -566,6 +568,7 @@ 1.210 + # Try to load the Mailman 2.1.x where x < 5, file 1.211 + try: 1.212 + fp = open(file214) 1.213 ++ ver = "214" 1.214 + except IOError, e: 1.215 + if e.errno <> errno.ENOENT: raise 1.216 + else: 1.217 +@@ -599,8 +602,12 @@ 1.218 + # data[0] is the address being unsubscribed 1.219 + addrops_by_address.setdefault(data[0], []).append((key, val)) 1.220 + elif op == Pending.SUBSCRIPTION: 1.221 +- # data[0] is a UserDesc object 1.222 +- addr = data[0].address 1.223 ++ if ver == "20": 1.224 ++ # data is tuple (emailaddr, password, digest) 1.225 ++ addr = data[0] 1.226 ++ else: 1.227 ++ # data[0] is a UserDesc object 1.228 ++ addr = data[0].address 1.229 + subs_by_address.setdefault(addr, []).append((key, val)) 1.230 + elif op == Pending.RE_ENABLE: 1.231 + # data[0] is the mailing list's internal name 1.232 +Index: scripts/driver 1.233 +--- scripts/driver.orig 2008-06-30 18:29:46 +0200 1.234 ++++ scripts/driver 2008-07-01 20:48:10 +0200 1.235 +@@ -95,6 +95,15 @@ 1.236 + module = getattr(pkg, scriptname) 1.237 + main = getattr(module, 'main') 1.238 + try: 1.239 ++ import os 1.240 ++ request_method = os.environ.get('REQUEST_METHOD') 1.241 ++ if not request_method in ['GET', 'POST', 'HEAD']: 1.242 ++ print "Status: 405 Method not allowed" 1.243 ++ print "Content-type: text/plain" 1.244 ++ print 1.245 ++ print "The method is not allowed" 1.246 ++ sys.exit() 1.247 ++ 1.248 + try: 1.249 + sys.stderr = logger 1.250 + sys.stdout = tempstdout