1779
by Mark Sapiro
Bump copyright dates. |
1 |
# Copyright (C) 1998-2018 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.
|
|
139
by bwarsaw
FormatUsers(): The user portion of the link should honor the setting |
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.
|
|
139
by bwarsaw
FormatUsers(): The user portion of the link should honor the setting |
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
|
139
by bwarsaw
FormatUsers(): The user portion of the link should honor the setting |
14 |
# along with this program; if not, write to the Free Software
|
930
by bwarsaw
CVE-2006-3636. Fixes for various cross-site scripting issues. Discovery by |
15 |
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
|
16 |
# USA.
|
|
1
by
This commit was manufactured by cvs2svn to create branch |
17 |
|
18 |
||
19 |
"""Routines for presentation of list-specific HTML text."""
|
|
20 |
||
21 |
import time |
|
22 |
import re |
|
23 |
||
24 |
from Mailman import mm_cfg |
|
25 |
from Mailman import Utils |
|
26 |
from Mailman import MemberAdaptor |
|
27 |
from Mailman.htmlformat import * |
|
28 |
||
29 |
from Mailman.i18n import _ |
|
30 |
||
1668
by Mark Sapiro
Fixes for CVE-2016-6893 and more. |
31 |
from Mailman.CSRFcheck import csrf_token |
32 |
||
1
by
This commit was manufactured by cvs2svn to create branch |
33 |
|
34 |
EMPTYSTRING = '' |
|
35 |
BR = '<br>' |
|
36 |
NL = '\n' |
|
37 |
COMMASPACE = ', ' |
|
38 |
||
39 |
||
40 |
||
41 |
class HTMLFormatter: |
|
42 |
def GetMailmanFooter(self): |
|
1705
by Mark Sapiro
Display only the list-owner address in the 'list run by' footer. |
43 |
ownertext = Utils.ObscureEmail(self.GetOwnerEmail(), 1) |
1
by
This commit was manufactured by cvs2svn to create branch |
44 |
# Remove the .Format() when htmlformat conversion is done.
|
45 |
realname = self.real_name |
|
46 |
hostname = self.host_name |
|
47 |
listinfo_link = Link(self.GetScriptURL('listinfo'), realname).Format() |
|
48 |
owner_link = Link('mailto:' + self.GetOwnerEmail(), ownertext).Format() |
|
49 |
innertext = _('%(listinfo_link)s list run by %(owner_link)s') |
|
50 |
return Container( |
|
51 |
'<hr>', |
|
52 |
Address( |
|
139
by bwarsaw
FormatUsers(): The user portion of the link should honor the setting |
53 |
Container( |
1
by
This commit was manufactured by cvs2svn to create branch |
54 |
innertext, |
55 |
'<br>', |
|
56 |
Link(self.GetScriptURL('admin'), |
|
57 |
_('%(realname)s administrative interface')), |
|
58 |
_(' (requires authorization)'), |
|
59 |
'<br>', |
|
60 |
Link(Utils.ScriptURL('listinfo'), |
|
61 |
_('Overview of all %(hostname)s mailing lists')), |
|
62 |
'<p>', MailmanLogo()))).Format() |
|
63 |
||
972
by msapiro
- CGI/admin.py |
64 |
def FormatUsers(self, digest, lang=None, list_hidden=False): |
1
by
This commit was manufactured by cvs2svn to create branch |
65 |
if lang is None: |
66 |
lang = self.preferred_language |
|
67 |
conceal_sub = mm_cfg.ConcealSubscription |
|
68 |
people = [] |
|
69 |
if digest: |
|
1042
by Mark Sapiro
HTMLFormatter.py - list_hidden didn't work for digest members. Fixed. |
70 |
members = self.getDigestMemberKeys() |
1
by
This commit was manufactured by cvs2svn to create branch |
71 |
else: |
72 |
members = self.getRegularMemberKeys() |
|
1042
by Mark Sapiro
HTMLFormatter.py - list_hidden didn't work for digest members. Fixed. |
73 |
for m in members: |
74 |
if list_hidden or not self.getMemberOption(m, conceal_sub): |
|
75 |
people.append(m) |
|
76 |
num_concealed = len(members) - len(people) |
|
1
by
This commit was manufactured by cvs2svn to create branch |
77 |
if num_concealed == 1: |
78 |
concealed = _('<em>(1 private member not shown)</em>') |
|
79 |
elif num_concealed > 1: |
|
80 |
concealed = _( |
|
81 |
'<em>(%(num_concealed)d private members not shown)</em>') |
|
82 |
else: |
|
83 |
concealed = '' |
|
84 |
items = [] |
|
85 |
people.sort() |
|
139
by bwarsaw
FormatUsers(): The user portion of the link should honor the setting |
86 |
obscure = self.obscure_addresses |
1
by
This commit was manufactured by cvs2svn to create branch |
87 |
for person in people: |
88 |
id = Utils.ObscureEmail(person) |
|
139
by bwarsaw
FormatUsers(): The user portion of the link should honor the setting |
89 |
url = self.GetOptionsURL(person, obscure=obscure) |
1721
by Mark Sapiro
Show case preserved emails in the roster. |
90 |
person = self.getMemberCPAddress(person) |
139
by bwarsaw
FormatUsers(): The user portion of the link should honor the setting |
91 |
if obscure: |
1
by
This commit was manufactured by cvs2svn to create branch |
92 |
showing = Utils.ObscureEmail(person, for_text=1) |
93 |
else: |
|
94 |
showing = person |
|
1516
by Mark Sapiro
A number of changes from the unofficial 2.2 branch have been backported to |
95 |
realname = Utils.uncanonstr(self.getMemberName(person), lang) |
1541
by Mark Sapiro
Because of privacy concerns with the 2.2 backport adding real name to |
96 |
if realname and mm_cfg.ROSTER_DISPLAY_REALNAME: |
1516
by Mark Sapiro
A number of changes from the unofficial 2.2 branch have been backported to |
97 |
showing += " (%s)" % Utils.websafe(realname) |
1
by
This commit was manufactured by cvs2svn to create branch |
98 |
got = Link(url, showing) |
99 |
if self.getDeliveryStatus(person) <> MemberAdaptor.ENABLED: |
|
100 |
got = Italic('(', got, ')') |
|
101 |
items.append(got) |
|
102 |
# Just return the .Format() so this works until I finish
|
|
103 |
# converting everything to htmlformat...
|
|
104 |
return concealed + UnorderedList(*tuple(items)).Format() |
|
105 |
||
106 |
def FormatOptionButton(self, option, value, user): |
|
107 |
if option == mm_cfg.DisableDelivery: |
|
108 |
optval = self.getDeliveryStatus(user) <> MemberAdaptor.ENABLED |
|
109 |
else: |
|
110 |
optval = self.getMemberOption(user, option) |
|
111 |
if optval == value: |
|
112 |
checked = ' CHECKED' |
|
113 |
else: |
|
114 |
checked = '' |
|
115 |
name = {mm_cfg.DontReceiveOwnPosts : 'dontreceive', |
|
116 |
mm_cfg.DisableDelivery : 'disablemail', |
|
117 |
mm_cfg.DisableMime : 'mime', |
|
118 |
mm_cfg.AcknowledgePosts : 'ackposts', |
|
119 |
mm_cfg.Digests : 'digest', |
|
120 |
mm_cfg.ConcealSubscription : 'conceal', |
|
121 |
mm_cfg.SuppressPasswordReminder : 'remind', |
|
122 |
mm_cfg.ReceiveNonmatchingTopics : 'rcvtopic', |
|
123 |
mm_cfg.DontReceiveDuplicates : 'nodupes', |
|
124 |
}[option] |
|
125 |
return '<input type=radio name="%s" value="%d"%s>' % ( |
|
126 |
name, value, checked) |
|
127 |
||
128 |
def FormatDigestButton(self): |
|
129 |
if self.digest_is_default: |
|
130 |
checked = ' CHECKED' |
|
131 |
else: |
|
132 |
checked = '' |
|
133 |
return '<input type=radio name="digest" value="1"%s>' % checked |
|
134 |
||
135 |
def FormatDisabledNotice(self, user): |
|
136 |
status = self.getDeliveryStatus(user) |
|
137 |
reason = None |
|
138 |
info = self.getBounceInfo(user) |
|
139 |
if status == MemberAdaptor.BYUSER: |
|
140 |
reason = _('; it was disabled by you') |
|
141 |
elif status == MemberAdaptor.BYADMIN: |
|
142 |
reason = _('; it was disabled by the list administrator') |
|
143 |
elif status == MemberAdaptor.BYBOUNCE: |
|
144 |
date = time.strftime('%d-%b-%Y', |
|
145 |
time.localtime(Utils.midnight(info.date))) |
|
146 |
reason = _('''; it was disabled due to excessive bounces. The |
|
147 |
last bounce was received on %(date)s''') |
|
148 |
elif status == MemberAdaptor.UNKNOWN: |
|
149 |
reason = _('; it was disabled for unknown reasons') |
|
150 |
if reason: |
|
151 |
note = FontSize('+1', _( |
|
152 |
'Note: your list delivery is currently disabled%(reason)s.' |
|
153 |
)).Format() |
|
154 |
link = Link('#disable', _('Mail delivery')).Format() |
|
155 |
mailto = Link('mailto:' + self.GetOwnerEmail(), |
|
156 |
_('the list administrator')).Format() |
|
157 |
return _('''<p>%(note)s |
|
158 |
||
159 |
<p>You may have disabled list delivery intentionally,
|
|
160 |
or it may have been triggered by bounces from your email
|
|
161 |
address. In either case, to re-enable delivery, change the
|
|
162 |
%(link)s option below. Contact %(mailto)s if you have any |
|
163 |
questions or need assistance.''') |
|
164 |
elif info and info.score > 0: |
|
165 |
# Provide information about their current bounce score. We know
|
|
166 |
# their membership is currently enabled.
|
|
167 |
score = info.score |
|
168 |
total = self.bounce_score_threshold |
|
169 |
return _('''<p>We have received some recent bounces from your |
|
170 |
address. Your current <em>bounce score</em> is %(score)s out of a |
|
171 |
maximum of %(total)s. Please double check that your subscribed |
|
172 |
address is correct and that there are no problems with delivery to
|
|
173 |
this address. Your bounce score will be automatically reset if
|
|
174 |
the problems are corrected soon.''') |
|
175 |
else: |
|
176 |
return '' |
|
177 |
||
178 |
def FormatUmbrellaNotice(self, user, type): |
|
179 |
addr = self.GetMemberAdminEmail(user) |
|
180 |
if self.umbrella_list: |
|
181 |
return _("(Note - you are subscribing to a list of mailing lists, " |
|
182 |
"so the %(type)s notice will be sent to the admin address" |
|
183 |
" for your membership, %(addr)s.)<p>") |
|
184 |
else: |
|
185 |
return "" |
|
186 |
||
187 |
def FormatSubscriptionMsg(self): |
|
188 |
msg = '' |
|
189 |
also = '' |
|
190 |
if self.subscribe_policy == 1: |
|
191 |
msg += _('''You will be sent email requesting confirmation, to |
|
192 |
prevent others from gratuitously subscribing you.''') |
|
193 |
elif self.subscribe_policy == 2: |
|
194 |
msg += _("""This is a closed list, which means your subscription |
|
195 |
will be held for approval. You will be notified of the list
|
|
196 |
moderator's decision by email.""") |
|
197 |
also = _('also ') |
|
198 |
elif self.subscribe_policy == 3: |
|
199 |
msg += _("""You will be sent email requesting confirmation, to |
|
200 |
prevent others from gratuitously subscribing you. Once
|
|
201 |
confirmation is received, your request will be held for approval
|
|
202 |
by the list moderator. You will be notified of the moderator's
|
|
203 |
decision by email.""") |
|
204 |
also = _("also ") |
|
205 |
if msg: |
|
206 |
msg += ' ' |
|
207 |
if self.private_roster == 1: |
|
208 |
msg += _('''This is %(also)sa private list, which means that the |
|
209 |
list of members is not available to non-members.''') |
|
210 |
elif self.private_roster: |
|
211 |
msg += _('''This is %(also)sa hidden list, which means that the |
|
212 |
list of members is available only to the list administrator.''') |
|
213 |
else: |
|
214 |
msg += _('''This is %(also)sa public list, which means that the |
|
215 |
list of members list is available to everyone.''') |
|
216 |
if self.obscure_addresses: |
|
217 |
msg += _(''' (but we obscure the addresses so they are not |
|
218 |
easily recognizable by spammers).''') |
|
219 |
||
220 |
if self.umbrella_list: |
|
221 |
sfx = self.umbrella_member_suffix |
|
222 |
msg += _("""<p>(Note that this is an umbrella list, intended to |
|
223 |
have only other mailing lists as members. Among other things,
|
|
224 |
this means that your confirmation request will be sent to the
|
|
225 |
`%(sfx)s' account for your address.)""") |
|
226 |
return msg |
|
227 |
||
228 |
def FormatUndigestButton(self): |
|
229 |
if self.digest_is_default: |
|
230 |
checked = '' |
|
231 |
else: |
|
232 |
checked = ' CHECKED' |
|
233 |
return '<input type=radio name="digest" value="0"%s>' % checked |
|
234 |
||
235 |
def FormatMimeDigestsButton(self): |
|
236 |
if self.mime_is_default_digest: |
|
237 |
checked = ' CHECKED' |
|
238 |
else: |
|
239 |
checked = '' |
|
240 |
return '<input type=radio name="mime" value="1"%s>' % checked |
|
241 |
||
242 |
def FormatPlainDigestsButton(self): |
|
243 |
if self.mime_is_default_digest: |
|
244 |
checked = '' |
|
245 |
else: |
|
246 |
checked = ' CHECKED' |
|
247 |
return '<input type=radio name="plain" value="1"%s>' % checked |
|
248 |
||
249 |
def FormatEditingOption(self, lang): |
|
250 |
if self.private_roster == 0: |
|
251 |
either = _('<b><i>either</i></b> ') |
|
252 |
else: |
|
253 |
either = '' |
|
254 |
realname = self.real_name |
|
255 |
||
256 |
text = (_('''To unsubscribe from %(realname)s, get a password reminder, |
|
257 |
or change your subscription options %(either)senter your subscription |
|
258 |
email address:
|
|
259 |
<p><center> ''') |
|
260 |
+ TextBox('email', size=30).Format() |
|
261 |
+ ' ' |
|
262 |
+ SubmitButton('UserOptions', |
|
263 |
_('Unsubscribe or edit options')).Format() |
|
264 |
+ Hidden('language', lang).Format() |
|
265 |
+ '</center>') |
|
266 |
if self.private_roster == 0: |
|
267 |
text += _('''<p>... <b><i>or</i></b> select your entry from |
|
268 |
the subscribers list (see above).''') |
|
269 |
text += _(''' If you leave the field blank, you will be prompted for |
|
270 |
your email address''') |
|
271 |
return text |
|
139
by bwarsaw
FormatUsers(): The user portion of the link should honor the setting |
272 |
|
1
by
This commit was manufactured by cvs2svn to create branch |
273 |
def RestrictedListMessage(self, which, restriction): |
274 |
if not restriction: |
|
275 |
return '' |
|
276 |
elif restriction == 1: |
|
277 |
return _( |
|
278 |
'''(<i>%(which)s is only available to the list
|
|
279 |
members.</i>)''') |
|
280 |
else: |
|
281 |
return _('''(<i>%(which)s is only available to the list |
|
282 |
administrator.</i>)''') |
|
283 |
||
284 |
def FormatRosterOptionForUser(self, lang): |
|
285 |
return self.RosterOption(lang).Format() |
|
286 |
||
287 |
def RosterOption(self, lang): |
|
288 |
container = Container() |
|
289 |
container.AddItem(Hidden('language', lang)) |
|
290 |
if not self.private_roster: |
|
291 |
container.AddItem(_("Click here for the list of ") |
|
292 |
+ self.real_name |
|
293 |
+ _(" subscribers: ")) |
|
294 |
container.AddItem(SubmitButton('SubscriberRoster', |
|
295 |
_("Visit Subscriber list"))) |
|
296 |
else: |
|
297 |
if self.private_roster == 1: |
|
298 |
only = _('members') |
|
299 |
whom = _('Address:') |
|
300 |
else: |
|
301 |
only = _('the list administrator') |
|
302 |
whom = _('Admin address:') |
|
303 |
# Solicit the user and password.
|
|
304 |
container.AddItem( |
|
305 |
self.RestrictedListMessage(_('The subscribers list'), |
|
306 |
self.private_roster) |
|
307 |
+ _(" <p>Enter your ") |
|
308 |
+ whom[:-1].lower() |
|
309 |
+ _(" and password to visit" |
|
310 |
" the subscribers list: <p><center> ") |
|
311 |
+ whom |
|
312 |
+ " ") |
|
313 |
container.AddItem(self.FormatBox('roster-email')) |
|
314 |
container.AddItem(_("Password: ") |
|
315 |
+ self.FormatSecureBox('roster-pw') |
|
316 |
+ " ") |
|
317 |
container.AddItem(SubmitButton('SubscriberRoster', |
|
318 |
_('Visit Subscriber List'))) |
|
319 |
container.AddItem("</center>") |
|
320 |
return container |
|
321 |
||
1668
by Mark Sapiro
Fixes for CVE-2016-6893 and more. |
322 |
def FormatFormStart(self, name, extra='', |
323 |
mlist=None, contexts=None, user=None): |
|
1
by
This commit was manufactured by cvs2svn to create branch |
324 |
base_url = self.GetScriptURL(name) |
325 |
if extra: |
|
326 |
full_url = "%s/%s" % (base_url, extra) |
|
327 |
else: |
|
328 |
full_url = base_url |
|
1668
by Mark Sapiro
Fixes for CVE-2016-6893 and more. |
329 |
if mlist: |
330 |
return ("""<form method="POST" action="%s"> |
|
331 |
<input type="hidden" name="csrf_token" value="%s">""" |
|
332 |
% (full_url, csrf_token(mlist, contexts, user))) |
|
1
by
This commit was manufactured by cvs2svn to create branch |
333 |
return ('<FORM Method=POST ACTION="%s">' % full_url) |
334 |
||
335 |
def FormatArchiveAnchor(self): |
|
336 |
return '<a href="%s">' % self.GetBaseArchiveURL() |
|
337 |
||
338 |
def FormatFormEnd(self): |
|
339 |
return '</FORM>' |
|
340 |
||
341 |
def FormatBox(self, name, size=20, value=''): |
|
930
by bwarsaw
CVE-2006-3636. Fixes for various cross-site scripting issues. Discovery by |
342 |
if isinstance(value, str): |
343 |
safevalue = Utils.websafe(value) |
|
344 |
else: |
|
345 |
safevalue = value |
|
1
by
This commit was manufactured by cvs2svn to create branch |
346 |
return '<INPUT type="Text" name="%s" size="%d" value="%s">' % ( |
930
by bwarsaw
CVE-2006-3636. Fixes for various cross-site scripting issues. Discovery by |
347 |
name, size, safevalue) |
1
by
This commit was manufactured by cvs2svn to create branch |
348 |
|
349 |
def FormatSecureBox(self, name): |
|
350 |
return '<INPUT type="Password" name="%s" size="15">' % name |
|
351 |
||
352 |
def FormatButton(self, name, text='Submit'): |
|
353 |
return '<INPUT type="Submit" name="%s" value="%s">' % (name, text) |
|
354 |
||
355 |
def FormatReminder(self, lang): |
|
356 |
if self.send_reminders: |
|
357 |
return _('Once a month, your password will be emailed to you as' |
|
358 |
' a reminder.') |
|
359 |
return '' |
|
360 |
||
361 |
def ParseTags(self, template, replacements, lang=None): |
|
362 |
if lang is None: |
|
363 |
charset = 'us-ascii' |
|
364 |
else: |
|
365 |
charset = Utils.GetCharSet(lang) |
|
366 |
text = Utils.maketext(template, raw=1, lang=lang, mlist=self) |
|
367 |
parts = re.split('(</?[Mm][Mm]-[^>]*>)', text) |
|
368 |
i = 1 |
|
369 |
while i < len(parts): |
|
370 |
tag = parts[i].lower() |
|
371 |
if replacements.has_key(tag): |
|
372 |
repl = replacements[tag] |
|
373 |
if isinstance(repl, type(u'')): |
|
374 |
repl = repl.encode(charset, 'replace') |
|
375 |
parts[i] = repl |
|
376 |
else: |
|
377 |
parts[i] = '' |
|
378 |
i = i + 2 |
|
379 |
return EMPTYSTRING.join(parts) |
|
380 |
||
381 |
# This needs to wait until after the list is inited, so let's build it
|
|
382 |
# when it's needed only.
|
|
383 |
def GetStandardReplacements(self, lang=None): |
|
384 |
dmember_len = len(self.getDigestMemberKeys()) |
|
385 |
member_len = len(self.getRegularMemberKeys()) |
|
386 |
# If only one language is enabled for this mailing list, omit the
|
|
387 |
# language choice buttons.
|
|
388 |
if len(self.GetAvailableLanguages()) == 1: |
|
389 |
listlangs = _(Utils.GetLanguageDescr(self.preferred_language)) |
|
390 |
else: |
|
391 |
listlangs = self.GetLangSelectBox(lang).Format() |
|
1781.1.2
by Yasuhito FUTATSUKI at POEM
* apply Utils.websafe() to description string in admin.py |
392 |
if lang: |
393 |
cset = Utils.GetCharSet(lang) or 'us-ascii' |
|
394 |
else: |
|
395 |
cset = Utils.GetCharSet(self.preferred_language) or 'us-ascii' |
|
139
by bwarsaw
FormatUsers(): The user portion of the link should honor the setting |
396 |
d = { |
1
by
This commit was manufactured by cvs2svn to create branch |
397 |
'<mm-mailman-footer>' : self.GetMailmanFooter(), |
398 |
'<mm-list-name>' : self.real_name, |
|
399 |
'<mm-email-user>' : self._internal_name, |
|
1781.1.2
by Yasuhito FUTATSUKI at POEM
* apply Utils.websafe() to description string in admin.py |
400 |
'<mm-list-description>' : |
401 |
Utils.websafe(self.GetDescription(cset)), |
|
1262
by Mark Sapiro
Two potential XSS vulnerabilities have been identified and fixed. |
402 |
'<mm-list-info>' : |
403 |
'<!---->' + BR.join(self.info.split(NL)) + '<!---->', |
|
1
by
This commit was manufactured by cvs2svn to create branch |
404 |
'<mm-form-end>' : self.FormatFormEnd(), |
405 |
'<mm-archive>' : self.FormatArchiveAnchor(), |
|
406 |
'</mm-archive>' : '</a>', |
|
407 |
'<mm-list-subscription-msg>' : self.FormatSubscriptionMsg(), |
|
408 |
'<mm-restricted-list-message>' : \ |
|
409 |
self.RestrictedListMessage(_('The current archive'), |
|
410 |
self.archive_private), |
|
411 |
'<mm-num-reg-users>' : `member_len`, |
|
412 |
'<mm-num-digesters>' : `dmember_len`, |
|
413 |
'<mm-num-members>' : (`member_len + dmember_len`), |
|
414 |
'<mm-posting-addr>' : '%s' % self.GetListEmail(), |
|
415 |
'<mm-request-addr>' : '%s' % self.GetRequestEmail(), |
|
416 |
'<mm-owner>' : self.GetOwnerEmail(), |
|
417 |
'<mm-reminder>' : self.FormatReminder(self.preferred_language), |
|
418 |
'<mm-host>' : self.host_name, |
|
419 |
'<mm-list-langs>' : listlangs, |
|
420 |
}
|
|
421 |
if mm_cfg.IMAGE_LOGOS: |
|
422 |
d['<mm-favicon>'] = mm_cfg.IMAGE_LOGOS + mm_cfg.SHORTCUT_ICON |
|
423 |
return d |
|
424 |
||
972
by msapiro
- CGI/admin.py |
425 |
def GetAllReplacements(self, lang=None, list_hidden=False): |
1
by
This commit was manufactured by cvs2svn to create branch |
426 |
"""
|
427 |
returns standard replaces plus formatted user lists in
|
|
428 |
a dict just like GetStandardReplacements.
|
|
429 |
"""
|
|
430 |
if lang is None: |
|
431 |
lang = self.preferred_language |
|
432 |
d = self.GetStandardReplacements(lang) |
|
972
by msapiro
- CGI/admin.py |
433 |
d.update({"<mm-regular-users>": self.FormatUsers(0, lang, list_hidden), |
434 |
"<mm-digest-users>": self.FormatUsers(1, lang, list_hidden)}) |
|
1
by
This commit was manufactured by cvs2svn to create branch |
435 |
return d |
436 |
||
437 |
def GetLangSelectBox(self, lang=None, varname='language'): |
|
438 |
if lang is None: |
|
439 |
lang = self.preferred_language |
|
440 |
# Figure out the available languages
|
|
441 |
values = self.GetAvailableLanguages() |
|
442 |
legend = map(_, map(Utils.GetLanguageDescr, values)) |
|
443 |
try: |
|
444 |
selected = values.index(lang) |
|
445 |
except ValueError: |
|
446 |
try: |
|
447 |
selected = values.index(self.preferred_language) |
|
448 |
except ValueError: |
|
449 |
selected = mm_cfg.DEFAULT_SERVER_LANGUAGE |
|
450 |
# Return the widget
|
|
451 |
return SelectOptions(varname, values, legend, selected) |