diff options
| -rw-r--r-- | Mailman/Archiver/Archiver.py | 18 | ||||
| -rw-r--r-- | Mailman/Cgi/Auth.py | 19 | ||||
| -rw-r--r-- | Mailman/Cgi/admin.py | 10 | ||||
| -rw-r--r-- | Mailman/Cgi/admindb.py | 2 | ||||
| -rw-r--r-- | Mailman/Cgi/create.py | 2 | ||||
| -rw-r--r-- | Mailman/Cgi/private.py | 19 | ||||
| -rw-r--r-- | Mailman/Cgi/wsgi_app.py | 60 | ||||
| -rw-r--r-- | Mailman/Defaults.py.in | 8 | ||||
| -rw-r--r-- | Mailman/Gui/Privacy.py | 2 | ||||
| -rw-r--r-- | Mailman/HTMLFormatter.py | 16 | ||||
| -rw-r--r-- | Mailman/MailList.py | 11 | ||||
| -rw-r--r-- | Mailman/Queue/HTTPRunner.py | 27 | ||||
| -rw-r--r-- | Mailman/SecurityManager.py | 15 | ||||
| -rw-r--r-- | Mailman/Utils.py | 37 | ||||
| -rw-r--r-- | Mailman/bin/export.py | 10 | ||||
| -rw-r--r-- | Mailman/bin/show_config.py | 197 | ||||
| -rw-r--r-- | Mailman/configuration.py | 2 | ||||
| -rw-r--r-- | Mailman/loginit.py | 1 | ||||
| -rw-r--r-- | bin/Makefile.in | 2 | ||||
| -rw-r--r-- | misc/Makefile.in | 22 | ||||
| -rw-r--r-- | misc/setuptools-0.6c3.tar.gz | bin | 0 -> 238544 bytes | |||
| -rw-r--r-- | misc/wsgiref-0.1.2-py2.4.egg | bin | 0 -> 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 = '<undetermined>' # 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 Binary files differnew file mode 100644 index 000000000..30a4a464a --- /dev/null +++ b/misc/setuptools-0.6c3.tar.gz diff --git a/misc/wsgiref-0.1.2-py2.4.egg b/misc/wsgiref-0.1.2-py2.4.egg Binary files differnew file mode 100644 index 000000000..b38cb8321 --- /dev/null +++ b/misc/wsgiref-0.1.2-py2.4.egg |
