mailman/mailman.patch

changeset 7
5443cb9b550a
child 371
3d7d8c68b2fc
     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

mercurial