Netscape fix

Top Page
Attachments:
Message as email
+ (text/plain)
Delete this message
Reply to this message
Author: ArtWagnerawagner@uswest.net
Date:  
Subject: Netscape fix
This is a multi-part message in MIME format.
--------------5924F90C7260D3B6966054A5
Content-Type: text/plain; charset=us-ascii
Content-Transfer-Encoding: 7bit

"der.hans" wrote:
>
> moin, moin,
>
> can we get this up on the web site, so we can point people at it?
>
> Maybe under a FAQ. We could include questions and answers about joining
> the mailing list and meetings and why everyone thinks Cindy has the PLUG
> website URL tatooed on her butt :).
>
> ciao,
>
> der.hans
> --
> # home.pages.de/~lufthans/ www.Opnix.com
> # Motorraeder toeten nicht. Motorraeder werden getoetet.
>
> _______________________________________________
> Plug-discuss mailing list -
> http://lists.PLUG.phoenix.az.us/mailman/listinfo/plug-discuss


I would hope we can fix the "Mail Hanging" problem with the
attached
patched version of "Message.py" from;
"mailman-1.1/Mailman/Messages.py"
Please note my added comments at line 35.
Arthur Wagner
--------------5924F90C7260D3B6966054A5
Content-Type: text/plain; charset=us-ascii;
name="Message.py"
Content-Transfer-Encoding: 7bit
Content-Disposition: inline;
filename="Message.py"

# Message.py from Mailman-1.1
# Copyright (C) 1998 by the Free Software Foundation, Inc.
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.


"""Embody incoming and outgoing messages as objects."""


import sys
import string
import time

# Python 1.5's version of rfc822.py is buggy and lacks features we
# depend on -- so we always use the up-to-date version distributed
# with Mailman.
from Mailman.pythonlib import rfc822


# Utility functions 2 of these classes use:
def AddBackNewline(str):
    return str + '\n'


def RemoveNewline(str):
    return str[:-1]

    

# XXX klm - use the standard lib StringIO module instead of FakeFile.
# If we're trying to create a message object from text, we need to pass
# a file object to rfc822.Message to get it to do its magic. Well,
# to avoid writing text out to a file, and having it read back in,
# here we define a class that will fool rfc822 into thinking it's a
# non-seekable message.
# The only method rfc822.Message ever calls on a non-seekable file is
# readline. It doesn't use the optional arg to readline, either.
# In my subclasses, I use the read() method, and might just use readlines()
# someday.
#
# It might be useful to expand this into a full blown fully functional class.

class FakeFile:
    def __init__(self, text):
    self.lines = map(AddBackNewline, string.split(text, '\n'))
    self.curline = 0
    self.lastline = len(self.lines) - 1
    def readline(self):
    if self.curline > self.lastline:
        return ''
    self.curline = self.curline + 1
    return self.lines[self.curline - 1]
    def read(self):
    startline = self.curline
    self.curline = self.lastline + 1
    return string.join(self.lines[startline:], '')
    def readlines(self):
    startline = self.curline
    self.curline = self.lastline + 1
    return self.lines[startline:]
    def seek(self, pos):
    if pos <> 0:
      raise ValueError, "FakeFiles can only seek to the beginning."
    self.curline = 0

    


# We know the message is gonna come in on stdin or from text for our purposes.
class IncomingMessage(rfc822.Message):
    def __init__(self, text=None):
    if not text:
        rfc822.Message.__init__(self, sys.stdin, 0)
        self.body = self.fp.read()
    else:
        rfc822.Message.__init__(self, FakeFile(text), 0)
        self.body = self.fp.read()
    self.file_count = None


    def readlines(self):
    if self.file_count <> None:
      x = self.file_count
      self.file_count = len(self.file_data)
      return self.file_data[x:]
        return map(RemoveNewline, self.headers) + [''] + \
           string.split(self.body,'\n')


    def readline(self):
    if self.file_count == None:
      self.file_count = 0
      self.file_data = map(RemoveNewline, self.headers) + [''] + \
           string.split(self.body,'\n')
    if self.file_count >= len(self.file_data):
        return ''    
    self.file_count = self.file_count + 1
    return self.file_data[self.file_count-1] + '\n'


# In lines 54 and 57 Reversed "sender" and "from" This fixes the problem
# with Netscape 4.6 through 4.73 postings hanging for Admin. Arthur L. Wagner

    def GetSender(self):
    # Look for a Sender field.
    sender = self.getheader('from')
    if sender:
        realname, mail_address = self.getaddr('from')
    else:
        try:
        realname, mail_address = self.getaddr('sender')
        except:
                real_name = mail_address = None


        # We can't trust that any of the headers really contained an address
        if mail_address and type(mail_address) == type(""):
            return string.lower(mail_address)
        else:
            # The unix from line is all we have left...
            if self.unixfrom:
                return string.lower(string.split(self.unixfrom)[1])


    def GetEnvelopeSender(self):
        #
        # look for unix from line and attain address
        # from it, return None if there is no unix from line
        # this function is used to get the envelope sender
        # when mail is sent to a <listname>-admin address
        # 
        if not self.unixfrom:
            return None
        # XXX assumes no whitespace in address
        parts = string.split(self.unixfrom)
        for part in parts:
            #
            # perform minimal check for the address
            #
            if string.find(part, '@') > -1:
                user, host = string.split(part, '@', 1)
                if not user: 
                    continue
                if string.count(host, ".") < 1: # doesn't look qualified
                    continue
                return part
        return None



    def GetSenderName(self):
    real_name, mail_addr = self.getaddr('from')
    if not real_name:
        return self.GetSender()
    return real_name


    def SetHeader(self, name, value, crush_duplicates=1):
        if crush_duplicates:
            self[name] = value
        else:
            # Only bother with the dict
            self.dict[string.lower(name)] = value


# This is a simplistic class.  It could do multi-line headers etc...
# But it doesn't because I don't need that for this app.
class OutgoingMessage:
    def __init__(self, headers=None, body='', sender=None):
        self.cached_headers = {}
    if headers:
        self.SetHeaders(headers)
    else:
        self.headers = []
    self.body = body
    self.sender = sender


    def readlines(self):
    if self.file_count <> None:
      x = self.file_count
      self.file_count = len(self.file_data)
      return self.file_data[x:]
        return map(RemoveNewline, self.headers) + [''] + \
           string.split(self.body,'\n')


    def readline(self):
    if self.file_count == None:
      self.file_count = 0
      self.file_data = map(RemoveNewline, self.headers) + [''] + \
           string.split(self.body,'\n')
    if self.file_count >= len(self.file_data):
        return ''    
    self.file_count = self.file_count + 1
    return self.file_data[self.file_count-1] + '\n'


    def SetHeaders(self, headers):
        self.headers = map(AddBackNewline, string.split(headers, '\n'))
        self.CacheHeaders()


    def CacheHeaders(self):
        for header in self.headers:
        i = string.find(header, ':')
        self.cached_headers[string.lower(string.strip(header[:i]))
                                ] = header[i+2:]


    def SetHeader(self, header, value, crush_duplicates=1):
    if value[-1] <> '\n':
        value = value + '\n'
    if crush_duplicates:
        # Run through the list and make sure header isn't already there.
        remove_these = []
        for item in self.headers:
        f = string.find(item, ':')
        if string.lower(item[:f]) == string.lower(header):
            remove_these.append(item)
        for item in remove_these:
        self.headers.remove(item)
        del remove_these
    self.headers.append('%s%s: %s' % (string.upper(header[0]),
                      string.lower(header[1:]),
                      value))
    self.cached_headers[string.lower(header)] = value


    def SetBody(self, body):
    self.body = body


    def AppendToBody(self, text):
    self.body = self.body + text


    def SetSender(self, sender, set_from=1):
        self.sender = sender
    if not self.getheader('from') and set_from:
        self.SetHeader('from', sender)


    def GetSender(self):
    return self.sender


# Lower case the name to give it the same UI as IncomingMessage 
# inherits from rfc822
    def getheader(self, str):
    str = string.lower(str)
    if not self.cached_headers.has_key(str):
        return None
    return self.cached_headers[str]


    def __delitem__(self, name):
        if not self.getheader(name):
            # XXX this should raise an exception
            return None
        newheaders = []
        name = string.lower(name)
        nlen = len(name)
        for h in self.headers:
            if (len(h) > (nlen+1)
                and h[nlen] == ":"
                and string.lower(h[:nlen]) == name):
                continue
            newheaders.append(h)
        self.headers = newheaders
        self.CacheHeaders()


    # XXX should have a __setitem__



class NewsMessage(IncomingMessage):
    def __init__(self, mail_msg):
    self.fp = mail_msg.fp
    self.fp.seek(0)
    rfc822.Message.__init__(self, self.fp, 0)
    self.body = self.fp.read()
    self.file_count = None


--------------5924F90C7260D3B6966054A5--