? gen_patch ? patch ? patch.2.1.1 ? gen_patch.2.1.1 ? Mailman/Archiver/HyperArch.py.diff ? Mailman/Handlers/Scrubber.py.diff ? Mailman/Handlers/AvoidDuplicates.py.diff ? misc/email-2.4.3 ? misc/JapaneseCodecs-1.4.9 ? misc/KoreanCodecs-2.0.5 Index: Mailman/MailList.py =================================================================== RCS file: /cvsroot/mailman/mailman/Mailman/MailList.py,v retrieving revision 2.100.2.1 diff -u -r2.100.2.1 MailList.py --- Mailman/MailList.py 2 Jan 2003 05:28:48 -0000 2.100.2.1 +++ Mailman/MailList.py 13 Feb 2003 11:02:13 -0000 @@ -895,7 +895,8 @@ text = Utils.maketext( "adminsubscribeack.txt", {"listname" : self.real_name, - "member" : formataddr((name, email)), + "member" : email, + # "member" : formataddr((name, email)), }, mlist=self) msg = Message.OwnerNotification(self, subject, text) msg.send(self) Index: Mailman/Utils.py =================================================================== RCS file: /cvsroot/mailman/mailman/Mailman/Utils.py,v retrieving revision 2.45.2.1 diff -u -r2.45.2.1 Utils.py --- Mailman/Utils.py 8 Feb 2003 07:13:49 -0000 2.45.2.1 +++ Mailman/Utils.py 13 Feb 2003 11:02:13 -0000 @@ -35,6 +35,7 @@ import cgi import htmlentitydefs import email.Iterators +import email.Header from types import UnicodeType from string import whitespace, digits try: @@ -51,6 +52,7 @@ from Mailman.SafeDict import SafeDict EMPTYSTRING = '' +UEMPTYSTRING = u'' NL = '\n' DOT = '.' IDENTCHARS = ascii_letters + digits + '_' @@ -776,3 +778,14 @@ a.append(c) # Join characters together and coerce to byte string return str(EMPTYSTRING.join(a)) + +def oneline(s, cset): + # Decode header string in one line and convert into specified charset + try: + h = email.Header.make_header(email.Header.decode_header(s)) + ustr = h.__unicode__() + oneline = UEMPTYSTRING.join(ustr.splitlines()) + return oneline.encode(cset, 'replace') + except (LookupError, UnicodeError): + # possibly charset problem. return with undecoded string in one line. + return EMPTYSTRING.join(s.splitlines()) Index: Mailman/Archiver/HyperArch.py =================================================================== RCS file: /cvsroot/mailman/mailman/Mailman/Archiver/HyperArch.py,v retrieving revision 2.37.2.3 diff -u -r2.37.2.3 HyperArch.py --- Mailman/Archiver/HyperArch.py 8 Feb 2003 07:13:49 -0000 2.37.2.3 +++ Mailman/Archiver/HyperArch.py 13 Feb 2003 11:02:13 -0000 @@ -257,7 +257,7 @@ self.ctype = ctype.lower() self.cenc = cenc.lower() self.decoded = {} - charset = message.get_param('charset') + charset = message.get_param('charset', 'us-ascii') if isinstance(charset, types.TupleType): # An RFC 2231 charset charset = unicode(charset[2], charset[0]) @@ -1091,6 +1091,9 @@ # 1. use lines directly, rather than source and dest # 2. make it clearer # 3. make it faster + atmark = _(' at ') + if len(lines) > 0 and type(lines[0]) == types.UnicodeType: + atmark = unicode(atmark, Utils.GetCharSet(self.lang), 'replace') source = lines[:] dest = lines last_line_was_quoted = 0 @@ -1131,7 +1134,7 @@ text = jr.group(1) length = len(text) if mm_cfg.ARCHIVER_OBSCURES_EMAILADDRS: - text = re.sub('@', _(' at '), text) + text = re.sub('@', atmark, text) URL = self.maillist.GetScriptURL( 'listinfo', absolute=1) else: Index: Mailman/Cgi/admindb.py =================================================================== RCS file: /cvsroot/mailman/mailman/Mailman/Cgi/admindb.py,v retrieving revision 2.45.2.1 diff -u -r2.45.2.1 admindb.py --- Mailman/Cgi/admindb.py 8 Feb 2003 07:13:49 -0000 2.45.2.1 +++ Mailman/Cgi/admindb.py 13 Feb 2003 11:02:13 -0000 @@ -471,9 +471,10 @@ mlist.HandleRequest(id, mm_cfg.DISCARD) continue t = Table(border=0) + lcset = Utils.GetCharSet(mlist.preferred_language) t.AddRow([Link(admindburl + '?msgid=%d' % id, '[%d]' % counter), Bold(_('Subject:')), - Utils.websafe(subject) + Utils.websafe(Utils.oneline(subject, lcset)) ]) t.AddRow([' ', Bold(_('Size:')), str(size) + _(' bytes')]) if reason: @@ -589,6 +590,13 @@ body = EMPTYSTRING.join(lines)[:mm_cfg.ADMINDB_PAGE_TEXT_LIMIT] else: body = EMPTYSTRING.join(lines) + # i18n: Get message charset + mcset = msg.get_param('charset', 'us-ascii').lower() + lcset = Utils.GetCharSet(mlist.preferred_language) + try: + body = unicode(body, mcset).encode(lcset) + except: + pass hdrtxt = NL.join(['%s: %s' % (k, v) for k, v in msg.items()]) hdrtxt = Utils.websafe(hdrtxt) # Okay, we've reconstituted the message just fine. Now for the fun part! @@ -596,7 +604,8 @@ t.AddRow([Bold(_('From:')), sender]) row, col = t.GetCurrentRowIndex(), t.GetCurrentCellIndex() t.AddCellInfo(row, col-1, align='right') - t.AddRow([Bold(_('Subject:')), Utils.websafe(subject)]) + t.AddRow([Bold(_('Subject:')), + Utils.websafe(Utils.oneline(subject, lcset))]) t.AddCellInfo(row+1, col-1, align='right') t.AddRow([Bold(_('Reason:')), _(reason)]) t.AddCellInfo(row+2, col-1, align='right') Index: Mailman/Handlers/AvoidDuplicates.py =================================================================== RCS file: /cvsroot/mailman/mailman/Mailman/Handlers/AvoidDuplicates.py,v retrieving revision 2.1 diff -u -r2.1 AvoidDuplicates.py --- Mailman/Handlers/AvoidDuplicates.py 17 Sep 2002 22:01:30 -0000 2.1 +++ Mailman/Handlers/AvoidDuplicates.py 13 Feb 2003 11:02:14 -0000 @@ -26,6 +26,8 @@ from email.Utils import getaddresses, formataddr +COMMASPACE = ', ' + def process(mlist, msg, msgdata): @@ -84,5 +86,4 @@ # Set the new list of recipients msgdata['recips'] = newrecips del msg['cc'] - for item in ccaddrs.values(): - msg['cc'] = formataddr(item) + msg['Cc'] = COMMASPACE.join([formataddr(item) for item in ccaddrs.values()]) Index: Mailman/Handlers/CookHeaders.py =================================================================== RCS file: /cvsroot/mailman/mailman/Mailman/Handlers/CookHeaders.py,v retrieving revision 2.33.2.1 diff -u -r2.33.2.1 CookHeaders.py --- Mailman/Handlers/CookHeaders.py 8 Feb 2003 07:13:50 -0000 2.33.2.1 +++ Mailman/Handlers/CookHeaders.py 13 Feb 2003 11:02:14 -0000 @@ -15,6 +15,7 @@ # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. """Cook a message's Subject header. + (sequence version) """ from __future__ import nested_scopes @@ -218,7 +219,9 @@ # Add the subject prefix unless the message is a digest or is being fast # tracked (e.g. internally crafted, delivered to a single user such as the # list admin). - prefix = mlist.subject_prefix + prefix = mlist.subject_prefix.strip() + if not prefix: + return subject = msg.get('subject', '') # Try to figure out what the continuation_ws is for the header if isinstance(subject, Header): @@ -233,31 +236,53 @@ # each chunk for the prefix. BAW: Note that if the prefix contains spaces # and each word of the prefix is encoded in a different chunk in the # header, we won't find it. I think in practice that's unlikely though. - headerbits = decode_header(subject) - if prefix and subject: - pattern = re.escape(prefix.strip()) - for decodedsubj, charset in headerbits: - if re.search(pattern, decodedsubj, re.IGNORECASE): - # The subject's already got the prefix, so don't change it - return - del msg['subject'] + # TK: We assume the subject is mono-lingual in sequence version + # and search first non-None charset + cmatch = re.search(r'=\?([^\?]+)\?[bq]\?[^\?]+\?=', subject, re.I) + if cmatch: + cset = cmatch.group(1).lower() + else: + cset = 'us-ascii' + headerstring = Utils.oneline(subject, cset) + # Note: searching prefix in subject is REMOVED. (seq version) if not subject: subject = _('(no subject)') + else: + subject = headerstring + # If the subject_prefix contains '%d', it is replaced with the + # mailing list sequential number. Also, if the prefix is closed with + # [],(), or {}, the prefix in the responding post subject will be cared. + # sequential number format allows '%05d' like pattern. + p = re.compile('%\d*d') + if p.search(prefix,1): + # prefix have number, so we should search prefix w/number + # in subject. + prefix_pattern = p.sub(r'\s*\d+\s*', prefix) + else: + prefix_pattern = prefix + prefix_pattern = re.sub('([\[\(\{])', '\\\\\g<1>', prefix_pattern) + subject = re.sub(prefix_pattern, '', subject) + subject = re.compile('(RE:\s*)+', re.I).sub('Re: ', subject, 1) + # and substitute %d in prefix with post_id + try: + prefix = prefix % mlist.post_id + except: + pass + # Note that trailing space was stripped in seq version and should be + # added if no mime encoded (TK) + if cset == 'us-ascii': + prefix += ' ' # Get the header as a Header instance, with proper unicode conversion h = uheader(mlist, prefix, 'Subject', continuation_ws=ws) - for s, c in headerbits: - # Once again, convert the string to unicode. - if c is None: - c = Charset('iso-8859-1') - if not isinstance(c, Charset): - c = Charset(c) - if not _isunicode(s): - codec = c.input_codec or 'ascii' - try: - s = unicode(s, codec, 'replace') - except LookupError: - # Unknown codec, is this default reasonable? - s = unicode(s, Utils.GetCharSet(mlist.preferred_language), - 'replace') - h.append(s, c) + # in seq version, subject header is already concatnated + if not _isunicode(subject): + try: + subject = unicode(subject, cset, 'replace') + except (LookupError, TypeError): + # unknown codec + cset = Utils.GetCharSet(mlist.preferred_language) + subject = unicode(subject, cset, 'replace') + subject = subject.encode(cset,'replace') + h.append(subject, cset) + del msg['subject'] msg['Subject'] = h Index: Mailman/Handlers/Decorate.py =================================================================== RCS file: /cvsroot/mailman/mailman/Mailman/Handlers/Decorate.py,v retrieving revision 2.21.2.2 diff -u -r2.21.2.2 Decorate.py --- Mailman/Handlers/Decorate.py 7 Jan 2003 14:18:39 -0000 2.21.2.2 +++ Mailman/Handlers/Decorate.py 13 Feb 2003 11:02:14 -0000 @@ -77,18 +77,31 @@ # BAW: If the charsets don't match, should we add the header and footer by # MIME multipart chroming the message? wrap = 1 - if not msg.is_multipart() and msgtype == 'text/plain' and \ - msg.get('content-transfer-encoding', '').lower() <> 'base64' and \ - (lcset == 'us-ascii' or mcset == lcset): - oldpayload = msg.get_payload() - frontsep = endsep = '' - if header and not header.endswith('\n'): - frontsep = '\n' - if footer and not oldpayload.endswith('\n'): - endsep = '\n' - payload = header + frontsep + oldpayload + endsep + footer - msg.set_payload(payload) - wrap = 0 + if not msg.is_multipart() and msgtype == 'text/plain': + # TK: Try to keep the message plain by converting the header/ + # footer/oldpayload into unicode and encode with mcset/lcset. + # Try to decode qp/base64 also. + uheader = unicode(header, lcset) + ufooter = unicode(footer, lcset) + try: + oldpayload = unicode(msg.get_payload(decode=1), mcset) + frontsep = endsep = u'' + if header and not header.endswith('\n'): + frontsep = u'\n' + if footer and not oldpayload.endswith('\n'): + endsep = u'\n' + payload = uheader + frontsep + oldpayload + endsep + ufooter + if lcset == 'us-ascii': + newcset = mcset + else: + newcset = lcset + payload = payload.encode(newcset) + del msg['content-transfer-encoding'] + del msg['content-type'] + msg.set_payload(payload, newcset) + wrap = 0 + except: + pass elif msg.get_type() == 'multipart/mixed': # The next easiest thing to do is just prepend the header and append # the footer as additional subparts Index: Mailman/Handlers/Hold.py =================================================================== RCS file: /cvsroot/mailman/mailman/Mailman/Handlers/Hold.py,v retrieving revision 2.33 diff -u -r2.33 Hold.py --- Mailman/Handlers/Hold.py 11 Dec 2002 12:41:56 -0000 2.33 +++ Mailman/Handlers/Hold.py 13 Feb 2003 11:02:14 -0000 @@ -197,6 +197,12 @@ exc = exc() listname = mlist.real_name sender = msgdata.get('sender', msg.get_sender()) + usersubject = msg.get('subject') + charset = Utils.GetCharSet(mlist.preferred_language) + if usersubject: + usersubject = Utils.oneline(usersubject, charset) + else: + usersubject = _('(no subject)') owneraddr = mlist.GetOwnerEmail() adminaddr = mlist.GetBouncesEmail() requestaddr = mlist.GetRequestEmail() @@ -211,7 +217,7 @@ 'hostname' : mlist.host_name, 'reason' : _(reason), 'sender' : sender, - 'subject' : msg.get('subject', _('(no subject)')), + 'subject' : usersubject, 'admindb_url': mlist.GetScriptURL('admindb', absolute=1), } # We may want to send a notification to the original sender too @@ -246,7 +252,6 @@ lang = mlist.preferred_language charset = Utils.GetCharSet(lang) # We need to regenerate or re-translate a few values in d - usersubject = msg.get('subject', _('(no subject)')) d['reason'] = _(reason) d['subject'] = usersubject # craft the admin notification message and deliver it Index: Mailman/Handlers/Scrubber.py =================================================================== RCS file: /cvsroot/mailman/mailman/Mailman/Handlers/Scrubber.py,v retrieving revision 2.18.2.3 diff -u -r2.18.2.3 Scrubber.py --- Mailman/Handlers/Scrubber.py 8 Feb 2003 07:13:50 -0000 2.18.2.3 +++ Mailman/Handlers/Scrubber.py 13 Feb 2003 11:02:14 -0000 @@ -32,6 +32,7 @@ from email.Utils import parsedate from email.Parser import HeaderParser from email.Generator import Generator +from email import message_from_string from Mailman import mm_cfg from Mailman import Utils @@ -270,6 +271,9 @@ Url : %(url)s """), lcset) outer = 0 + # TK: We (Japanese) need to stringify and re-generate the message + # instance because multiple charsets are used. + msg = message_from_string(str(msg)) # We still have to sanitize multipart messages to flat text because # Pipermail can't handle messages with list payloads. This is a kludge; # def (n) clever hack ;). @@ -286,8 +290,11 @@ # BAW: Martin's original patch suggested we might want to try # generalizing to utf-8, and that's probably a good idea (eventually). text = [] - for part in msg.get_payload(): + for part in msg.walk(): # All parts should be scrubbed to text/plain by now. + # ... or embedded multipart message ... so, walk don't get + if part.get_content_maintype() == 'multipart': + continue partctype = part.get_content_type() if partctype <> 'text/plain': text.append(_('Skipped content of type %(partctype)s')) Index: cron/checkdbs =================================================================== RCS file: /cvsroot/mailman/mailman/cron/checkdbs,v retrieving revision 2.17 diff -u -r2.17 checkdbs --- cron/checkdbs 28 Oct 2002 03:43:42 -0000 2.17 +++ cron/checkdbs 13 Feb 2003 11:02:14 -0000 @@ -92,6 +92,7 @@ def pending_requests(mlist): + lcset = Utils.GetCharSet(mlist.preferred_language) # Must return a byte string pending = [] first = 1 @@ -101,6 +102,8 @@ first = 0 when, addr, fullname, passwd, digest, lang = mlist.GetRecord(id) if fullname: + if _isunicode(fullname): + fullname = fullname.encode(lcset, 'replace') fullname = ' (%s)' % fullname pending.append(' %s%s %s' % (addr, fullname, time.ctime(when))) first = 1 @@ -110,6 +113,8 @@ first = 0 info = mlist.GetRecord(id) when, sender, subject, reason, text, msgdata = mlist.GetRecord(id) + subject = Utils.oneline(subject, lcset) + reason = _(reason) date = time.ctime(when) pending.append(_("""\ From: %(sender)s on %(date)s