From b132a73f15e432eaf43310fce9196ca0c0651465 Mon Sep 17 00:00:00 2001
From: <>
Date: Thu, 2 Jan 2003 05:25:50 +0000
Subject: This commit was manufactured by cvs2svn to create branch
'Release_2_1-maint'.
---
Mailman/Cgi/create.py | 410 ++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 410 insertions(+)
create mode 100644 Mailman/Cgi/create.py
(limited to 'Mailman/Cgi/create.py')
diff --git a/Mailman/Cgi/create.py b/Mailman/Cgi/create.py
new file mode 100644
index 00000000..31e16269
--- /dev/null
+++ b/Mailman/Cgi/create.py
@@ -0,0 +1,410 @@
+# Copyright (C) 2001,2002 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.
+
+"""Create mailing lists through the web."""
+
+import sys
+import os
+import signal
+import cgi
+import sha
+from types import ListType
+
+from Mailman import mm_cfg
+from Mailman import MailList
+from Mailman import Message
+from Mailman import Errors
+from Mailman import i18n
+from Mailman.htmlformat import *
+from Mailman.Logging.Syslog import syslog
+
+# Set up i18n
+_ = i18n._
+i18n.set_language(mm_cfg.DEFAULT_SERVER_LANGUAGE)
+
+
+
+def main():
+ doc = Document()
+ doc.set_language(mm_cfg.DEFAULT_SERVER_LANGUAGE)
+
+ cgidata = cgi.FieldStorage()
+ parts = Utils.GetPathPieces()
+ if parts:
+ # Bad URL specification
+ title = _('Bad URL specification')
+ doc.SetTitle(title)
+ doc.AddItem(
+ Header(3, Bold(FontAttr(title, color='#ff0000', size='+2'))))
+ syslog('error', 'Bad URL specification: %s', parts)
+ elif cgidata.has_key('doit'):
+ # We must be processing the list creation request
+ process_request(doc, cgidata)
+ elif cgidata.has_key('clear'):
+ request_creation(doc)
+ else:
+ # Put up the list creation request form
+ request_creation(doc)
+ doc.AddItem('
')
+ # Always add the footer and print the document
+ doc.AddItem(_('Return to the ') +
+ Link(Utils.ScriptURL('listinfo'),
+ _('general list overview')).Format())
+ doc.AddItem(_('
Return to the ') +
+ Link(Utils.ScriptURL('admin'),
+ _('administrative list overview')).Format())
+ doc.AddItem(MailmanLogo())
+ print doc.Format()
+
+
+
+def process_request(doc, cgidata):
+ # Lowercase the listname since this is treated as the "internal" name.
+ listname = cgidata.getvalue('listname', '').strip().lower()
+ owner = cgidata.getvalue('owner', '').strip()
+ try:
+ autogen = int(cgidata.getvalue('autogen', '0'))
+ except ValueError:
+ autogen = 0
+ try:
+ notify = int(cgidata.getvalue('notify', '0'))
+ except ValueError:
+ notify = 0
+ try:
+ moderate = int(cgidata.getvalue('moderate', '0'))
+ except ValueError:
+ moderate = mm_cfg.DEFAULT_DEFAULT_MEMBER_MODERATION
+
+ password = cgidata.getvalue('password', '').strip()
+ confirm = cgidata.getvalue('confirm', '').strip()
+ auth = cgidata.getvalue('auth', '').strip()
+ langs = cgidata.getvalue('langs', [mm_cfg.DEFAULT_SERVER_LANGUAGE])
+
+ if type(langs) <> ListType:
+ langs = [langs]
+ # Sanity check
+ if '@' in listname:
+ request_creation(doc, cgidata,
+ _('List name must not include "@": %(listname)s'))
+ return
+ if Utils.list_exists(listname):
+ # BAW: should we tell them the list already exists? This could be
+ # used to mine/guess the existance of non-advertised lists. Then
+ # again, that can be done in other ways already, so oh well.
+ request_creation(doc, cgidata, _('List already exists: %(listname)s'))
+ return
+ if not listname:
+ request_creation(doc, cgidata,
+ _('You forgot to enter the list name'))
+ return
+ if not owner:
+ request_creation(doc, cgidata,
+ _('You forgot to specify the list owner'))
+ return
+
+ if autogen:
+ if password or confirm:
+ request_creation(
+ doc, cgidata,
+ _('''Leave the initial password (and confirmation) fields
+ blank if you want Mailman to autogenerate the list
+ passwords.'''))
+ return
+ password = confirm = Utils.MakeRandomPassword(length=8)
+ else:
+ if password <> confirm:
+ request_creation(doc, cgidata,
+ _('Initial list passwords do not match'))
+ return
+ if not password:
+ request_creation(
+ doc, cgidata,
+ # The little tag is used so that this string
+ # differs from the one in bin/newlist. The former is destined
+ # for the web while the latter is destined for email, so they
+ # must be different entries in the message catalog.
+ _('The list password cannot be empty'))
+ return
+ # The authorization password must be non-empty, and it must match either
+ # the list creation password or the site admin password
+ ok = 0
+ if auth:
+ ok = Utils.check_global_password(auth, 0)
+ if not ok:
+ ok = Utils.check_global_password(auth)
+ if not ok:
+ request_creation(
+ doc, cgidata,
+ _('You are not authorized to create new mailing lists'))
+ return
+ # We've got all the data we need, so go ahead and try to create the list
+ # See admin.py for why we need to set up the signal handler.
+ mlist = MailList.MailList()
+
+ def sigterm_handler(signum, frame, mlist=mlist):
+ # Make sure the list gets unlocked...
+ mlist.Unlock()
+ # ...and ensure we exit, otherwise race conditions could cause us to
+ # enter MailList.Save() while we're in the unlocked state, and that
+ # could be bad!
+ sys.exit(0)
+
+ try:
+ # Install the emergency shutdown signal handler
+ signal.signal(signal.SIGTERM, sigterm_handler)
+
+ pw = sha.new(password).hexdigest()
+ # Guarantee that all newly created files have the proper permission.
+ # proper group ownership should be assured by the autoconf script
+ # enforcing that all directories have the group sticky bit set
+ oldmask = os.umask(002)
+ try:
+ try:
+ mlist.Create(listname, owner, pw, langs)
+ finally:
+ os.umask(oldmask)
+ except Errors.MMBadEmailError, s:
+ request_creation(doc, cgidata,
+ _('Bad owner email address: %(s)s'))
+ return
+ except Errors.MMListAlreadyExistsError:
+ request_creation(doc, cgidata,
+ _('List already exists: %(listname)s'))
+ return
+ except Errors.BadListNameError, s:
+ request_creation(doc, cgidata,
+ _('Illegal list name: %(s)s'))
+ return
+ except Errors.MMListError:
+ request_creation(
+ doc, cgidata,
+ _('''Some unknown error occurred while creating the list.
+ Please contact the site administrator for assistance.'''))
+ return
+
+ # Initialize the host_name and web_page_url attributes, based on
+ # virtual hosting settings and the request environment variables.
+ hostname = Utils.get_domain()
+ mlist.default_member_moderation = moderate
+ mlist.web_page_url = mm_cfg.DEFAULT_URL_PATTERN % hostname
+ mlist.host_name = mm_cfg.VIRTUAL_HOSTS.get(
+ hostname, mm_cfg.DEFAULT_EMAIL_HOST)
+ mlist.Save()
+ finally:
+ # Now be sure to unlock the list. It's okay if we get a signal here
+ # because essentially, the signal handler will do the same thing. And
+ # unlocking is unconditional, so it's not an error if we unlock while
+ # we're already unlocked.
+ mlist.Unlock()
+
+ # Now do the MTA-specific list creation tasks
+ if mm_cfg.MTA:
+ modname = 'Mailman.MTA.' + mm_cfg.MTA
+ __import__(modname)
+ sys.modules[modname].create(mlist, cgi=1)
+
+ # And send the notice to the list owner.
+ if notify:
+ siteadmin = Utils.get_site_email(mlist.host_name, 'admin')
+ text = Utils.maketext(
+ 'newlist.txt',
+ {'listname' : listname,
+ 'password' : password,
+ 'admin_url' : mlist.GetScriptURL('admin', absolute=1),
+ 'listinfo_url': mlist.GetScriptURL('listinfo', absolute=1),
+ 'requestaddr' : mlist.GetRequestEmail(),
+ 'siteowner' : siteadmin,
+ }, mlist=mlist)
+ msg = Message.UserNotification(
+ owner, siteadmin,
+ _('Your new mailing list: %(listname)s'),
+ text, mlist.preferred_language)
+ msg.send(mlist)
+
+ # Success!
+ listinfo_url = mlist.GetScriptURL('listinfo', absolute=1)
+ admin_url = mlist.GetScriptURL('admin', absolute=1)
+ create_url = Utils.ScriptURL('create')
+
+ title = _('Mailing list creation results')
+ doc.SetTitle(title)
+ table = Table(border=0, width='100%')
+ table.AddRow([Center(Bold(FontAttr(title, size='+1')))])
+ table.AddCellInfo(table.GetCurrentRowIndex(), 0,
+ bgcolor=mm_cfg.WEB_HEADER_COLOR)
+ table.AddRow([_('''You have successfully created the mailing list
+ %(listname)s and notification has been sent to the list owner
+ %(owner)s. You can now:''')])
+ ullist = UnorderedList()
+ ullist.AddItem(Link(listinfo_url, _("Visit the list's info page")))
+ ullist.AddItem(Link(admin_url, _("Visit the list's admin page")))
+ ullist.AddItem(Link(create_url, _('Create another list')))
+ table.AddRow([ullist])
+ doc.AddItem(table)
+
+
+
+# Because the cgi module blows
+class Dummy:
+ def getvalue(self, name, default):
+ return default
+dummy = Dummy()
+
+
+
+def request_creation(doc, cgidata=dummy, errmsg=None):
+ # What virtual domain are we using?
+ hostname = Utils.get_domain()
+ # Set up the document
+ title = _('Create a %(hostname)s Mailing List')
+ doc.SetTitle(title)
+ table = Table(border=0, width='100%')
+ table.AddRow([Center(Bold(FontAttr(title, size='+1')))])
+ table.AddCellInfo(table.GetCurrentRowIndex(), 0,
+ bgcolor=mm_cfg.WEB_HEADER_COLOR)
+ # Add any error message
+ if errmsg:
+ table.AddRow([Header(3, Bold(
+ FontAttr(_('Error: '), color='#ff0000', size='+2').Format() +
+ Italic(errmsg).Format()))])
+ table.AddRow([_("""You can create a new mailing list by entering the
+ relevant information into the form below. The name of the mailing list
+ will be used as the primary address for posting messages to the list, so
+ it should be lowercased. You will not be able to change this once the
+ list is created.
+
+ You also need to enter the email address of the initial list owner.
+ Once the list is created, the list owner will be given notification, along
+ with the initial list password. The list owner will then be able to
+ modify the password and add or remove additional list owners.
+
+
If you want Mailman to automatically generate the initial list admin
+ password, click on `Yes' in the autogenerate field below, and leave the
+ initial list password fields empty.
+
+
You must have the proper authorization to create new mailing lists.
+ Each site should have a list creator's password, which you can
+ enter in the field at the bottom. Note that the site administrator's
+ password can also be used for authentication.
+ """)])
+ # Build the form for the necessary input
+ GREY = mm_cfg.WEB_ADMINITEM_COLOR
+ form = Form(Utils.ScriptURL('create'))
+ ftable = Table(border=0, cols='2', width='100%',
+ cellspacing=3, cellpadding=4)
+
+ ftable.AddRow([Center(Italic(_('List Identity')))])
+ ftable.AddCellInfo(ftable.GetCurrentRowIndex(), 0, colspan=2)
+
+ ftable.AddRow([Label(_('Name of list:')),
+ TextBox('listname', cgidata.getvalue('listname', ''))])
+ ftable.AddCellInfo(ftable.GetCurrentRowIndex(), 0, bgcolor=GREY)
+ ftable.AddCellInfo(ftable.GetCurrentRowIndex(), 1, bgcolor=GREY)
+
+ ftable.AddRow([Label(_('Initial list owner address:')),
+ TextBox('owner', cgidata.getvalue('owner', ''))])
+ ftable.AddCellInfo(ftable.GetCurrentRowIndex(), 0, bgcolor=GREY)
+ ftable.AddCellInfo(ftable.GetCurrentRowIndex(), 1, bgcolor=GREY)
+
+ try:
+ autogen = int(cgidata.getvalue('autogen', '0'))
+ except ValueError:
+ autogen = 0
+ ftable.AddRow([Label(_('Auto-generate initial list password?')),
+ RadioButtonArray('autogen', (_('No'), _('Yes')),
+ checked=autogen,
+ values=(0, 1))])
+ ftable.AddCellInfo(ftable.GetCurrentRowIndex(), 0, bgcolor=GREY)
+ ftable.AddCellInfo(ftable.GetCurrentRowIndex(), 1, bgcolor=GREY)
+
+ ftable.AddRow([Label(_('Initial list password:')),
+ PasswordBox('password', cgidata.getvalue('password', ''))])
+ ftable.AddCellInfo(ftable.GetCurrentRowIndex(), 0, bgcolor=GREY)
+ ftable.AddCellInfo(ftable.GetCurrentRowIndex(), 1, bgcolor=GREY)
+
+ ftable.AddRow([Label(_('Confirm initial password:')),
+ PasswordBox('confirm', cgidata.getvalue('confirm', ''))])
+ ftable.AddCellInfo(ftable.GetCurrentRowIndex(), 0, bgcolor=GREY)
+ ftable.AddCellInfo(ftable.GetCurrentRowIndex(), 1, bgcolor=GREY)
+
+ try:
+ notify = int(cgidata.getvalue('notify', '1'))
+ except ValueError:
+ notify = 1
+
+ ftable.AddRow([Center(Italic(_('List Characteristics')))])
+ ftable.AddCellInfo(ftable.GetCurrentRowIndex(), 0, colspan=2)
+
+ ftable.AddRow([
+ Label(_("""Should new members be quarantined before they
+ are allowed to post unmoderated to this list? Answer Yes to hold
+ new member postings for moderator approval by default.""")),
+ RadioButtonArray('moderate', (_('No'), _('Yes')),
+ checked=mm_cfg.DEFAULT_DEFAULT_MEMBER_MODERATION,
+ values=(0,1))])
+ ftable.AddCellInfo(ftable.GetCurrentRowIndex(), 0, bgcolor=GREY)
+ ftable.AddCellInfo(ftable.GetCurrentRowIndex(), 1, bgcolor=GREY)
+ # Create the table of initially supported languages, sorted on the long
+ # name of the language.
+ revmap = {}
+ for key, (name, charset) in mm_cfg.LC_DESCRIPTIONS.items():
+ revmap[_(name)] = key
+ langnames = revmap.keys()
+ langnames.sort()
+ langs = []
+ for name in langnames:
+ langs.append(revmap[name])
+ try:
+ langi = langs.index(mm_cfg.DEFAULT_SERVER_LANGUAGE)
+ except ValueError:
+ # Someone must have deleted the servers's preferred language. Could
+ # be other trouble lurking!
+ langi = 0
+ # BAW: we should preserve the list of checked languages across form
+ # invocations.
+ checked = [0] * len(langs)
+ checked[langi] = 1
+ deflang = _(Utils.GetLanguageDescr(mm_cfg.DEFAULT_SERVER_LANGUAGE))
+ ftable.AddRow([Label(_(
+ '''Initial list of supported languages.
Note that if you do not
+ select at least one initial language, the list will use the server
+ default language of %(deflang)s''')),
+ CheckBoxArray('langs',
+ [_(Utils.GetLanguageDescr(L)) for L in langs],
+ checked=checked,
+ values=langs)])
+ ftable.AddCellInfo(ftable.GetCurrentRowIndex(), 0, bgcolor=GREY)
+ ftable.AddCellInfo(ftable.GetCurrentRowIndex(), 1, bgcolor=GREY)
+
+ ftable.AddRow([Label(_('Send "list created" email to list owner?')),
+ RadioButtonArray('notify', (_('No'), _('Yes')),
+ checked=notify,
+ values=(0, 1))])
+ ftable.AddCellInfo(ftable.GetCurrentRowIndex(), 0, bgcolor=GREY)
+ ftable.AddCellInfo(ftable.GetCurrentRowIndex(), 1, bgcolor=GREY)
+
+ ftable.AddRow(['
'])
+ ftable.AddCellInfo(ftable.GetCurrentRowIndex(), 0, colspan=2)
+ ftable.AddRow([Label(_("List creator's (authentication) password:")),
+ PasswordBox('auth')])
+ ftable.AddCellInfo(ftable.GetCurrentRowIndex(), 0, bgcolor=GREY)
+ ftable.AddCellInfo(ftable.GetCurrentRowIndex(), 1, bgcolor=GREY)
+
+ ftable.AddRow([Center(SubmitButton('doit', _('Create List'))),
+ Center(SubmitButton('clear', _('Clear Form')))])
+ form.AddItem(ftable)
+ table.AddRow([form])
+ doc.AddItem(table)
--
cgit v1.2.3