summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Mailman/Archiver/Archiver.py18
-rw-r--r--Mailman/Cgi/Auth.py19
-rw-r--r--Mailman/Cgi/admin.py10
-rw-r--r--Mailman/Cgi/admindb.py2
-rw-r--r--Mailman/Cgi/create.py2
-rw-r--r--Mailman/Cgi/private.py19
-rw-r--r--Mailman/Cgi/wsgi_app.py60
-rw-r--r--Mailman/Defaults.py.in8
-rw-r--r--Mailman/Gui/Privacy.py2
-rw-r--r--Mailman/HTMLFormatter.py16
-rw-r--r--Mailman/MailList.py11
-rw-r--r--Mailman/Queue/HTTPRunner.py27
-rw-r--r--Mailman/SecurityManager.py15
-rw-r--r--Mailman/Utils.py37
-rw-r--r--Mailman/bin/export.py10
-rw-r--r--Mailman/bin/show_config.py197
-rw-r--r--Mailman/configuration.py2
-rw-r--r--Mailman/loginit.py1
-rw-r--r--bin/Makefile.in2
-rw-r--r--misc/Makefile.in22
-rw-r--r--misc/setuptools-0.6c3.tar.gzbin0 -> 238544 bytes
-rw-r--r--misc/wsgiref-0.1.2-py2.4.eggbin0 -> 39890 bytes
22 files changed, 236 insertions, 244 deletions
diff --git a/Mailman/Archiver/Archiver.py b/Mailman/Archiver/Archiver.py
index 8c8dcd238..f76992928 100644
--- a/Mailman/Archiver/Archiver.py
+++ b/Mailman/Archiver/Archiver.py
@@ -117,7 +117,7 @@ class Archiver:
fp.write(Utils.maketext(
'emptyarchive.html',
{'listname': self.real_name,
- 'listinfo': self.GetScriptURL('listinfo', absolute=1),
+ 'listinfo': self.GetScriptURL('listinfo'),
}, mlist=self))
if fp:
fp.close()
@@ -135,19 +135,17 @@ class Archiver:
self.internal_name() + '.mbox')
def GetBaseArchiveURL(self):
- url = self.GetScriptURL('private', absolute=1) + '/'
if self.archive_private:
- return url
+ url = self.GetScriptURL('private')
else:
- hostname = re.match('[^:]*://([^/]*)/.*', url).group(1)\
- or mm_cfg.DEFAULT_URL_HOST
- url = mm_cfg.PUBLIC_ARCHIVE_URL % {
+ web_host = config.domains.get(self.host_name, self.host_name)
+ url = config.PUBLIC_ARCHIVE_URL % {
'listname': self.internal_name(),
- 'hostname': hostname
+ 'hostname': web_host,
}
- if not url.endswith('/'):
- url += '/'
- return url
+ if not url.endswith('/'):
+ url += '/'
+ return url
def __archive_file(self, afn):
"""Open (creating, if necessary) the named archive file."""
diff --git a/Mailman/Cgi/Auth.py b/Mailman/Cgi/Auth.py
index 8c66c4d36..98e9fe49d 100644
--- a/Mailman/Cgi/Auth.py
+++ b/Mailman/Cgi/Auth.py
@@ -1,26 +1,25 @@
-# Copyright (C) 1998,1999,2000,2001,2002 by the Free Software Foundation, Inc.
+# Copyright (C) 1998-2006 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
+# USA.
"""Common routines for logging in and logging out of the list administrator
and list moderator interface.
"""
-from Mailman import mm_cfg
from Mailman import Utils
-from Mailman import Errors
from Mailman.htmlformat import FontAttr
from Mailman.i18n import _
@@ -34,12 +33,14 @@ class NotLoggedInError(Exception):
-def loginpage(mlist, scriptname, msg='', frontpage=None):
+def loginpage(mlist, scriptname, msg='', frontpage=False):
url = mlist.GetScriptURL(scriptname)
if frontpage:
actionurl = url
else:
- actionurl = Utils.GetRequestURI(url)
+ request = Utils.GetRequestURI(url)
+ up = '../' * request.count('/')
+ actionurl = up + request
if msg:
msg = FontAttr(msg, color='#ff0000', size='+1').Format()
if scriptname == 'admindb':
diff --git a/Mailman/Cgi/admin.py b/Mailman/Cgi/admin.py
index 001004fa0..3fbbd4ca4 100644
--- a/Mailman/Cgi/admin.py
+++ b/Mailman/Cgi/admin.py
@@ -99,7 +99,7 @@ def main():
# Is this a log-out request?
if category == 'logout':
print mlist.ZapCookie(mm_cfg.AuthListAdmin)
- Auth.loginpage(mlist, 'admin', frontpage=1)
+ Auth.loginpage(mlist, 'admin', frontpage=True)
return
# Sanity check
@@ -795,9 +795,9 @@ def get_item_gui_description(mlist, category, subcat,
# the details page!
if detailsp:
if subcat:
- varhelp = '/?VARHELP=%s/%s/%s' % (category, subcat, varname)
+ varhelp = '?VARHELP=%s/%s/%s' % (category, subcat, varname)
else:
- varhelp = '/?VARHELP=%s/%s' % (category, varname)
+ varhelp = '?VARHELP=%s/%s' % (category, varname)
if descr == elaboration:
linktext = _('<br>(Edit <b>%(varname)s</b>)')
else:
@@ -817,7 +817,7 @@ def get_item_gui_description(mlist, category, subcat,
def membership_options(mlist, subcat, cgidata, doc, form):
# Show the main stuff
- adminurl = mlist.GetScriptURL('admin', absolute=1)
+ adminurl = mlist.GetScriptURL('admin')
container = Container()
header = Table(width="100%")
# If we're in the list subcategory, show the membership list
@@ -1200,7 +1200,7 @@ def mass_remove(mlist, container):
def password_inputs(mlist):
- adminurl = mlist.GetScriptURL('admin', absolute=1)
+ adminurl = mlist.GetScriptURL('admin')
table = Table(cellspacing=3, cellpadding=4)
table.AddRow([Center(Header(2, _('Change list ownership passwords')))])
table.AddCellInfo(table.GetCurrentRowIndex(), 0, colspan=2,
diff --git a/Mailman/Cgi/admindb.py b/Mailman/Cgi/admindb.py
index 188aabd1c..7d762a172 100644
--- a/Mailman/Cgi/admindb.py
+++ b/Mailman/Cgi/admindb.py
@@ -172,7 +172,7 @@ def main():
doc.AddItem(Header(2, title))
doc.AddItem(_('There are no pending requests.'))
doc.AddItem(' ')
- doc.AddItem(Link(mlist.GetScriptURL('admindb', absolute=1),
+ doc.AddItem(Link(mlist.GetScriptURL('admindb'),
_('Click here to reload this page.')))
doc.AddItem(mlist.GetMailmanFooter())
print doc.Format()
diff --git a/Mailman/Cgi/create.py b/Mailman/Cgi/create.py
index 9a5ab73d8..8db59fdc7 100644
--- a/Mailman/Cgi/create.py
+++ b/Mailman/Cgi/create.py
@@ -154,7 +154,7 @@ def process_request(doc, cgidata):
url_host = Utils.get_request_domain()
email_host = config.get_email_host(url_host)
if not email_host:
- safehostname = Utils.websafe(email_host)
+ safehostname = Utils.websafe(url_host)
request_creation(doc, cgidata,
_('Unknown virtual host: $safehostname'))
return
diff --git a/Mailman/Cgi/private.py b/Mailman/Cgi/private.py
index 97dc66690..c9e69944b 100644
--- a/Mailman/Cgi/private.py
+++ b/Mailman/Cgi/private.py
@@ -23,18 +23,17 @@ import cgi
import logging
import mimetypes
-from Mailman import mm_cfg
-from Mailman import Utils
-from Mailman import MailList
from Mailman import Errors
+from Mailman import MailList
+from Mailman import Utils
from Mailman import i18n
-from Mailman.htmlformat import *
from Mailman.configuration import config
+from Mailman.htmlformat import *
# Set up i18n. Until we know which list is being requested, we use the
# server's default.
_ = i18n._
-i18n.set_language(mm_cfg.DEFAULT_SERVER_LANGUAGE)
+i18n.set_language(config.DEFAULT_SERVER_LANGUAGE)
SLASH = '/'
@@ -61,7 +60,7 @@ def guess_type(url, strict):
def main():
doc = Document()
- doc.set_language(mm_cfg.DEFAULT_SERVER_LANGUAGE)
+ doc.set_language(config.DEFAULT_SERVER_LANGUAGE)
parts = Utils.GetPathPieces()
if not parts:
@@ -127,10 +126,10 @@ def main():
realname = mlist.real_name
message = ''
- if not mlist.WebAuthenticate((mm_cfg.AuthUser,
- mm_cfg.AuthListModerator,
- mm_cfg.AuthListAdmin,
- mm_cfg.AuthSiteAdmin),
+ if not mlist.WebAuthenticate((config.AuthUser,
+ config.AuthListModerator,
+ config.AuthListAdmin,
+ config.AuthSiteAdmin),
password, username):
if cgidata.has_key('submit'):
# This is a re-authorization attempt
diff --git a/Mailman/Cgi/wsgi_app.py b/Mailman/Cgi/wsgi_app.py
index b7acd45fa..8e77352d6 100644
--- a/Mailman/Cgi/wsgi_app.py
+++ b/Mailman/Cgi/wsgi_app.py
@@ -1,5 +1,3 @@
-# -*- python -*-
-
# Copyright (C) 2006 by the Free Software Foundation, Inc.
#
# This program is free software; you can redistribute it and/or
@@ -17,30 +15,36 @@
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
# USA.
+import os
import sys
+
+from cStringIO import StringIO
+from email import message_from_string
+
+from Mailman.configuration import config
+
+# XXX Should this be configurable in Defaults.py?
STEALTH_MODE = False
-# Shoul this be configurable in Defaults.py?
+
+
def websafe(s):
return s
-import os
-import StringIO
-from email import message_from_string
-from Mailman.configuration import config
SCRIPTS = ['admin', 'admindb', 'confirm', 'create',
'edithtml', 'listinfo', 'options', 'private',
'rmlist', 'roster', 'subscribe']
-SLASH = '/'
-NL2 = '\n\n'
-CRLF2 = '\r\n\r\n'
-# WSGI to CGI wrapper. Mostly copied from scripts/driver.
+SLASH = '/'
+NL2 = '\n\n'
+CRLF2 = '\r\n\r\n'
-def mailman_app(environ, start_response):
- """wrapper to *.py cgi commands"""
+
+# WSGI to CGI wrapper. Mostly copied from scripts/driver.
+def mailman_app(environ, start_response):
+ """Wrapper to *.py CGI commands"""
global STEALTH_MODE, websafe
try:
try:
@@ -65,7 +69,7 @@ def mailman_app(environ, start_response):
environ['PATH_INFO'] = SLASH + SLASH.join(paths[2:])
else:
environ['PATH_INFO'] = ''
- # reverse proxy environment.
+ # Reverse proxy environment.
if environ.has_key('HTTP_X_FORWARDED_HOST'):
environ['HTTP_HOST'] = environ['HTTP_X_FORWARDED_HOST']
if environ.has_key('HTTP_X_FORWARDED_FOR'):
@@ -75,14 +79,14 @@ def mailman_app(environ, start_response):
os.environ['HTTP_COOKIE'] = ''
for k, v in environ.items():
os.environ[k] = str(v)
- # Prepare for redirection.
+ # Prepare for redirection
save_stdin = sys.stdin
# CGI writes its output to sys.stdout, while wsgi app should
# return (list of) strings.
save_stdout = sys.stdout
save_stderr = sys.stderr
- tmpstdout = StringIO.StringIO()
- tmpstderr = StringIO.StringIO()
+ tmpstdout = StringIO()
+ tmpstderr = StringIO()
response = ''
try:
try:
@@ -117,7 +121,7 @@ def mailman_app(environ, start_response):
except:
start_response('200 OK', [('Content-Type', 'text/html')])
retstring = print_traceback(log)
- retstring +=print_environment(log)
+ retstring += print_environment(log)
return retstring
@@ -133,13 +137,13 @@ def print_traceback(log=None):
except ImportError:
traceback = None
try:
- from Mailman.mm_cfg import VERSION
+ from Mailman.Version import VERSION
except ImportError:
VERSION = '&lt;undetermined&gt;'
# Write to the log file first.
if log:
- outfp = StringIO.StringIO()
+ outfp = StringIO()
print >> outfp, '@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@'
print >> outfp, '[----- Mailman Version: %s -----]' % VERSION
@@ -155,7 +159,7 @@ def print_traceback(log=None):
log.error('%s', outfp.getvalue())
# return HTML sink.
- htfp = StringIO.StringIO()
+ htfp = StringIO()
print >> htfp, """\
<head><title>Bug in Mailman version %(VERSION)s</title></head>
<body bgcolor=#ffffff><h2>Bug in Mailman version %(VERSION)s</h2>
@@ -192,7 +196,7 @@ def print_environment(log=None):
os = None
if log:
- outfp = StringIO.StringIO()
+ outfp = StringIO()
# Write some information about our Python executable to the log file.
print >> outfp, '[----- Python Information -----]'
@@ -204,20 +208,20 @@ def print_environment(log=None):
print >> outfp, 'sys.platform =', sys.platform
# Write the same information to the HTML sink.
- htfp = StringIO.StringIO()
+ htfp = StringIO()
if not STEALTH_MODE:
- print >> htfp, '''\
+ print >> htfp, """\
<p><hr><h4>Python information:</h4>
<p><table>
<tr><th>Variable</th><th>Value</th></tr>
<tr><td><tt>sys.version</tt></td><td> %s </td></tr>
<tr><td><tt>sys.executable</tt></td><td> %s </td></tr>
-<tr><td><tt>sys.prefix</tt></td><td> %s </td></tr>'
+<tr><td><tt>sys.prefix</tt></td><td> %s </td></tr>
<tr><td><tt>sys.exec_prefix</tt></td><td> %s </td></tr>
<tr><td><tt>sys.path</tt></td><td> %s </td></tr>
<tr><td><tt>sys.platform</tt></td><td> %s </td></tr>
-</table>''' % (sys.version, sys.executable, sys.prefix,
+</table>""" % (sys.version, sys.executable, sys.prefix,
sys.exec_prefix, sys.path, sys.platform)
# Write environment variables to the log file.
@@ -231,12 +235,12 @@ def print_environment(log=None):
# Write environment variables to the HTML sink.
if not STEALTH_MODE:
- print >> htfp, '''\
+ print >> htfp, """\
<p><hr><h4>Environment variables:</h4>
<p><table>
<tr><th>Variable</th><th>Value</th></tr>
-'''
+"""
if os:
for k, v in os.environ.items():
print >> htfp, '<tr><td><tt>' + websafe(k) + \
diff --git a/Mailman/Defaults.py.in b/Mailman/Defaults.py.in
index 3c5b9e2da..1840ad998 100644
--- a/Mailman/Defaults.py.in
+++ b/Mailman/Defaults.py.in
@@ -716,7 +716,7 @@ USE_MAILDIR = No
#
# NOTE: LMTP delivery is experimental for Mailman 2.2.
USE_LMTP = No
-# NOTE: If you set USE_LMTP = Yes, add the following line to your mailman.cfg
+# NOTE: If you set USE_LMTP = Yes, add the following line to your mailman.cfg
# file (uncommented of course!)
# QRUNNERS.append(('LMTPRunner', 1))
@@ -727,8 +727,10 @@ LMTP_HOST = 'localhost'
LMTP_PORT = 8025
# Experimental WSGI Server.
-# You must enable PROXY of Apache httpd server and configure to pass
-# mailman CGI requests to this WSGI Server:
+#
+# You must enable PROXY of Apache httpd server and configure to pass Mailman
+# CGI requests to this WSGI Server:
+#
# ProxyPass /mailman/ http://localhost:2580/
HTTP_HOST = 'localhost'
HTTP_PORT = 2580
diff --git a/Mailman/Gui/Privacy.py b/Mailman/Gui/Privacy.py
index e073c4ec7..03e756d9b 100644
--- a/Mailman/Gui/Privacy.py
+++ b/Mailman/Gui/Privacy.py
@@ -160,7 +160,7 @@ class Privacy(GUIBase):
spammers.""")),
]
- adminurl = mlist.GetScriptURL('admin', absolute=1)
+ adminurl = mlist.GetScriptURL('admin')
sender_rtn = [
_("""When a message is posted to the list, a series of
moderation steps are take to decide whether the a moderator must
diff --git a/Mailman/HTMLFormatter.py b/Mailman/HTMLFormatter.py
index e6afda9b5..f61ccbb82 100644
--- a/Mailman/HTMLFormatter.py
+++ b/Mailman/HTMLFormatter.py
@@ -1,4 +1,4 @@
-# Copyright (C) 1998-2003 by the Free Software Foundation, Inc.
+# Copyright (C) 1998-2006 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
@@ -12,19 +12,18 @@
#
# 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
-
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
+# USA.
"""Routines for presentation of list-specific HTML text."""
-import time
import re
+import time
-from Mailman import mm_cfg
-from Mailman import Utils
from Mailman import MemberAdaptor
+from Mailman import Utils
+from Mailman import mm_cfg
from Mailman.htmlformat import *
-
from Mailman.i18n import _
@@ -42,7 +41,8 @@ class HTMLFormatter:
# Remove the .Format() when htmlformat conversion is done.
realname = self.real_name
hostname = self.host_name
- listinfo_link = Link(self.GetScriptURL('listinfo'), realname).Format()
+ listinfo_link = Link(self.GetScriptURL('listinfo'),
+ realname).Format()
owner_link = Link('mailto:' + self.GetOwnerEmail(), ownertext).Format()
innertext = _('%(listinfo_link)s list run by %(owner_link)s')
return Container(
diff --git a/Mailman/MailList.py b/Mailman/MailList.py
index 575c9cc84..7cac64865 100644
--- a/Mailman/MailList.py
+++ b/Mailman/MailList.py
@@ -262,12 +262,10 @@ class MailList(HTMLFormatter, Deliverer, ListAdmin,
acct, host = tuple(member.split('@'))
return "%s%s@%s" % (acct, self.umbrella_member_suffix, host)
- def GetScriptURL(self, scriptname, absolute=False):
- return '%s/%s' % (
- Utils.ScriptURL(scriptname, self.web_page_url, absolute),
- self.fqdn_listname)
+ def GetScriptURL(self, target):
+ return Utils.ScriptURL(target) + '/' + self.fqdn_listname
- def GetOptionsURL(self, user, obscure=0, absolute=False):
+ def GetOptionsURL(self, user, obscure=False, absolute=False):
url = self.GetScriptURL('options', absolute)
if obscure:
user = Utils.ObscureEmail(user)
@@ -299,8 +297,7 @@ class MailList(HTMLFormatter, Deliverer, ListAdmin,
name + '@' +
self.host_name)
else:
- self._full_path = os.path.join(config.LIST_DATA_DIR,
- name)
+ self._full_path = os.path.join(config.LIST_DATA_DIR, name)
else:
self._full_path = ''
# Only one level of mixin inheritance allowed
diff --git a/Mailman/Queue/HTTPRunner.py b/Mailman/Queue/HTTPRunner.py
index df36db0d8..e542dc9a3 100644
--- a/Mailman/Queue/HTTPRunner.py
+++ b/Mailman/Queue/HTTPRunner.py
@@ -15,25 +15,24 @@
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
# USA.
-"""Mailman HTTP runner (server).
-
-"""
+"""Mailman HTTP runner (server)."""
import sys
import logging
-import StringIO
+from cStringIO import StringIO
from wsgiref.simple_server import make_server, WSGIRequestHandler
+from Mailman.Cgi.wsgi_app import mailman_app
from Mailman.Queue.Runner import Runner
from Mailman.configuration import config
-from Mailman.Cgi.wsgi_app import mailman_app
hlog = logging.getLogger('mailman.http')
qlog = logging.getLogger('mailman.qrunner')
-class HTTPRunner(Runner):
+
+class HTTPRunner(Runner):
def __init__(self, slice=None, numslices=1):
pass
@@ -41,23 +40,27 @@ class HTTPRunner(Runner):
pass
+
class MailmanWSGIRequestHandler(WSGIRequestHandler):
-
def handle(self):
"""Handle a single HTTP request with error output to elog"""
- stderr = StringIO.StringIO()
- save_stderr = sys.stderr
+ stderr = StringIO()
+ saved_stderr = sys.stderr
sys.stderr = stderr
- WSGIRequestHandler.handle(self)
- sys.stderr = save_stderr
+ try:
+ WSGIRequestHandler.handle(self)
+ finally:
+ sys.stderr = saved_stderr
hlog.info(stderr.getvalue().strip())
+
server = make_server(config.HTTP_HOST, config.HTTP_PORT,
mailman_app,
handler_class=MailmanWSGIRequestHandler)
+
+
qlog.info('HTTPRunner qrunner started.')
server.serve_forever()
# We'll never get here, but just in case...
qlog.info('HTTPRunner qrunner exiting.')
-
diff --git a/Mailman/SecurityManager.py b/Mailman/SecurityManager.py
index e97084cf1..8c55d2863 100644
--- a/Mailman/SecurityManager.py
+++ b/Mailman/SecurityManager.py
@@ -57,8 +57,6 @@ import logging
import marshal
import binascii
-from urlparse import urlparse
-
from Mailman import Errors
from Mailman import mm_cfg
from Mailman import Utils
@@ -225,6 +223,9 @@ class SecurityManager:
return True
return False
+ def _cookie_path(self):
+ return '/%s/%s' % (os.environ['SCRIPT_NAME'], self.fqdn_listname)
+
def MakeCookie(self, authcontext, user=None):
key, secret = self.AuthContextInfo(authcontext, user)
if key is None or secret is None or not isinstance(secret, str):
@@ -236,10 +237,7 @@ class SecurityManager:
# Create the cookie object.
c = Cookie.SimpleCookie()
c[key] = binascii.hexlify(marshal.dumps((issued, mac)))
- # The path to all Mailman stuff, minus the scheme and host,
- # i.e. usually the string `/mailman'
- path = urlparse(self.web_page_url)[2]
- c[key]['path'] = path
+ c[key]['path'] = self._cookie_path()
# We use session cookies, so don't set `expires' or `max-age' keys.
# Set the RFC 2109 required header.
c[key]['version'] = 1
@@ -253,10 +251,7 @@ class SecurityManager:
# string.
c = Cookie.SimpleCookie()
c[key] = ''
- # The path to all Mailman stuff, minus the scheme and host,
- # i.e. usually the string `/mailman'
- path = urlparse(self.web_page_url)[2]
- c[key]['path'] = path
+ c[key]['path'] = self._cookie_path()
c[key]['max-age'] = 0
# Don't set expires=0 here otherwise it'll force a persistent cookie
c[key]['version'] = 1
diff --git a/Mailman/Utils.py b/Mailman/Utils.py
index 10281bdcc..edbf25f31 100644
--- a/Mailman/Utils.py
+++ b/Mailman/Utils.py
@@ -202,7 +202,7 @@ _badchars = re.compile(r'[][()<>|;^,\000-\037\177-\377]')
def ValidateEmail(s):
"""Verify that the an email address isn't grossly evil."""
# Pretty minimal, cheesy check. We could do better...
- if not s or s.count(' ') > 0:
+ if not s or ' ' in s:
raise Errors.MMBadEmailError
if _badchars.search(s) or s[0] == '-':
raise Errors.MMHostileAddress, s
@@ -226,36 +226,13 @@ def GetPathPieces(envar='PATH_INFO'):
path = CRNLpat.split(path)[0]
log.error('Warning: Possible malformed path attack.')
return [p for p in path.split('/') if p]
- return None
+ return []
-def ScriptURL(target, web_page_url=None, absolute=False):
- """target - scriptname only, nothing extra
- web_page_url - the list's configvar of the same name
- absolute - a flag which if set, generates an absolute url
- """
- if web_page_url is None:
- web_page_url = config.DEFAULT_URL_PATTERN % get_request_domain()
- if web_page_url[-1] <> '/':
- web_page_url = web_page_url + '/'
- fullpath = os.environ.get('REQUEST_URI')
- if fullpath is None:
- fullpath = os.environ.get('SCRIPT_NAME', '') + \
- os.environ.get('PATH_INFO', '')
- baseurl = urlparse.urlparse(web_page_url)[2]
- if not absolute and fullpath.endswith(baseurl):
- # Use relative addressing
- fullpath = fullpath[len(baseurl):]
- i = fullpath.find('?')
- if i > 0:
- count = fullpath.count('/', 0, i)
- else:
- count = fullpath.count('/')
- path = ('../' * count) + target
- else:
- path = web_page_url + target
- return path + config.CGIEXT
+def ScriptURL(target):
+ up = '../' * len(GetPathPieces())
+ return '%s%s' % (up, target + config.CGIEXT)
@@ -630,9 +607,9 @@ def GetRequestURI(fallback=None, escape=True):
unless `escape' is set to 0.
"""
url = fallback
- if os.environ.has_key('REQUEST_URI'):
+ if 'REQUEST_URI' in os.environ:
url = os.environ['REQUEST_URI']
- elif os.environ.has_key('SCRIPT_NAME') and os.environ.has_key('PATH_INFO'):
+ elif 'SCRIPT_NAME' in os.environ and 'PATH_INFO' in os.environ:
url = os.environ['SCRIPT_NAME'] + os.environ['PATH_INFO']
if escape:
return websafe(url)
diff --git a/Mailman/bin/export.py b/Mailman/bin/export.py
index 4a72c4e82..1419e95df 100644
--- a/Mailman/bin/export.py
+++ b/Mailman/bin/export.py
@@ -156,12 +156,15 @@ class XMLDumper(object):
self._element('value', v)
self._pop_element('option')
else:
- self._element('option', name=varname, value=value)
+ self._element('option', value, name=varname)
def _dump_list(self, mlist, with_passwords):
# Write list configuration values
self._push_element('list', name=mlist.fqdn_listname)
- self._element('language', mlist.preferred_language)
+ self._push_element('configuration')
+ self._element('option',
+ mlist.preferred_language,
+ name='preferred_language')
for k in config.ADMIN_CATEGORIES:
subcats = mlist.GetConfigSubCategories(k)
if subcats is None:
@@ -169,6 +172,7 @@ class XMLDumper(object):
else:
for subcat in [t[0] for t in subcats]:
self._do_list_categories(mlist, k, subcat)
+ self._pop_element('configuration')
# Write membership
self._push_element('roster')
digesters = set(mlist.getDigestMemberKeys())
@@ -206,14 +210,12 @@ class XMLDumper(object):
when = datetime.datetime.fromtimestamp(changed)
attrs['changed'] = when.isoformat()
self._element('delivery', **attrs)
- self._push_element('options')
for option, flag in Defaults.OPTINFO.items():
# Digest/Regular delivery flag must be handled separately
if option in ('digest', 'plain'):
continue
value = mlist.getMemberOption(member, flag)
self._element(option, value)
- self._pop_element('options')
topics = mlist.getMemberTopics(member)
if not topics:
self._element('topics')
diff --git a/Mailman/bin/show_config.py b/Mailman/bin/show_config.py
index ee97b16a8..3ecfd32b4 100644
--- a/Mailman/bin/show_config.py
+++ b/Mailman/bin/show_config.py
@@ -1,99 +1,98 @@
-# Copyright (C) 2006 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
-# USA.
-
-import re
-import sys
-import pprint
-import optparse
-
-from Mailman import Version
-from Mailman.configuration import config
-from Mailman.i18n import _
-
-__i18_templates__ = True
-
-# List of names never to show even if --verbose
-NEVER_SHOW = ['__builtins__', '__doc__']
-
-
-
-def parseargs():
- parser = optparse.OptionParser(version=Version.MAILMAN_VERSION,
- usage=_("""\
-%%prog [options] [pattern ...]
-
-Show the values of various Defaults.py/mailman.cfg variables.
-If one or more patterns are given, show only those variables
-whose names match a pattern"""))
- parser.add_option('-v', '--verbose',
- default=False, action='store_true',
- help=_(
-"Show all configuration names, not just 'settings'."))
- parser.add_option('-i', '--ignorecase',
- default=False, action='store_true',
- help=_("Match patterns case-insensitively."))
- parser.add_option('-C', '--config',
- help=_('Alternative configuration file to use'))
- opts, args = parser.parse_args()
- return parser, opts, args
-
-
-
-def main():
- parser, opts, args = parseargs()
-
- patterns = []
- if opts.ignorecase:
- flag = re.IGNORECASE
- else:
- flag = 0
- for pattern in args:
- patterns.append(re.compile(pattern, flag))
-
- pp = pprint.PrettyPrinter(indent=4)
- config.load(opts.config)
- names = config.__dict__.keys()
- names.sort()
- for name in names:
- if name in NEVER_SHOW:
- continue
- if not opts.verbose:
- if name.startswith('_') or re.search('[a-z]', name):
- continue
- if patterns:
- hit = False
- for pattern in patterns:
- if pattern.search(name):
- hit = True
- break
- if not hit:
- continue
- value = config.__dict__[name]
- if isinstance(value, str):
- if re.search('\n', value):
- print '%s = """%s"""' %(name, value)
- else:
- print "%s = '%s'" % (name, value)
- else:
- print '%s = ' % name,
- pp.pprint(value)
-
-
-
-if __name__ == '__main__':
- main()
-
+# Copyright (C) 2006 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
+# USA.
+
+import re
+import sys
+import pprint
+import optparse
+
+from Mailman import Version
+from Mailman.configuration import config
+from Mailman.i18n import _
+
+__i18_templates__ = True
+
+# List of names never to show even if --verbose
+NEVER_SHOW = ['__builtins__', '__doc__']
+
+
+
+def parseargs():
+ parser = optparse.OptionParser(version=Version.MAILMAN_VERSION,
+ usage=_("""\
+%%prog [options] [pattern ...]
+
+Show the values of various Defaults.py/mailman.cfg variables.
+If one or more patterns are given, show only those variables
+whose names match a pattern"""))
+ parser.add_option('-v', '--verbose',
+ default=False, action='store_true',
+ help=_(
+"Show all configuration names, not just 'settings'."))
+ parser.add_option('-i', '--ignorecase',
+ default=False, action='store_true',
+ help=_("Match patterns case-insensitively."))
+ parser.add_option('-C', '--config',
+ help=_('Alternative configuration file to use'))
+ opts, args = parser.parse_args()
+ return parser, opts, args
+
+
+
+def main():
+ parser, opts, args = parseargs()
+
+ patterns = []
+ if opts.ignorecase:
+ flag = re.IGNORECASE
+ else:
+ flag = 0
+ for pattern in args:
+ patterns.append(re.compile(pattern, flag))
+
+ pp = pprint.PrettyPrinter(indent=4)
+ config.load(opts.config)
+ names = config.__dict__.keys()
+ names.sort()
+ for name in names:
+ if name in NEVER_SHOW:
+ continue
+ if not opts.verbose:
+ if name.startswith('_') or re.search('[a-z]', name):
+ continue
+ if patterns:
+ hit = False
+ for pattern in patterns:
+ if pattern.search(name):
+ hit = True
+ break
+ if not hit:
+ continue
+ value = config.__dict__[name]
+ if isinstance(value, str):
+ if re.search('\n', value):
+ print '%s = """%s"""' %(name, value)
+ else:
+ print "%s = '%s'" % (name, value)
+ else:
+ print '%s = ' % name,
+ pp.pprint(value)
+
+
+
+if __name__ == '__main__':
+ main()
diff --git a/Mailman/configuration.py b/Mailman/configuration.py
index 6ee94b911..66aa6c191 100644
--- a/Mailman/configuration.py
+++ b/Mailman/configuration.py
@@ -29,7 +29,7 @@ _missing = object()
class Configuration(object):
def __init__(self):
- self.domains = {}
+ self.domains = {} # email host -> web host
self._reverse = None
def load(self, filename=None):
diff --git a/Mailman/loginit.py b/Mailman/loginit.py
index cfeb64366..2dfa00837 100644
--- a/Mailman/loginit.py
+++ b/Mailman/loginit.py
@@ -31,6 +31,7 @@ DATEFMT = '%b %d %H:%M:%S %Y'
LOGGERS = (
'bounce',
'config',
+ 'debug',
'error',
'http',
'locks',
diff --git a/bin/Makefile.in b/bin/Makefile.in
index a9b9c6688..f576606b3 100644
--- a/bin/Makefile.in
+++ b/bin/Makefile.in
@@ -54,7 +54,7 @@ SCRIPTS= mmshell \
reset_pw.py templ2pot.py po2templ.py
LN_SCRIPTS= add_members arch change_pw check_perms config_list \
- export find_member genaliases inject list_lists \
+ export find_member genaliases import inject list_lists \
list_members list_owners mailmanctl mmsitepass newlist \
qrunner rmlist show_config show_qfiles testall unshunt \
update version
diff --git a/misc/Makefile.in b/misc/Makefile.in
index 9227f63a9..f6d919f6b 100644
--- a/misc/Makefile.in
+++ b/misc/Makefile.in
@@ -48,14 +48,23 @@ SCRIPTSDIR= $(prefix)/scripts
SHELL= /bin/sh
PYTHONLIBDIR= $(prefix)/pythonlib
+
+# Traditional distutils packages
SETUPINSTOPTS= --install-lib $(DESTDIR)$(PYTHONLIBDIR) \
--install-purelib $(DESTDIR)$(PYTHONLIBDIR) \
--install-data $(DESTDIR)$(PYTHONLIBDIR)
SETUPCMD= setup.py --quiet install $(SETUPINSTOPTS)
-EMAILPKG= email-4.0.1
+EMAIL= email-4.0.1
+SETUPTOOLS= setuptools-0.6c3
+SETUPPKGS= $(EMAIL) $(SETUPTOOLS)
+
+EZINSTOPTS= --install-dir $(DESTDIR)$(PYTHONLIBDIR)
+EZCMD= $(PYTHONLIBDIR)/$(SETUPTOOLS)-py2.4.egg/easy_install.py \
+ $(EZINSTALLOPTS)
-PACKAGES= $(EMAILPKG)
+WSGIREF= wsgiref-0.1.2-py2.4.egg
+EZPKGS= $(WSGIREF)
# Modes for directories and executables created by the install
# process. Default to group-writable directories but
@@ -86,10 +95,15 @@ install-other:
$(INSTALL) -m $(FILEMODE) mailman.cfg.sample $(DESTDIR)$(ETCDIR)
install-packages:
- for p in $(PACKAGES); \
+ for p in $(SETUPPKGS); \
do \
gunzip -c $(srcdir)/$$p.tar.gz | tar xf -; \
- (cd $$p ; umask 02 ; PYTHONPATH=$(PYTHONLIBDIR) $(PYTHON) $(SETUPCMD)); \
+ (cd $$p ; umask 02 ; \
+ PYTHONPATH=$(PYTHONLIBDIR) $(PYTHON) $(SETUPCMD)); \
+ done
+ for p in $(EZPKGS); \
+ do \
+ (umask 02 ; PYTHONPATH=$(PYTHONLIBDIR) $(PYTHON) $(EZCMD) $$p); \
done
finish:
diff --git a/misc/setuptools-0.6c3.tar.gz b/misc/setuptools-0.6c3.tar.gz
new file mode 100644
index 000000000..30a4a464a
--- /dev/null
+++ b/misc/setuptools-0.6c3.tar.gz
Binary files differ
diff --git a/misc/wsgiref-0.1.2-py2.4.egg b/misc/wsgiref-0.1.2-py2.4.egg
new file mode 100644
index 000000000..b38cb8321
--- /dev/null
+++ b/misc/wsgiref-0.1.2-py2.4.egg
Binary files differ