356
by bwarsaw
process_request(): Catch base class of EmailAddressError so either |
1 |
# Copyright (C) 2001-2004 by the Free Software Foundation, Inc.
|
1
by
This commit was manufactured by cvs2svn to create branch |
2 |
#
|
3 |
# This program is free software; you can redistribute it and/or
|
|
4 |
# modify it under the terms of the GNU General Public License
|
|
5 |
# as published by the Free Software Foundation; either version 2
|
|
6 |
# of the License, or (at your option) any later version.
|
|
128
by bwarsaw
process_request(), request_creation(): Close cross-site scripting |
7 |
#
|
1
by
This commit was manufactured by cvs2svn to create branch |
8 |
# This program is distributed in the hope that it will be useful,
|
9 |
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
10 |
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
11 |
# GNU General Public License for more details.
|
|
128
by bwarsaw
process_request(), request_creation(): Close cross-site scripting |
12 |
#
|
1
by
This commit was manufactured by cvs2svn to create branch |
13 |
# You should have received a copy of the GNU General Public License
|
128
by bwarsaw
process_request(), request_creation(): Close cross-site scripting |
14 |
# along with this program; if not, write to the Free Software
|
749
by tkikuchi
FSF office has moved to 51 Franklin Street. |
15 |
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
1
by
This commit was manufactured by cvs2svn to create branch |
16 |
|
17 |
"""Create mailing lists through the web."""
|
|
18 |
||
19 |
import sys |
|
20 |
import os |
|
21 |
import signal |
|
22 |
import cgi |
|
23 |
import sha |
|
24 |
from types import ListType |
|
25 |
||
26 |
from Mailman import mm_cfg |
|
27 |
from Mailman import MailList |
|
28 |
from Mailman import Message |
|
29 |
from Mailman import Errors |
|
30 |
from Mailman import i18n |
|
31 |
from Mailman.htmlformat import * |
|
32 |
from Mailman.Logging.Syslog import syslog |
|
33 |
||
34 |
# Set up i18n
|
|
35 |
_ = i18n._ |
|
36 |
i18n.set_language(mm_cfg.DEFAULT_SERVER_LANGUAGE) |
|
37 |
||
38 |
||
39 |
||
40 |
def main(): |
|
41 |
doc = Document() |
|
42 |
doc.set_language(mm_cfg.DEFAULT_SERVER_LANGUAGE) |
|
43 |
||
44 |
cgidata = cgi.FieldStorage() |
|
45 |
parts = Utils.GetPathPieces() |
|
46 |
if parts: |
|
47 |
# Bad URL specification
|
|
48 |
title = _('Bad URL specification') |
|
49 |
doc.SetTitle(title) |
|
50 |
doc.AddItem( |
|
51 |
Header(3, Bold(FontAttr(title, color='#ff0000', size='+2')))) |
|
52 |
syslog('error', 'Bad URL specification: %s', parts) |
|
53 |
elif cgidata.has_key('doit'): |
|
54 |
# We must be processing the list creation request
|
|
55 |
process_request(doc, cgidata) |
|
56 |
elif cgidata.has_key('clear'): |
|
57 |
request_creation(doc) |
|
58 |
else: |
|
59 |
# Put up the list creation request form
|
|
60 |
request_creation(doc) |
|
61 |
doc.AddItem('<hr>') |
|
62 |
# Always add the footer and print the document
|
|
63 |
doc.AddItem(_('Return to the ') + |
|
64 |
Link(Utils.ScriptURL('listinfo'), |
|
65 |
_('general list overview')).Format()) |
|
66 |
doc.AddItem(_('<br>Return to the ') + |
|
67 |
Link(Utils.ScriptURL('admin'), |
|
68 |
_('administrative list overview')).Format()) |
|
69 |
doc.AddItem(MailmanLogo()) |
|
70 |
print doc.Format() |
|
71 |
||
72 |
||
73 |
||
74 |
def process_request(doc, cgidata): |
|
75 |
# Lowercase the listname since this is treated as the "internal" name.
|
|
76 |
listname = cgidata.getvalue('listname', '').strip().lower() |
|
77 |
owner = cgidata.getvalue('owner', '').strip() |
|
78 |
try: |
|
79 |
autogen = int(cgidata.getvalue('autogen', '0')) |
|
80 |
except ValueError: |
|
81 |
autogen = 0 |
|
82 |
try: |
|
83 |
notify = int(cgidata.getvalue('notify', '0')) |
|
84 |
except ValueError: |
|
85 |
notify = 0 |
|
86 |
try: |
|
87 |
moderate = int(cgidata.getvalue('moderate', '0')) |
|
88 |
except ValueError: |
|
89 |
moderate = mm_cfg.DEFAULT_DEFAULT_MEMBER_MODERATION |
|
128
by bwarsaw
process_request(), request_creation(): Close cross-site scripting |
90 |
|
1
by
This commit was manufactured by cvs2svn to create branch |
91 |
password = cgidata.getvalue('password', '').strip() |
92 |
confirm = cgidata.getvalue('confirm', '').strip() |
|
93 |
auth = cgidata.getvalue('auth', '').strip() |
|
94 |
langs = cgidata.getvalue('langs', [mm_cfg.DEFAULT_SERVER_LANGUAGE]) |
|
95 |
||
176
by bwarsaw
process_request(): In response to SF bug # 835870, we now check the |
96 |
if not isinstance(langs, ListType): |
1
by
This commit was manufactured by cvs2svn to create branch |
97 |
langs = [langs] |
98 |
# Sanity check
|
|
128
by bwarsaw
process_request(), request_creation(): Close cross-site scripting |
99 |
safelistname = Utils.websafe(listname) |
1
by
This commit was manufactured by cvs2svn to create branch |
100 |
if '@' in listname: |
101 |
request_creation(doc, cgidata, |
|
128
by bwarsaw
process_request(), request_creation(): Close cross-site scripting |
102 |
_('List name must not include "@": %(safelistname)s')) |
1
by
This commit was manufactured by cvs2svn to create branch |
103 |
return
|
104 |
if Utils.list_exists(listname): |
|
105 |
# BAW: should we tell them the list already exists? This could be
|
|
106 |
# used to mine/guess the existance of non-advertised lists. Then
|
|
107 |
# again, that can be done in other ways already, so oh well.
|
|
128
by bwarsaw
process_request(), request_creation(): Close cross-site scripting |
108 |
request_creation(doc, cgidata, |
109 |
_('List already exists: %(safelistname)s')) |
|
1
by
This commit was manufactured by cvs2svn to create branch |
110 |
return
|
111 |
if not listname: |
|
112 |
request_creation(doc, cgidata, |
|
113 |
_('You forgot to enter the list name')) |
|
114 |
return
|
|
115 |
if not owner: |
|
116 |
request_creation(doc, cgidata, |
|
117 |
_('You forgot to specify the list owner')) |
|
118 |
return
|
|
119 |
||
120 |
if autogen: |
|
121 |
if password or confirm: |
|
122 |
request_creation( |
|
123 |
doc, cgidata, |
|
124 |
_('''Leave the initial password (and confirmation) fields |
|
125 |
blank if you want Mailman to autogenerate the list
|
|
126 |
passwords.''')) |
|
127 |
return
|
|
567
by bwarsaw
From the NEWS file: |
128 |
password = confirm = Utils.MakeRandomPassword( |
129 |
mm_cfg.ADMIN_PASSWORD_LENGTH) |
|
1
by
This commit was manufactured by cvs2svn to create branch |
130 |
else: |
131 |
if password <> confirm: |
|
132 |
request_creation(doc, cgidata, |
|
133 |
_('Initial list passwords do not match')) |
|
134 |
return
|
|
135 |
if not password: |
|
136 |
request_creation( |
|
137 |
doc, cgidata, |
|
138 |
# The little <!-- ignore --> tag is used so that this string
|
|
139 |
# differs from the one in bin/newlist. The former is destined
|
|
140 |
# for the web while the latter is destined for email, so they
|
|
141 |
# must be different entries in the message catalog.
|
|
142 |
_('The list password cannot be empty<!-- ignore -->')) |
|
143 |
return
|
|
144 |
# The authorization password must be non-empty, and it must match either
|
|
145 |
# the list creation password or the site admin password
|
|
146 |
ok = 0 |
|
147 |
if auth: |
|
148 |
ok = Utils.check_global_password(auth, 0) |
|
149 |
if not ok: |
|
150 |
ok = Utils.check_global_password(auth) |
|
151 |
if not ok: |
|
152 |
request_creation( |
|
153 |
doc, cgidata, |
|
154 |
_('You are not authorized to create new mailing lists')) |
|
155 |
return
|
|
176
by bwarsaw
process_request(): In response to SF bug # 835870, we now check the |
156 |
# Make sure the web hostname matches one of our virtual domains
|
157 |
hostname = Utils.get_domain() |
|
158 |
if mm_cfg.VIRTUAL_HOST_OVERVIEW and \ |
|
159 |
not mm_cfg.VIRTUAL_HOSTS.has_key(hostname): |
|
160 |
safehostname = Utils.websafe(hostname) |
|
161 |
request_creation(doc, cgidata, |
|
162 |
_('Unknown virtual host: %(safehostname)s')) |
|
163 |
return
|
|
164 |
emailhost = mm_cfg.VIRTUAL_HOSTS.get(hostname, mm_cfg.DEFAULT_EMAIL_HOST) |
|
1
by
This commit was manufactured by cvs2svn to create branch |
165 |
# We've got all the data we need, so go ahead and try to create the list
|
166 |
# See admin.py for why we need to set up the signal handler.
|
|
167 |
mlist = MailList.MailList() |
|
168 |
||
169 |
def sigterm_handler(signum, frame, mlist=mlist): |
|
170 |
# Make sure the list gets unlocked...
|
|
171 |
mlist.Unlock() |
|
172 |
# ...and ensure we exit, otherwise race conditions could cause us to
|
|
173 |
# enter MailList.Save() while we're in the unlocked state, and that
|
|
174 |
# could be bad!
|
|
175 |
sys.exit(0) |
|
176 |
||
177 |
try: |
|
178 |
# Install the emergency shutdown signal handler
|
|
179 |
signal.signal(signal.SIGTERM, sigterm_handler) |
|
180 |
||
181 |
pw = sha.new(password).hexdigest() |
|
182 |
# Guarantee that all newly created files have the proper permission.
|
|
183 |
# proper group ownership should be assured by the autoconf script
|
|
184 |
# enforcing that all directories have the group sticky bit set
|
|
185 |
oldmask = os.umask(002) |
|
186 |
try: |
|
187 |
try: |
|
176
by bwarsaw
process_request(): In response to SF bug # 835870, we now check the |
188 |
mlist.Create(listname, owner, pw, langs, emailhost) |
1
by
This commit was manufactured by cvs2svn to create branch |
189 |
finally: |
190 |
os.umask(oldmask) |
|
356
by bwarsaw
process_request(): Catch base class of EmailAddressError so either |
191 |
except Errors.EmailAddressError, s: |
1
by
This commit was manufactured by cvs2svn to create branch |
192 |
request_creation(doc, cgidata, |
193 |
_('Bad owner email address: %(s)s')) |
|
194 |
return
|
|
195 |
except Errors.MMListAlreadyExistsError: |
|
196 |
request_creation(doc, cgidata, |
|
197 |
_('List already exists: %(listname)s')) |
|
198 |
return
|
|
199 |
except Errors.BadListNameError, s: |
|
200 |
request_creation(doc, cgidata, |
|
201 |
_('Illegal list name: %(s)s')) |
|
202 |
return
|
|
203 |
except Errors.MMListError: |
|
204 |
request_creation( |
|
205 |
doc, cgidata, |
|
206 |
_('''Some unknown error occurred while creating the list. |
|
207 |
Please contact the site administrator for assistance.''')) |
|
208 |
return
|
|
128
by bwarsaw
process_request(), request_creation(): Close cross-site scripting |
209 |
|
1
by
This commit was manufactured by cvs2svn to create branch |
210 |
# Initialize the host_name and web_page_url attributes, based on
|
211 |
# virtual hosting settings and the request environment variables.
|
|
212 |
mlist.default_member_moderation = moderate |
|
213 |
mlist.web_page_url = mm_cfg.DEFAULT_URL_PATTERN % hostname |
|
176
by bwarsaw
process_request(): In response to SF bug # 835870, we now check the |
214 |
mlist.host_name = emailhost |
1
by
This commit was manufactured by cvs2svn to create branch |
215 |
mlist.Save() |
216 |
finally: |
|
217 |
# Now be sure to unlock the list. It's okay if we get a signal here
|
|
218 |
# because essentially, the signal handler will do the same thing. And
|
|
219 |
# unlocking is unconditional, so it's not an error if we unlock while
|
|
220 |
# we're already unlocked.
|
|
221 |
mlist.Unlock() |
|
222 |
||
223 |
# Now do the MTA-specific list creation tasks
|
|
224 |
if mm_cfg.MTA: |
|
225 |
modname = 'Mailman.MTA.' + mm_cfg.MTA |
|
226 |
__import__(modname) |
|
227 |
sys.modules[modname].create(mlist, cgi=1) |
|
228 |
||
229 |
# And send the notice to the list owner.
|
|
230 |
if notify: |
|
488
by tkikuchi
[ 874764 ] -admin address is now equiv to -bounce |
231 |
siteowner = Utils.get_site_email(mlist.host_name, 'owner') |
1
by
This commit was manufactured by cvs2svn to create branch |
232 |
text = Utils.maketext( |
233 |
'newlist.txt', |
|
234 |
{'listname' : listname, |
|
128
by bwarsaw
process_request(), request_creation(): Close cross-site scripting |
235 |
'password' : password, |
236 |
'admin_url' : mlist.GetScriptURL('admin', absolute=1), |
|
1
by
This commit was manufactured by cvs2svn to create branch |
237 |
'listinfo_url': mlist.GetScriptURL('listinfo', absolute=1), |
238 |
'requestaddr' : mlist.GetRequestEmail(), |
|
488
by tkikuchi
[ 874764 ] -admin address is now equiv to -bounce |
239 |
'siteowner' : siteowner, |
1
by
This commit was manufactured by cvs2svn to create branch |
240 |
}, mlist=mlist) |
241 |
msg = Message.UserNotification( |
|
488
by tkikuchi
[ 874764 ] -admin address is now equiv to -bounce |
242 |
owner, siteowner, |
1
by
This commit was manufactured by cvs2svn to create branch |
243 |
_('Your new mailing list: %(listname)s'), |
244 |
text, mlist.preferred_language) |
|
245 |
msg.send(mlist) |
|
246 |
||
247 |
# Success!
|
|
248 |
listinfo_url = mlist.GetScriptURL('listinfo', absolute=1) |
|
249 |
admin_url = mlist.GetScriptURL('admin', absolute=1) |
|
250 |
create_url = Utils.ScriptURL('create') |
|
251 |
||
252 |
title = _('Mailing list creation results') |
|
253 |
doc.SetTitle(title) |
|
254 |
table = Table(border=0, width='100%') |
|
255 |
table.AddRow([Center(Bold(FontAttr(title, size='+1')))]) |
|
256 |
table.AddCellInfo(table.GetCurrentRowIndex(), 0, |
|
257 |
bgcolor=mm_cfg.WEB_HEADER_COLOR) |
|
258 |
table.AddRow([_('''You have successfully created the mailing list |
|
259 |
<b>%(listname)s</b> and notification has been sent to the list owner |
|
260 |
<b>%(owner)s</b>. You can now:''')]) |
|
261 |
ullist = UnorderedList() |
|
262 |
ullist.AddItem(Link(listinfo_url, _("Visit the list's info page"))) |
|
263 |
ullist.AddItem(Link(admin_url, _("Visit the list's admin page"))) |
|
264 |
ullist.AddItem(Link(create_url, _('Create another list'))) |
|
265 |
table.AddRow([ullist]) |
|
266 |
doc.AddItem(table) |
|
267 |
||
268 |
||
269 |
||
270 |
# Because the cgi module blows
|
|
271 |
class Dummy: |
|
272 |
def getvalue(self, name, default): |
|
273 |
return default |
|
274 |
dummy = Dummy() |
|
275 |
||
276 |
||
277 |
||
278 |
def request_creation(doc, cgidata=dummy, errmsg=None): |
|
279 |
# What virtual domain are we using?
|
|
280 |
hostname = Utils.get_domain() |
|
281 |
# Set up the document
|
|
282 |
title = _('Create a %(hostname)s Mailing List') |
|
283 |
doc.SetTitle(title) |
|
284 |
table = Table(border=0, width='100%') |
|
285 |
table.AddRow([Center(Bold(FontAttr(title, size='+1')))]) |
|
286 |
table.AddCellInfo(table.GetCurrentRowIndex(), 0, |
|
287 |
bgcolor=mm_cfg.WEB_HEADER_COLOR) |
|
288 |
# Add any error message
|
|
289 |
if errmsg: |
|
290 |
table.AddRow([Header(3, Bold( |
|
291 |
FontAttr(_('Error: '), color='#ff0000', size='+2').Format() + |
|
292 |
Italic(errmsg).Format()))]) |
|
293 |
table.AddRow([_("""You can create a new mailing list by entering the |
|
294 |
relevant information into the form below. The name of the mailing list
|
|
295 |
will be used as the primary address for posting messages to the list, so
|
|
296 |
it should be lowercased. You will not be able to change this once the
|
|
297 |
list is created.
|
|
298 |
||
299 |
<p>You also need to enter the email address of the initial list owner.
|
|
300 |
Once the list is created, the list owner will be given notification, along
|
|
301 |
with the initial list password. The list owner will then be able to
|
|
302 |
modify the password and add or remove additional list owners.
|
|
303 |
||
304 |
<p>If you want Mailman to automatically generate the initial list admin
|
|
305 |
password, click on `Yes' in the autogenerate field below, and leave the
|
|
306 |
initial list password fields empty.
|
|
307 |
||
308 |
<p>You must have the proper authorization to create new mailing lists.
|
|
309 |
Each site should have a <em>list creator's</em> password, which you can
|
|
310 |
enter in the field at the bottom. Note that the site administrator's
|
|
311 |
password can also be used for authentication.
|
|
312 |
""")]) |
|
313 |
# Build the form for the necessary input
|
|
314 |
GREY = mm_cfg.WEB_ADMINITEM_COLOR |
|
315 |
form = Form(Utils.ScriptURL('create')) |
|
316 |
ftable = Table(border=0, cols='2', width='100%', |
|
317 |
cellspacing=3, cellpadding=4) |
|
318 |
||
319 |
ftable.AddRow([Center(Italic(_('List Identity')))]) |
|
320 |
ftable.AddCellInfo(ftable.GetCurrentRowIndex(), 0, colspan=2) |
|
321 |
||
128
by bwarsaw
process_request(), request_creation(): Close cross-site scripting |
322 |
safelistname = Utils.websafe(cgidata.getvalue('listname', '')) |
1
by
This commit was manufactured by cvs2svn to create branch |
323 |
ftable.AddRow([Label(_('Name of list:')), |
128
by bwarsaw
process_request(), request_creation(): Close cross-site scripting |
324 |
TextBox('listname', safelistname)]) |
1
by
This commit was manufactured by cvs2svn to create branch |
325 |
ftable.AddCellInfo(ftable.GetCurrentRowIndex(), 0, bgcolor=GREY) |
326 |
ftable.AddCellInfo(ftable.GetCurrentRowIndex(), 1, bgcolor=GREY) |
|
327 |
||
128
by bwarsaw
process_request(), request_creation(): Close cross-site scripting |
328 |
safeowner = Utils.websafe(cgidata.getvalue('owner', '')) |
1
by
This commit was manufactured by cvs2svn to create branch |
329 |
ftable.AddRow([Label(_('Initial list owner address:')), |
128
by bwarsaw
process_request(), request_creation(): Close cross-site scripting |
330 |
TextBox('owner', safeowner)]) |
1
by
This commit was manufactured by cvs2svn to create branch |
331 |
ftable.AddCellInfo(ftable.GetCurrentRowIndex(), 0, bgcolor=GREY) |
332 |
ftable.AddCellInfo(ftable.GetCurrentRowIndex(), 1, bgcolor=GREY) |
|
333 |
||
334 |
try: |
|
335 |
autogen = int(cgidata.getvalue('autogen', '0')) |
|
336 |
except ValueError: |
|
337 |
autogen = 0 |
|
338 |
ftable.AddRow([Label(_('Auto-generate initial list password?')), |
|
339 |
RadioButtonArray('autogen', (_('No'), _('Yes')), |
|
340 |
checked=autogen, |
|
341 |
values=(0, 1))]) |
|
342 |
ftable.AddCellInfo(ftable.GetCurrentRowIndex(), 0, bgcolor=GREY) |
|
343 |
ftable.AddCellInfo(ftable.GetCurrentRowIndex(), 1, bgcolor=GREY) |
|
344 |
||
128
by bwarsaw
process_request(), request_creation(): Close cross-site scripting |
345 |
safepasswd = Utils.websafe(cgidata.getvalue('password', '')) |
1
by
This commit was manufactured by cvs2svn to create branch |
346 |
ftable.AddRow([Label(_('Initial list password:')), |
128
by bwarsaw
process_request(), request_creation(): Close cross-site scripting |
347 |
PasswordBox('password', safepasswd)]) |
1
by
This commit was manufactured by cvs2svn to create branch |
348 |
ftable.AddCellInfo(ftable.GetCurrentRowIndex(), 0, bgcolor=GREY) |
349 |
ftable.AddCellInfo(ftable.GetCurrentRowIndex(), 1, bgcolor=GREY) |
|
350 |
||
128
by bwarsaw
process_request(), request_creation(): Close cross-site scripting |
351 |
safeconfirm = Utils.websafe(cgidata.getvalue('confirm', '')) |
1
by
This commit was manufactured by cvs2svn to create branch |
352 |
ftable.AddRow([Label(_('Confirm initial password:')), |
128
by bwarsaw
process_request(), request_creation(): Close cross-site scripting |
353 |
PasswordBox('confirm', safeconfirm)]) |
1
by
This commit was manufactured by cvs2svn to create branch |
354 |
ftable.AddCellInfo(ftable.GetCurrentRowIndex(), 0, bgcolor=GREY) |
355 |
ftable.AddCellInfo(ftable.GetCurrentRowIndex(), 1, bgcolor=GREY) |
|
356 |
||
357 |
try: |
|
358 |
notify = int(cgidata.getvalue('notify', '1')) |
|
359 |
except ValueError: |
|
360 |
notify = 1 |
|
361 |
||
362 |
ftable.AddRow([Center(Italic(_('List Characteristics')))]) |
|
363 |
ftable.AddCellInfo(ftable.GetCurrentRowIndex(), 0, colspan=2) |
|
364 |
||
365 |
ftable.AddRow([ |
|
366 |
Label(_("""Should new members be quarantined before they |
|
367 |
are allowed to post unmoderated to this list? Answer <em>Yes</em> to hold
|
|
368 |
new member postings for moderator approval by default.""")), |
|
369 |
RadioButtonArray('moderate', (_('No'), _('Yes')), |
|
370 |
checked=mm_cfg.DEFAULT_DEFAULT_MEMBER_MODERATION, |
|
371 |
values=(0,1))]) |
|
372 |
ftable.AddCellInfo(ftable.GetCurrentRowIndex(), 0, bgcolor=GREY) |
|
373 |
ftable.AddCellInfo(ftable.GetCurrentRowIndex(), 1, bgcolor=GREY) |
|
374 |
# Create the table of initially supported languages, sorted on the long
|
|
375 |
# name of the language.
|
|
376 |
revmap = {} |
|
377 |
for key, (name, charset) in mm_cfg.LC_DESCRIPTIONS.items(): |
|
378 |
revmap[_(name)] = key |
|
379 |
langnames = revmap.keys() |
|
380 |
langnames.sort() |
|
381 |
langs = [] |
|
382 |
for name in langnames: |
|
383 |
langs.append(revmap[name]) |
|
384 |
try: |
|
385 |
langi = langs.index(mm_cfg.DEFAULT_SERVER_LANGUAGE) |
|
386 |
except ValueError: |
|
387 |
# Someone must have deleted the servers's preferred language. Could
|
|
388 |
# be other trouble lurking!
|
|
389 |
langi = 0 |
|
390 |
# BAW: we should preserve the list of checked languages across form
|
|
391 |
# invocations.
|
|
392 |
checked = [0] * len(langs) |
|
393 |
checked[langi] = 1 |
|
394 |
deflang = _(Utils.GetLanguageDescr(mm_cfg.DEFAULT_SERVER_LANGUAGE)) |
|
395 |
ftable.AddRow([Label(_( |
|
396 |
'''Initial list of supported languages. <p>Note that if you do not
|
|
397 |
select at least one initial language, the list will use the server
|
|
398 |
default language of %(deflang)s''')), |
|
399 |
CheckBoxArray('langs', |
|
400 |
[_(Utils.GetLanguageDescr(L)) for L in langs], |
|
401 |
checked=checked, |
|
402 |
values=langs)]) |
|
403 |
ftable.AddCellInfo(ftable.GetCurrentRowIndex(), 0, bgcolor=GREY) |
|
404 |
ftable.AddCellInfo(ftable.GetCurrentRowIndex(), 1, bgcolor=GREY) |
|
405 |
||
406 |
ftable.AddRow([Label(_('Send "list created" email to list owner?')), |
|
407 |
RadioButtonArray('notify', (_('No'), _('Yes')), |
|
408 |
checked=notify, |
|
409 |
values=(0, 1))]) |
|
410 |
ftable.AddCellInfo(ftable.GetCurrentRowIndex(), 0, bgcolor=GREY) |
|
411 |
ftable.AddCellInfo(ftable.GetCurrentRowIndex(), 1, bgcolor=GREY) |
|
412 |
||
413 |
ftable.AddRow(['<hr>']) |
|
414 |
ftable.AddCellInfo(ftable.GetCurrentRowIndex(), 0, colspan=2) |
|
415 |
ftable.AddRow([Label(_("List creator's (authentication) password:")), |
|
416 |
PasswordBox('auth')]) |
|
417 |
ftable.AddCellInfo(ftable.GetCurrentRowIndex(), 0, bgcolor=GREY) |
|
418 |
ftable.AddCellInfo(ftable.GetCurrentRowIndex(), 1, bgcolor=GREY) |
|
419 |
||
420 |
ftable.AddRow([Center(SubmitButton('doit', _('Create List'))), |
|
421 |
Center(SubmitButton('clear', _('Clear Form')))]) |
|
422 |
form.AddItem(ftable) |
|
423 |
table.AddRow([form]) |
|
424 |
doc.AddItem(table) |