summaryrefslogtreecommitdiff
path: root/mailman/web/Gui
diff options
context:
space:
mode:
Diffstat (limited to 'mailman/web/Gui')
-rw-r--r--mailman/web/Gui/Archive.py45
-rw-r--r--mailman/web/Gui/Autoresponse.py99
-rw-r--r--mailman/web/Gui/Bounce.py195
-rw-r--r--mailman/web/Gui/ContentFilter.py199
-rw-r--r--mailman/web/Gui/Digest.py161
-rw-r--r--mailman/web/Gui/GUIBase.py209
-rw-r--r--mailman/web/Gui/General.py464
-rw-r--r--mailman/web/Gui/Language.py128
-rw-r--r--mailman/web/Gui/Membership.py34
-rw-r--r--mailman/web/Gui/NonDigest.py158
-rw-r--r--mailman/web/Gui/Passwords.py31
-rw-r--r--mailman/web/Gui/Privacy.py537
-rw-r--r--mailman/web/Gui/Topics.py162
-rw-r--r--mailman/web/Gui/Usenet.py140
-rw-r--r--mailman/web/Gui/__init__.py33
15 files changed, 0 insertions, 2595 deletions
diff --git a/mailman/web/Gui/Archive.py b/mailman/web/Gui/Archive.py
deleted file mode 100644
index 4090e74e9..000000000
--- a/mailman/web/Gui/Archive.py
+++ /dev/null
@@ -1,45 +0,0 @@
-# Copyright (C) 2001-2009 by the Free Software Foundation, Inc.
-#
-# This file is part of GNU Mailman.
-#
-# GNU Mailman 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 3 of the License, or (at your option)
-# any later version.
-#
-# GNU Mailman 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
-# GNU Mailman. If not, see <http://www.gnu.org/licenses/>.
-
-from Mailman.Gui.GUIBase import GUIBase
-from Mailman.configuration import config
-from Mailman.i18n import _
-
-
-
-class Archive(GUIBase):
- def GetConfigCategory(self):
- return 'archive', _('Archiving Options')
-
- def GetConfigInfo(self, mlist, category, subcat=None):
- if category <> 'archive':
- return None
- return [
- _("List traffic archival policies."),
-
- ('archive', config.Toggle, (_('No'), _('Yes')), 0,
- _('Archive messages?')),
-
- ('archive_private', config.Radio, (_('public'), _('private')), 0,
- _('Is archive file source for public or private archival?')),
-
- ('archive_volume_frequency', config.Radio,
- (_('Yearly'), _('Monthly'), _('Quarterly'),
- _('Weekly'), _('Daily')),
- 0,
- _('How often should a new archive volume be started?')),
- ]
diff --git a/mailman/web/Gui/Autoresponse.py b/mailman/web/Gui/Autoresponse.py
deleted file mode 100644
index 72ef42cad..000000000
--- a/mailman/web/Gui/Autoresponse.py
+++ /dev/null
@@ -1,99 +0,0 @@
-# Copyright (C) 2001-2009 by the Free Software Foundation, Inc.
-#
-# This file is part of GNU Mailman.
-#
-# GNU Mailman 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 3 of the License, or (at your option)
-# any later version.
-#
-# GNU Mailman 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
-# GNU Mailman. If not, see <http://www.gnu.org/licenses/>.
-
-"""Administrative GUI for the autoresponder."""
-
-from Mailman import Utils
-from Mailman.Gui.GUIBase import GUIBase
-from Mailman.configuration import config
-from Mailman.i18n import _
-
-# These are the allowable string substitution variables
-ALLOWEDS = ('listname', 'listurl', 'requestemail', 'adminemail', 'owneremail')
-
-
-
-class Autoresponse(GUIBase):
- def GetConfigCategory(self):
- return 'autoreply', _('Auto-responder')
-
- def GetConfigInfo(self, mlist, category, subcat=None):
- if category <> 'autoreply':
- return None
- WIDTH = config.TEXTFIELDWIDTH
-
- return [
- _("""\
-Auto-responder characteristics.<p>
-
-In the text fields below, string interpolation is performed with
-the following key/value substitutions:
-<p><ul>
- <li><b>listname</b> - <em>gets the name of the mailing list</em>
- <li><b>listurl</b> - <em>gets the list's listinfo URL</em>
- <li><b>requestemail</b> - <em>gets the list's -request address</em>
- <li><b>owneremail</b> - <em>gets the list's -owner address</em>
-</ul>
-
-<p>For each text field, you can either enter the text directly into the text
-box, or you can specify a file on your local system to upload as the text."""),
-
- ('autorespond_postings', config.Toggle, (_('No'), _('Yes')), 0,
- _('''Should Mailman send an auto-response to mailing list
- posters?''')),
-
- ('autoresponse_postings_text', config.FileUpload,
- (6, WIDTH), 0,
- _('Auto-response text to send to mailing list posters.')),
-
- ('autorespond_admin', config.Toggle, (_('No'), _('Yes')), 0,
- _('''Should Mailman send an auto-response to emails sent to the
- -owner address?''')),
-
- ('autoresponse_admin_text', config.FileUpload,
- (6, WIDTH), 0,
- _('Auto-response text to send to -owner emails.')),
-
- ('autorespond_requests', config.Radio,
- (_('No'), _('Yes, w/discard'), _('Yes, w/forward')), 0,
- _('''Should Mailman send an auto-response to emails sent to the
- -request address? If you choose yes, decide whether you want
- Mailman to discard the original email, or forward it on to the
- system as a normal mail command.''')),
-
- ('autoresponse_request_text', config.FileUpload,
- (6, WIDTH), 0,
- _('Auto-response text to send to -request emails.')),
-
- ('autoresponse_graceperiod', config.Number, 3, 0,
- _('''Number of days between auto-responses to either the mailing
- list or -request/-owner address from the same poster. Set to
- zero (or negative) for no grace period (i.e. auto-respond to
- every message).''')),
- ]
-
- def _setValue(self, mlist, property, val, doc):
- # Handle these specially because we may need to convert to/from
- # external $-string representation.
- if property in ('autoresponse_postings_text',
- 'autoresponse_admin_text',
- 'autoresponse_request_text'):
- val = self._convertString(mlist, property, ALLOWEDS, val, doc)
- if val is None:
- # There was a problem, so don't set it
- return
- GUIBase._setValue(self, mlist, property, val, doc)
diff --git a/mailman/web/Gui/Bounce.py b/mailman/web/Gui/Bounce.py
deleted file mode 100644
index a2f6f887a..000000000
--- a/mailman/web/Gui/Bounce.py
+++ /dev/null
@@ -1,195 +0,0 @@
-# Copyright (C) 2001-2009 by the Free Software Foundation, Inc.
-#
-# This file is part of GNU Mailman.
-#
-# GNU Mailman 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 3 of the License, or (at your option)
-# any later version.
-#
-# GNU Mailman 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
-# GNU Mailman. If not, see <http://www.gnu.org/licenses/>.
-
-from Mailman.Gui.GUIBase import GUIBase
-from Mailman.configuration import config
-from Mailman.i18n import _
-
-
-
-class Bounce(GUIBase):
- def GetConfigCategory(self):
- return 'bounce', _('Bounce processing')
-
- def GetConfigInfo(self, mlist, category, subcat=None):
- if category <> 'bounce':
- return None
- return [
- _("""These policies control the automatic bounce processing system
- in Mailman. Here's an overview of how it works.
-
- <p>When a bounce is received, Mailman tries to extract two pieces
- of information from the message: the address of the member the
- message was intended for, and the severity of the problem causing
- the bounce. The severity can be either <em>hard</em> or
- <em>soft</em> meaning either a fatal error occurred, or a
- transient error occurred. When in doubt, a hard severity is used.
-
- <p>If no member address can be extracted from the bounce, then the
- bounce is usually discarded. Otherwise, each member is assigned a
- <em>bounce score</em> and every time we encounter a bounce from
- this member we increment the score. Hard bounces increment by 1
- while soft bounces increment by 0.5. We only increment the bounce
- score once per day, so even if we receive ten hard bounces from a
- member per day, their score will increase by only 1 for that day.
-
- <p>When a member's bounce score is greater than the
- <a href="?VARHELP=bounce/bounce_score_threshold">bounce score
- threshold</a>, the subscription is disabled. Once disabled, the
- member will not receive any postings from the list until their
- membership is explicitly re-enabled (either by the list
- administrator or the user). However, they will receive occasional
- reminders that their membership has been disabled, and these
- reminders will include information about how to re-enable their
- membership.
-
- <p>You can control both the
- <a href="?VARHELP=bounce/bounce_you_are_disabled_warnings">number
- of reminders</a> the member will receive and the
- <a href="?VARHELP=bounce/bounce_you_are_disabled_warnings_interval"
- >frequency</a> with which these reminders are sent.
-
- <p>There is one other important configuration variable; after a
- certain period of time -- during which no bounces from the member
- are received -- the bounce information is
- <a href="?VARHELP=bounce/bounce_info_stale_after">considered
- stale</a> and discarded. Thus by adjusting this value, and the
- score threshold, you can control how quickly bouncing members are
- disabled. You should tune both of these to the frequency and
- traffic volume of your list."""),
-
- _('Bounce detection sensitivity'),
-
- ('bounce_processing', config.Toggle, (_('No'), _('Yes')), 0,
- _('Should Mailman perform automatic bounce processing?'),
- _("""By setting this value to <em>No</em>, you disable all
- automatic bounce processing for this list, however bounce
- messages will still be discarded so that the list administrator
- isn't inundated with them.""")),
-
- ('bounce_score_threshold', config.Number, 5, 0,
- _("""The maximum member bounce score before the member's
- subscription is disabled. This value can be a floating point
- number."""),
- _("""Each subscriber is assigned a bounce score, as a floating
- point number. Whenever Mailman receives a bounce from a list
- member, that member's score is incremented. Hard bounces (fatal
- errors) increase the score by 1, while soft bounces (temporary
- errors) increase the score by 0.5. Only one bounce per day
- counts against a member's score, so even if 10 bounces are
- received for a member on the same day, their score will increase
- by just 1.
-
- This variable describes the upper limit for a member's bounce
- score, above which they are automatically disabled, but not
- removed from the mailing list.""")),
-
- ('bounce_info_stale_after', config.Number, 5, 0,
- _("""The number of days after which a member's bounce information
- is discarded, if no new bounces have been received in the
- interim. This value must be an integer.""")),
-
- ('bounce_you_are_disabled_warnings', config.Number, 5, 0,
- _("""How many <em>Your Membership Is Disabled</em> warnings a
- disabled member should get before their address is removed from
- the mailing list. Set to 0 to immediately remove an address from
- the list once their bounce score exceeds the threshold. This
- value must be an integer.""")),
-
- ('bounce_you_are_disabled_warnings_interval', config.Number, 5, 0,
- _("""The number of days between sending the <em>Your Membership
- Is Disabled</em> warnings. This value must be an integer.""")),
-
- _('Notifications'),
-
- ('bounce_unrecognized_goes_to_list_owner', config.Toggle,
- (_('No'), _('Yes')), 0,
- _('''Should Mailman send you, the list owner, any bounce messages
- that failed to be detected by the bounce processor? <em>Yes</em>
- is recommended.'''),
- _("""While Mailman's bounce detector is fairly robust, it's
- impossible to detect every bounce format in the world. You
- should keep this variable set to <em>Yes</em> for two reasons: 1)
- If this really is a permanent bounce from one of your members,
- you should probably manually remove them from your list, and 2)
- you might want to send the message on to the Mailman developers
- so that this new format can be added to its known set.
-
- <p>If you really can't be bothered, then set this variable to
- <em>No</em> and all non-detected bounces will be discarded
- without further processing.
-
- <p><b>Note:</b> This setting will also affect all messages sent
- to your list's -admin address. This address is deprecated and
- should never be used, but some people may still send mail to this
- address. If this happens, and this variable is set to
- <em>No</em> those messages too will get discarded. You may want
- to set up an
- <a href="?VARHELP=autoreply/autoresponse_admin_text">autoresponse
- message</a> for email to the -owner and -admin address.""")),
-
- ('bounce_notify_owner_on_disable', config.Toggle,
- (_('No'), _('Yes')), 0,
- _("""Should Mailman notify you, the list owner, when bounces
- cause a member's subscription to be disabled?"""),
- _("""By setting this value to <em>No</em>, you turn off
- notification messages that are normally sent to the list owners
- when a member's delivery is disabled due to excessive bounces.
- An attempt to notify the member will always be made.""")),
-
- ('bounce_notify_owner_on_removal', config.Toggle,
- (_('No'), _('Yes')), 0,
- _("""Should Mailman notify you, the list owner, when bounces
- cause a member to be unsubscribed?"""),
- _("""By setting this value to <em>No</em>, you turn off
- notification messages that are normally sent to the list owners
- when a member is unsubscribed due to excessive bounces. An
- attempt to notify the member will always be made.""")),
-
- ]
-
- def _setValue(self, mlist, property, val, doc):
- # Do value conversion from web representation to internal
- # representation.
- try:
- if property == 'bounce_processing':
- val = int(val)
- elif property == 'bounce_score_threshold':
- val = float(val)
- elif property == 'bounce_info_stale_after':
- val = config.days(int(val))
- elif property == 'bounce_you_are_disabled_warnings':
- val = int(val)
- elif property == 'bounce_you_are_disabled_warnings_interval':
- val = config.days(int(val))
- elif property == 'bounce_notify_owner_on_disable':
- val = int(val)
- elif property == 'bounce_notify_owner_on_removal':
- val = int(val)
- except ValueError:
- doc.addError(
- _("""Bad value for <a href="?VARHELP=bounce/%(property)s"
- >%(property)s</a>: %(val)s"""),
- tag = _('Error: '))
- return
- GUIBase._setValue(self, mlist, property, val, doc)
-
- def getValue(self, mlist, kind, varname, params):
- if varname not in ('bounce_info_stale_after',
- 'bounce_you_are_disabled_warnings_interval'):
- return None
- return int(getattr(mlist, varname) / config.days(1))
diff --git a/mailman/web/Gui/ContentFilter.py b/mailman/web/Gui/ContentFilter.py
deleted file mode 100644
index 09817f4aa..000000000
--- a/mailman/web/Gui/ContentFilter.py
+++ /dev/null
@@ -1,199 +0,0 @@
-# Copyright (C) 2002-2009 by the Free Software Foundation, Inc.
-#
-# This file is part of GNU Mailman.
-#
-# GNU Mailman 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 3 of the License, or (at your option)
-# any later version.
-#
-# GNU Mailman 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
-# GNU Mailman. If not, see <http://www.gnu.org/licenses/>.
-
-"""GUI component managing the content filtering options."""
-
-from Mailman.Gui.GUIBase import GUIBase
-from Mailman.configuration import config
-from Mailman.i18n import _
-
-NL = '\n'
-
-
-
-class ContentFilter(GUIBase):
- def GetConfigCategory(self):
- return 'contentfilter', _('Content&nbsp;filtering')
-
- def GetConfigInfo(self, mlist, category, subcat=None):
- if category <> 'contentfilter':
- return None
- WIDTH = config.TEXTFIELDWIDTH
-
- actions = [_('Discard'), _('Reject'), _('Forward to List Owner')]
- if config.OWNERS_CAN_PRESERVE_FILTERED_MESSAGES:
- actions.append(_('Preserve'))
-
- return [
- _("""Policies concerning the content of list traffic.
-
- <p>Content filtering works like this: when a message is
- received by the list and you have enabled content filtering, the
- individual attachments are first compared to the
- <a href="?VARHELP=contentfilter/filter_mime_types">filter
- types</a>. If the attachment type matches an entry in the filter
- types, it is discarded.
-
- <p>Then, if there are <a
- href="?VARHELP=contentfilter/pass_mime_types">pass types</a>
- defined, any attachment type that does <em>not</em> match a
- pass type is also discarded. If there are no pass types defined,
- this check is skipped.
-
- <p>After this initial filtering, any <tt>multipart</tt>
- attachments that are empty are removed. If the outer message is
- left empty after this filtering, then the whole message is
- discarded.
-
- <p> Then, each <tt>multipart/alternative</tt> section will
- be replaced by just the first alternative that is non-empty after
- filtering if
- <a href="?VARHELP=contentfilter/collapse_alternatives"
- >collapse_alternatives</a> is enabled.
-
- <p>Finally, any <tt>text/html</tt> parts that are left in the
- message may be converted to <tt>text/plain</tt> if
- <a href="?VARHELP=contentfilter/convert_html_to_plaintext"
- >convert_html_to_plaintext</a> is enabled and the site is
- configured to allow these conversions."""),
-
- ('filter_content', config.Radio, (_('No'), _('Yes')), 0,
- _("""Should Mailman filter the content of list traffic according
- to the settings below?""")),
-
- ('filter_mime_types', config.Text, (10, WIDTH), 0,
- _("""Remove message attachments that have a matching content
- type."""),
-
- _("""Use this option to remove each message attachment that
- matches one of these content types. Each line should contain a
- string naming a MIME <tt>type/subtype</tt>,
- e.g. <tt>image/gif</tt>. Leave off the subtype to remove all
- parts with a matching major content type, e.g. <tt>image</tt>.
-
- <p>Blank lines are ignored.
-
- <p>See also <a href="?VARHELP=contentfilter/pass_mime_types"
- >pass_mime_types</a> for a content type whitelist.""")),
-
- ('pass_mime_types', config.Text, (10, WIDTH), 0,
- _("""Remove message attachments that don't have a matching
- content type. Leave this field blank to skip this filter
- test."""),
-
- _("""Use this option to remove each message attachment that does
- not have a matching content type. Requirements and formats are
- exactly like <a href="?VARHELP=contentfilter/filter_mime_types"
- >filter_mime_types</a>.
-
- <p><b>Note:</b> if you add entries to this list but don't add
- <tt>multipart</tt> to this list, any messages with attachments
- will be rejected by the pass filter.""")),
-
- ('filter_filename_extensions', config.Text, (10, WIDTH), 0,
- _("""Remove message attachments that have a matching filename
- extension."""),),
-
- ('pass_filename_extensions', config.Text, (10, WIDTH), 0,
- _("""Remove message attachments that don't have a matching
- filename extension. Leave this field blank to skip this filter
- test."""),),
-
- ('collapse_alternatives', config.Radio, (_('No'), _('Yes')), 0,
- _("""Should Mailman collapse multipart/alternative to its
- first part content?""")),
-
- ('convert_html_to_plaintext', config.Radio, (_('No'), _('Yes')), 0,
- _("""Should Mailman convert <tt>text/html</tt> parts to plain
- text? This conversion happens after MIME attachments have been
- stripped.""")),
-
- ('filter_action', config.Radio, tuple(actions), 0,
-
- _("""Action to take when a message matches the content filtering
- rules."""),
-
- _("""One of these actions is take when the message matches one of
- the content filtering rules, meaning, the top-level
- content type matches one of the <a
- href="?VARHELP=contentfilter/filter_mime_types"
- >filter_mime_types</a>, or the top-level content type does
- <strong>not</strong> match one of the
- <a href="?VARHELP=contentfilter/pass_mime_types"
- >pass_mime_types</a>, or if after filtering the subparts of the
- message, the message ends up empty.
-
- <p>Note this action is not taken if after filtering the message
- still contains content. In that case the message is always
- forwarded on to the list membership.
-
- <p>When messages are discarded, a log entry is written
- containing the Message-ID of the discarded message. When
- messages are rejected or forwarded to the list owner, a reason
- for the rejection is included in the bounce message to the
- original author. When messages are preserved, they are saved in
- a special queue directory on disk for the site administrator to
- view (and possibly rescue) but otherwise discarded. This last
- option is only available if enabled by the site
- administrator.""")),
- ]
-
- def _setValue(self, mlist, property, val, doc):
- if property in ('filter_mime_types', 'pass_mime_types'):
- types = []
- for spectype in [s.strip() for s in val.splitlines()]:
- ok = 1
- slashes = spectype.count('/')
- if slashes == 0 and not spectype:
- ok = 0
- elif slashes == 1:
- maintype, subtype = [s.strip().lower()
- for s in spectype.split('/')]
- if not maintype or not subtype:
- ok = 0
- elif slashes > 1:
- ok = 0
- if not ok:
- doc.addError(_('Bad MIME type ignored: %(spectype)s'))
- else:
- types.append(spectype.strip().lower())
- if property == 'filter_mime_types':
- mlist.filter_mime_types = types
- elif property == 'pass_mime_types':
- mlist.pass_mime_types = types
- elif property in ('filter_filename_extensions',
- 'pass_filename_extensions'):
- fexts = []
- for ext in [s.strip() for s in val.splitlines()]:
- fexts.append(ext.lower())
- if property == 'filter_filename_extensions':
- mlist.filter_filename_extensions = fexts
- elif property == 'pass_filename_extensions':
- mlist.pass_filename_extensions = fexts
- else:
- GUIBase._setValue(self, mlist, property, val, doc)
-
- def getValue(self, mlist, kind, property, params):
- if property == 'filter_mime_types':
- return NL.join(mlist.filter_mime_types)
- if property == 'pass_mime_types':
- return NL.join(mlist.pass_mime_types)
- if property == 'filter_filename_extensions':
- return NL.join(mlist.filter_filename_extensions)
- if property == 'pass_filename_extensions':
- return NL.join(mlist.pass_filename_extensions)
- return None
diff --git a/mailman/web/Gui/Digest.py b/mailman/web/Gui/Digest.py
deleted file mode 100644
index 821d0684f..000000000
--- a/mailman/web/Gui/Digest.py
+++ /dev/null
@@ -1,161 +0,0 @@
-# Copyright (C) 1998-2009 by the Free Software Foundation, Inc.
-#
-# This file is part of GNU Mailman.
-#
-# GNU Mailman 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 3 of the License, or (at your option)
-# any later version.
-#
-# GNU Mailman 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
-# GNU Mailman. If not, see <http://www.gnu.org/licenses/>.
-
-"""Administrative GUI for digest deliveries."""
-
-from Mailman import Utils
-from Mailman.configuration import config
-from Mailman.i18n import _
-
-# Intra-package import
-from Mailman.Gui.GUIBase import GUIBase
-
-# Common b/w nondigest and digest headers & footers. Personalizations may add
-# to this.
-ALLOWEDS = ('real_name', 'list_name', 'host_name', 'web_page_url',
- 'description', 'info', 'cgiext', '_internal_name',
- )
-
-
-
-class Digest(GUIBase):
- def GetConfigCategory(self):
- return 'digest', _('Digest options')
-
- def GetConfigInfo(self, mlist, category, subcat=None):
- if category <> 'digest':
- return None
- WIDTH = config.TEXTFIELDWIDTH
-
- info = [
- _("Batched-delivery digest characteristics."),
-
- ('digestable', config.Toggle, (_('No'), _('Yes')), 1,
- _('Can list members choose to receive list traffic '
- 'bunched in digests?')),
-
- ('digest_is_default', config.Radio,
- (_('Regular'), _('Digest')), 0,
- _('Which delivery mode is the default for new users?')),
-
- ('mime_is_default_digest', config.Radio,
- (_('Plain'), _('MIME')), 0,
- _('When receiving digests, which format is default?')),
-
- ('digest_size_threshhold', config.Number, 3, 0,
- _('How big in Kb should a digest be before it gets sent out?')),
- # Should offer a 'set to 0' for no size threshhold.
-
- ('digest_send_periodic', config.Radio, (_('No'), _('Yes')), 1,
- _('Should a digest be dispatched daily when the size threshold '
- "isn't reached?")),
-
- ('digest_header', config.Text, (4, WIDTH), 0,
- _('Header added to every digest'),
- _("Text attached (as an initial message, before the table"
- " of contents) to the top of digests. ")
- + Utils.maketext('headfoot.html', raw=1, mlist=mlist)),
-
- ('digest_footer', config.Text, (4, WIDTH), 0,
- _('Footer added to every digest'),
- _("Text attached (as a final message) to the bottom of digests. ")
- + Utils.maketext('headfoot.html', raw=1, mlist=mlist)),
-
- ('digest_volume_frequency', config.Radio,
- (_('Yearly'), _('Monthly'), _('Quarterly'),
- _('Weekly'), _('Daily')), 0,
- _('How often should a new digest volume be started?'),
- _('''When a new digest volume is started, the volume number is
- incremented and the issue number is reset to 1.''')),
-
- ('_new_volume', config.Toggle, (_('No'), _('Yes')), 0,
- _('Should Mailman start a new digest volume?'),
- _('''Setting this option instructs Mailman to start a new volume
- with the next digest sent out.''')),
-
- ('_send_digest_now', config.Toggle, (_('No'), _('Yes')), 0,
- _('''Should Mailman send the next digest right now, if it is not
- empty?''')),
- ]
-
-## if config.OWNERS_CAN_ENABLE_PERSONALIZATION:
-## info.extend([
-## ('digest_personalize', config.Toggle, (_('No'), _('Yes')), 1,
-
-## _('''Should Mailman personalize each digest delivery?
-## This is often useful for announce-only lists, but <a
-## href="?VARHELP=digest/digest_personalize">read the details</a>
-## section for a discussion of important performance
-## issues.'''),
-
-## _("""Normally, Mailman sends the digest messages to
-## the mail server in batches. This is much more efficent
-## because it reduces the amount of traffic between Mailman and
-## the mail server.
-
-## <p>However, some lists can benefit from a more personalized
-## approach. In this case, Mailman crafts a new message for
-## each member on the digest delivery list. Turning this on
-## adds a few more expansion variables that can be included in
-## the <a href="?VARHELP=digest/digest_header">message header</a>
-## and <a href="?VARHELP=digest/digest_footer">message footer</a>
-## but it may degrade the performance of your site as
-## a whole.
-
-## <p>You need to carefully consider whether the trade-off is
-## worth it, or whether there are other ways to accomplish what
-## you want. You should also carefully monitor your system load
-## to make sure it is acceptable.
-
-## <p>These additional substitution variables will be available
-## for your headers and footers, when this feature is enabled:
-
-## <ul><li><b>user_address</b> - The address of the user,
-## coerced to lower case.
-## <li><b>user_delivered_to</b> - The case-preserved address
-## that the user is subscribed with.
-## <li><b>user_password</b> - The user's password.
-## <li><b>user_name</b> - The user's full name.
-## <li><b>user_optionsurl</b> - The url to the user's option
-## page.
-## """))
-## ])
-
- return info
-
- def _setValue(self, mlist, property, val, doc):
- # Watch for the special, immediate action attributes
- if property == '_new_volume' and val:
- mlist.bump_digest_volume()
- volume = mlist.volume
- number = mlist.next_digest_number
- doc.AddItem(_("""The next digest will be sent as volume
- %(volume)s, number %(number)s"""))
- elif property == '_send_digest_now' and val:
- status = mlist.send_digest_now()
- if status:
- doc.AddItem(_("""A digest has been sent."""))
- else:
- doc.AddItem(_("""There was no digest to send."""))
- else:
- # Everything else...
- if property in ('digest_header', 'digest_footer'):
- val = self._convertString(mlist, property, ALLOWEDS, val, doc)
- if val is None:
- # There was a problem, so don't set it
- return
- GUIBase._setValue(self, mlist, property, val, doc)
diff --git a/mailman/web/Gui/GUIBase.py b/mailman/web/Gui/GUIBase.py
deleted file mode 100644
index b2846eb7b..000000000
--- a/mailman/web/Gui/GUIBase.py
+++ /dev/null
@@ -1,209 +0,0 @@
-# Copyright (C) 2002-2009 by the Free Software Foundation, Inc.
-#
-# This file is part of GNU Mailman.
-#
-# GNU Mailman 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 3 of the License, or (at your option)
-# any later version.
-#
-# GNU Mailman 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
-# GNU Mailman. If not, see <http://www.gnu.org/licenses/>.
-
-"""Base class for all web GUI components."""
-
-import re
-
-from Mailman import Defaults
-from Mailman import Errors
-from Mailman import Utils
-from Mailman.i18n import _
-
-NL = '\n'
-BADJOINER = '</code>, <code>'
-
-
-
-class GUIBase:
- # Providing a common interface for GUI component form processing. Most
- # GUI components won't need to override anything, but some may want to
- # override _setValue() to provide some specialized processing for some
- # attributes.
- def _getValidValue(self, mlist, property, wtype, val):
- # Coerce and validate the new value.
- #
- # Radio buttons and boolean toggles both have integral type
- if wtype in (Defaults.Radio, Defaults.Toggle):
- # Let ValueErrors propagate
- return int(val)
- # String and Text widgets both just return their values verbatim
- # but convert into unicode (for 2.2)
- if wtype in (Defaults.String, Defaults.Text):
- return unicode(val, Utils.GetCharSet(mlist.preferred_language))
- # This widget contains a single email address
- if wtype == Defaults.Email:
- # BAW: We must allow blank values otherwise reply_to_address can't
- # be cleared. This is currently the only Defaults.Email type
- # widget in the interface, so watch out if we ever add any new
- # ones.
- if val:
- # Let InvalidEmailAddress propagate.
- Utils.ValidateEmail(val)
- return val
- # These widget types contain lists of email addresses, one per line.
- # The EmailListEx allows each line to contain either an email address
- # or a regular expression
- if wtype in (Defaults.EmailList, Defaults.EmailListEx):
- # BAW: value might already be a list, if this is coming from
- # config_list input. Sigh.
- if isinstance(val, list):
- return val
- addrs = []
- for addr in [s.strip() for s in val.split(NL)]:
- # Discard empty lines
- if not addr:
- continue
- try:
- # This throws an exception if the address is invalid
- Utils.ValidateEmail(addr)
- except Errors.EmailAddressError:
- # See if this is a context that accepts regular
- # expressions, and that the re is legal
- if wtype == Defaults.EmailListEx and addr.startswith('^'):
- try:
- re.compile(addr)
- except re.error:
- raise ValueError
- else:
- raise
- addrs.append(addr)
- return addrs
- # This is a host name, i.e. verbatim
- if wtype == Defaults.Host:
- return val
- # This is a number, either a float or an integer
- if wtype == Defaults.Number:
- num = -1
- try:
- num = int(val)
- except ValueError:
- # Let ValueErrors percolate up
- num = float(val)
- if num < 0:
- return getattr(mlist, property)
- return num
- # This widget is a select box, i.e. verbatim
- if wtype == Defaults.Select:
- return val
- # Checkboxes return a list of the selected items, even if only one is
- # selected.
- if wtype == Defaults.Checkbox:
- if isinstance(val, list):
- return val
- return [val]
- if wtype == Defaults.FileUpload:
- return val
- if wtype == Defaults.Topics:
- return val
- if wtype == Defaults.HeaderFilter:
- return val
- # Should never get here
- assert 0, 'Bad gui widget type: %s' % wtype
-
- def _setValue(self, mlist, property, val, doc):
- # Set the value, or override to take special action on the property
- if not property.startswith('_') and getattr(mlist, property) <> val:
- setattr(mlist, property, val)
-
- def _postValidate(self, mlist, doc):
- # Validate all the attributes for this category
- pass
-
- def _escape(self, property, value):
- value = value.replace('<', '&lt;')
- return value
-
- def handleForm(self, mlist, category, subcat, cgidata, doc):
- for item in self.GetConfigInfo(mlist, category, subcat):
- # Skip descriptions and legacy non-attributes
- if not isinstance(item, tuple) or len(item) < 5:
- continue
- # Unpack the gui item description
- property, wtype, args, deps, desc = item[0:5]
- # BAW: I know this code is a little crufty but I wanted to
- # reproduce the semantics of the original code in admin.py as
- # closely as possible, for now. We can clean it up later.
- #
- # The property may be uploadable...
- uploadprop = property + '_upload'
- if cgidata.has_key(uploadprop) and cgidata[uploadprop].value:
- val = cgidata[uploadprop].value
- elif not cgidata.has_key(property):
- continue
- elif isinstance(cgidata[property], list):
- val = [self._escape(property, x.value)
- for x in cgidata[property]]
- else:
- val = self._escape(property, cgidata[property].value)
- # Coerce the value to the expected type, raising exceptions if the
- # value is invalid.
- try:
- val = self._getValidValue(mlist, property, wtype, val)
- except ValueError:
- doc.addError(_('Invalid value for variable: %(property)s'))
- # This is the parent of InvalidEmailAddress
- except Errors.EmailAddressError:
- doc.addError(
- _('Bad email address for option %(property)s: %(val)s'))
- else:
- # Set the attribute, which will normally delegate to the mlist
- self._setValue(mlist, property, val, doc)
- # Do a final sweep once all the attributes have been set. This is how
- # we can do cross-attribute assertions
- self._postValidate(mlist, doc)
-
- # Convenience method for handling $-string attributes
- def _convertString(self, mlist, property, alloweds, val, doc):
- # Is the list using $-strings?
- dollarp = getattr(mlist, 'use_dollar_strings', 0)
- if dollarp:
- ids = Utils.dollar_identifiers(val)
- else:
- # %-strings
- ids = Utils.percent_identifiers(val)
- # Here's the list of allowable interpolations
- for allowed in alloweds:
- if ids.has_key(allowed):
- del ids[allowed]
- if ids:
- # What's left are not allowed
- badkeys = ids.keys()
- badkeys.sort()
- bad = BADJOINER.join(badkeys)
- doc.addError(_(
- """The following illegal substitution variables were
- found in the <code>%(property)s</code> string:
- <code>%(bad)s</code>
- <p>Your list may not operate properly until you correct this
- problem."""), tag=_('Warning: '))
- return val
- # Now if we're still using %-strings, do a roundtrip conversion and
- # see if the converted value is the same as the new value. If not,
- # then they probably left off a trailing `s'. We'll warn them and use
- # the corrected string.
- if not dollarp:
- fixed = Utils.to_percent(Utils.to_dollar(val))
- if fixed <> val:
- doc.addError(_(
- """Your <code>%(property)s</code> string appeared to
- have some correctable problems in its new value.
- The fixed value will be used instead. Please
- double check that this is what you intended.
- """))
- return fixed
- return val
diff --git a/mailman/web/Gui/General.py b/mailman/web/Gui/General.py
deleted file mode 100644
index 27ef354be..000000000
--- a/mailman/web/Gui/General.py
+++ /dev/null
@@ -1,464 +0,0 @@
-# Copyright (C) 2001-2009 by the Free Software Foundation, Inc.
-#
-# This file is part of GNU Mailman.
-#
-# GNU Mailman 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 3 of the License, or (at your option)
-# any later version.
-#
-# GNU Mailman 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
-# GNU Mailman. If not, see <http://www.gnu.org/licenses/>.
-
-"""MailList mixin class managing the general options."""
-
-import re
-
-from Mailman import Errors
-from Mailman import Utils
-from Mailman.Gui.GUIBase import GUIBase
-from Mailman.configuration import config
-from Mailman.i18n import _
-
-OPTIONS = ('hide', 'ack', 'notmetoo', 'nodupes')
-
-
-
-class General(GUIBase):
- def GetConfigCategory(self):
- return 'general', _('General Options')
-
- def GetConfigInfo(self, mlist, category, subcat):
- if category <> 'general':
- return None
- WIDTH = config.TEXTFIELDWIDTH
-
- # These are for the default_options checkboxes below.
- bitfields = {'hide' : config.ConcealSubscription,
- 'ack' : config.AcknowledgePosts,
- 'notmetoo' : config.DontReceiveOwnPosts,
- 'nodupes' : config.DontReceiveDuplicates
- }
- bitdescrs = {
- 'hide' : _("Conceal the member's address"),
- 'ack' : _("Acknowledge the member's posting"),
- 'notmetoo' : _("Do not send a copy of a member's own post"),
- 'nodupes' :
- _('Filter out duplicate messages to list members (if possible)'),
- }
-
- optvals = [mlist.new_member_options & bitfields[o] for o in OPTIONS]
- opttext = [bitdescrs[o] for o in OPTIONS]
-
- rtn = [
- _('''Fundamental list characteristics, including descriptive
- info and basic behaviors.'''),
-
- _('General list personality'),
-
- ('real_name', config.String, WIDTH, 0,
- _('The public name of this list (make case-changes only).'),
- _('''The capitalization of this name can be changed to make it
- presentable in polite company as a proper noun, or to make an
- acronym part all upper case, etc. However, the name will be
- advertised as the email address (e.g., in subscribe confirmation
- notices), so it should <em>not</em> be otherwise altered. (Email
- addresses are not case sensitive, but they are sensitive to
- almost everything else :-)''')),
-
- ('owner', config.EmailList, (3, WIDTH), 0,
- _("""The list administrator email addresses. Multiple
- administrator addresses, each on separate line is okay."""),
-
- _('''There are two ownership roles associated with each mailing
- list. The <em>list administrators</em> are the people who have
- ultimate control over all parameters of this mailing list. They
- are able to change any list configuration variable available
- through these administration web pages.
-
- <p>The <em>list moderators</em> have more limited permissions;
- they are not able to change any list configuration variable, but
- they are allowed to tend to pending administration requests,
- including approving or rejecting held subscription requests, and
- disposing of held postings. Of course, the <em>list
- administrators</em> can also tend to pending requests.
-
- <p>In order to split the list ownership duties into
- administrators and moderators, you must
- <a href="passwords">set a separate moderator password</a>,
- and also provide the <a href="?VARHELP=general/moderator">email
- addresses of the list moderators</a>. Note that the field you
- are changing here specifies the list administrators.''')),
-
- ('moderator', config.EmailList, (3, WIDTH), 0,
- _("""The list moderator email addresses. Multiple
- moderator addresses, each on separate line is okay."""),
-
- _('''There are two ownership roles associated with each mailing
- list. The <em>list administrators</em> are the people who have
- ultimate control over all parameters of this mailing list. They
- are able to change any list configuration variable available
- through these administration web pages.
-
- <p>The <em>list moderators</em> have more limited permissions;
- they are not able to change any list configuration variable, but
- they are allowed to tend to pending administration requests,
- including approving or rejecting held subscription requests, and
- disposing of held postings. Of course, the <em>list
- administrators</em> can also tend to pending requests.
-
- <p>In order to split the list ownership duties into
- administrators and moderators, you must
- <a href="passwords">set a separate moderator password</a>,
- and also provide the email addresses of the list moderators in
- this section. Note that the field you are changing here
- specifies the list moderators.''')),
-
- ('description', config.String, WIDTH, 0,
- _('A terse phrase identifying this list.'),
-
- _('''This description is used when the mailing list is listed with
- other mailing lists, or in headers, and so forth. It should
- be as succinct as you can get it, while still identifying what
- the list is.''')),
-
- ('info', config.Text, (7, WIDTH), 0,
- _('''An introductory description - a few paragraphs - about the
- list. It will be included, as html, at the top of the listinfo
- page. Carriage returns will end a paragraph - see the details
- for more info.'''),
- _("""The text will be treated as html <em>except</em> that
- newlines will be translated to &lt;br&gt; - so you can use links,
- preformatted text, etc, but don't put in carriage returns except
- where you mean to separate paragraphs. And review your changes -
- bad html (like some unterminated HTML constructs) can prevent
- display of the entire listinfo page.""")),
-
- ('subject_prefix', config.String, WIDTH, 0,
- _('Prefix for subject line of list postings.'),
- _("""This text will be prepended to subject lines of messages
- posted to the list, to distinguish mailing list messages in in
- mailbox summaries. Brevity is premium here, it's ok to shorten
- long mailing list names to something more concise, as long as it
- still identifies the mailing list.
- You can also add a sequencial number by %%d substitution
- directive. eg.; [listname %%d] -> [listname 123]
- (listname %%05d) -> (listname 00123)
- """)),
-
- ('anonymous_list', config.Radio, (_('No'), _('Yes')), 0,
- _("""Hide the sender of a message, replacing it with the list
- address (Removes From, Sender and Reply-To fields)""")),
-
- _('''<tt>Reply-To:</tt> header munging'''),
-
- ('first_strip_reply_to', config.Radio, (_('No'), _('Yes')), 0,
- _('''Should any existing <tt>Reply-To:</tt> header found in the
- original message be stripped? If so, this will be done
- regardless of whether an explict <tt>Reply-To:</tt> header is
- added by Mailman or not.''')),
-
- ('reply_goes_to_list', config.Radio,
- (_('Poster'), _('This list'), _('Explicit address')), 0,
- _('''Where are replies to list messages directed?
- <tt>Poster</tt> is <em>strongly</em> recommended for most mailing
- lists.'''),
-
- # Details for reply_goes_to_list
- _("""This option controls what Mailman does to the
- <tt>Reply-To:</tt> header in messages flowing through this
- mailing list. When set to <em>Poster</em>, no <tt>Reply-To:</tt>
- header is added by Mailman, although if one is present in the
- original message, it is not stripped. Setting this value to
- either <em>This list</em> or <em>Explicit address</em> causes
- Mailman to insert a specific <tt>Reply-To:</tt> header in all
- messages, overriding the header in the original message if
- necessary (<em>Explicit address</em> inserts the value of <a
- href="?VARHELP=general/reply_to_address">reply_to_address</a>).
-
- <p>There are many reasons not to introduce or override the
- <tt>Reply-To:</tt> header. One is that some posters depend on
- their own <tt>Reply-To:</tt> settings to convey their valid
- return address. Another is that modifying <tt>Reply-To:</tt>
- makes it much more difficult to send private replies. See <a
- href="http://www.unicom.com/pw/reply-to-harmful.html">`Reply-To'
- Munging Considered Harmful</a> for a general discussion of this
- issue. See <a
- href="http://www.metasystema.net/essays/reply-to.mhtml">Reply-To
- Munging Considered Useful</a> for a dissenting opinion.
-
- <p>Some mailing lists have restricted posting privileges, with a
- parallel list devoted to discussions. Examples are `patches' or
- `checkin' lists, where software changes are posted by a revision
- control system, but discussion about the changes occurs on a
- developers mailing list. To support these types of mailing
- lists, select <tt>Explicit address</tt> and set the
- <tt>Reply-To:</tt> address below to point to the parallel
- list.""")),
-
- ('reply_to_address', config.Email, WIDTH, 0,
- _('Explicit <tt>Reply-To:</tt> header.'),
- # Details for reply_to_address
- _("""This is the address set in the <tt>Reply-To:</tt> header
- when the <a
- href="?VARHELP=general/reply_goes_to_list">reply_goes_to_list</a>
- option is set to <em>Explicit address</em>.
-
- <p>There are many reasons not to introduce or override the
- <tt>Reply-To:</tt> header. One is that some posters depend on
- their own <tt>Reply-To:</tt> settings to convey their valid
- return address. Another is that modifying <tt>Reply-To:</tt>
- makes it much more difficult to send private replies. See <a
- href="http://www.unicom.com/pw/reply-to-harmful.html">`Reply-To'
- Munging Considered Harmful</a> for a general discussion of this
- issue. See <a
- href="http://www.metasystema.net/essays/reply-to.mhtml">Reply-To
- Munging Considered Useful</a> for a dissenting opinion.
-
- <p>Some mailing lists have restricted posting privileges, with a
- parallel list devoted to discussions. Examples are `patches' or
- `checkin' lists, where software changes are posted by a revision
- control system, but discussion about the changes occurs on a
- developers mailing list. To support these types of mailing
- lists, specify the explicit <tt>Reply-To:</tt> address here. You
- must also specify <tt>Explicit address</tt> in the
- <tt>reply_goes_to_list</tt>
- variable.
-
- <p>Note that if the original message contains a
- <tt>Reply-To:</tt> header, it will not be changed.""")),
-
- _('Umbrella list settings'),
-
- ('umbrella_list', config.Radio, (_('No'), _('Yes')), 0,
- _('''Send password reminders to, eg, "-owner" address instead of
- directly to user.'''),
-
- _("""Set this to yes when this list is intended to cascade only
- to other mailing lists. When set, meta notices like
- confirmations and password reminders will be directed to an
- address derived from the member\'s address - it will have the
- value of "umbrella_member_suffix" appended to the member's
- account name.""")),
-
- ('umbrella_member_suffix', config.String, WIDTH, 0,
- _('''Suffix for use when this list is an umbrella for other
- lists, according to setting of previous "umbrella_list"
- setting.'''),
-
- _("""When "umbrella_list" is set to indicate that this list has
- other mailing lists as members, then administrative notices like
- confirmations and password reminders need to not be sent to the
- member list addresses, but rather to the owner of those member
- lists. In that case, the value of this setting is appended to
- the member's account name for such notices. `-owner' is the
- typical choice. This setting has no effect when "umbrella_list"
- is "No".""")),
-
- _('Notifications'),
-
- ('send_reminders', config.Radio, (_('No'), _('Yes')), 0,
- _('''Send monthly password reminders?'''),
-
- _('''Turn this on if you want password reminders to be sent once
- per month to your members. Note that members may disable their
- own individual password reminders.''')),
-
- ('welcome_msg', config.Text, (4, WIDTH), 0,
- _('''List-specific text prepended to new-subscriber welcome
- message'''),
-
- _("""This value, if any, will be added to the front of the
- new-subscriber welcome message. The rest of the welcome message
- already describes the important addresses and URLs for the
- mailing list, so you don't need to include any of that kind of
- stuff here. This should just contain mission-specific kinds of
- things, like etiquette policies or team orientation, or that kind
- of thing.
-
- <p>Note that this text will be wrapped, according to the
- following rules:
- <ul><li>Each paragraph is filled so that no line is longer than
- 70 characters.
- <li>Any line that begins with whitespace is not filled.
- <li>A blank line separates paragraphs.
- </ul>""")),
-
- ('send_welcome_msg', config.Radio, (_('No'), _('Yes')), 0,
- _('Send welcome message to newly subscribed members?'),
- _("""Turn this off only if you plan on subscribing people manually
- and don't want them to know that you did so. This option is most
- useful for transparently migrating lists from some other mailing
- list manager to Mailman.""")),
-
- ('goodbye_msg', config.Text, (4, WIDTH), 0,
- _('''Text sent to people leaving the list. If empty, no special
- text will be added to the unsubscribe message.''')),
-
- ('send_goodbye_msg', config.Radio, (_('No'), _('Yes')), 0,
- _('Send goodbye message to members when they are unsubscribed?')),
-
- ('admin_immed_notify', config.Radio, (_('No'), _('Yes')), 0,
- _('''Should the list moderators get immediate notice of new
- requests, as well as daily notices about collected ones?'''),
-
- _('''List moderators (and list administrators) are sent daily
- reminders of requests pending approval, like subscriptions to a
- moderated list, or postings that are being held for one reason or
- another. Setting this option causes notices to be sent
- immediately on the arrival of new requests as well.''')),
-
- ('admin_notify_mchanges', config.Radio, (_('No'), _('Yes')), 0,
- _('''Should administrator get notices of subscribes and
- unsubscribes?''')),
-
- ('respond_to_post_requests', config.Radio,
- (_('No'), _('Yes')), 0,
- _('Send mail to poster when their posting is held for approval?')
- ),
-
- _('Additional settings'),
-
- ('emergency', config.Toggle, (_('No'), _('Yes')), 0,
- _('Emergency moderation of all list traffic.'),
- _("""When this option is enabled, all list traffic is emergency
- moderated, i.e. held for moderation. Turn this option on when
- your list is experiencing a flamewar and you want a cooling off
- period.""")),
-
- ('new_member_options', config.Checkbox,
- (opttext, optvals, 0, OPTIONS),
- # The description for new_member_options includes a kludge where
- # we add a hidden field so that even when all the checkboxes are
- # deselected, the form data will still have a new_member_options
- # key (it will always be a list). Otherwise, we'd never be able
- # to tell if all were deselected!
- 0, _('''Default options for new members joining this list.<input
- type="hidden" name="new_member_options" value="ignore">'''),
-
- _("""When a new member is subscribed to this list, their initial
- set of options is taken from the this variable's setting.""")),
-
- ('administrivia', config.Radio, (_('No'), _('Yes')), 0,
- _('''(Administrivia filter) Check postings and intercept ones
- that seem to be administrative requests?'''),
-
- _("""Administrivia tests will check postings to see whether it's
- really meant as an administrative request (like subscribe,
- unsubscribe, etc), and will add it to the the administrative
- requests queue, notifying the administrator of the new request,
- in the process.""")),
-
- ('max_message_size', config.Number, 7, 0,
- _('''Maximum length in kilobytes (KB) of a message body. Use 0
- for no limit.''')),
-
- ('host_name', config.Host, WIDTH, 0,
- _('Host name this list prefers for email.'),
-
- _("""The "host_name" is the preferred name for email to
- mailman-related addresses on this host, and generally should be
- the mail host's exchanger address, if any. This setting can be
- useful for selecting among alternative names of a host that has
- multiple addresses.""")),
-
- ]
-
- if config.ALLOW_RFC2369_OVERRIDES:
- rtn.append(
- ('include_rfc2369_headers', config.Radio,
- (_('No'), _('Yes')), 0,
- _("""Should messages from this mailing list include the
- <a href="http://www.faqs.org/rfcs/rfc2369.html">RFC 2369</a>
- (i.e. <tt>List-*</tt>) headers? <em>Yes</em> is highly
- recommended."""),
-
- _("""RFC 2369 defines a set of List-* headers that are
- normally added to every message sent to the list membership.
- These greatly aid end-users who are using standards compliant
- mail readers. They should normally always be enabled.
-
- <p>However, not all mail readers are standards compliant yet,
- and if you have a large number of members who are using
- non-compliant mail readers, they may be annoyed at these
- headers. You should first try to educate your members as to
- why these headers exist, and how to hide them in their mail
- clients. As a last resort you can disable these headers, but
- this is not recommended (and in fact, your ability to disable
- these headers may eventually go away)."""))
- )
- # Suppression of List-Post: headers
- rtn.append(
- ('include_list_post_header', config.Radio,
- (_('No'), _('Yes')), 0,
- _('Should postings include the <tt>List-Post:</tt> header?'),
- _("""The <tt>List-Post:</tt> header is one of the headers
- recommended by
- <a href="http://www.faqs.org/rfcs/rfc2369.html">RFC 2369</a>.
- However for some <em>announce-only</em> mailing lists, only a
- very select group of people are allowed to post to the list; the
- general membership is usually not allowed to post. For lists of
- this nature, the <tt>List-Post:</tt> header is misleading.
- Select <em>No</em> to disable the inclusion of this header. (This
- does not affect the inclusion of the other <tt>List-*:</tt>
- headers.)"""))
- )
-
- # Discard held messages after this number of days
- rtn.append(
- ('max_days_to_hold', config.Number, 7, 0,
- _("""Discard held messages older than this number of days.
- Use 0 for no automatic discarding."""))
- )
-
- return rtn
-
- def _setValue(self, mlist, property, val, doc):
- if property == 'real_name' and \
- val.lower() <> mlist.internal_name().lower():
- # These values can't differ by other than case
- doc.addError(_("""<b>real_name</b> attribute not
- changed! It must differ from the list's name by case
- only."""))
- elif property == 'new_member_options':
- newopts = 0
- for opt in OPTIONS:
- bitfield = config.OPTINFO[opt]
- if opt in val:
- newopts |= bitfield
- mlist.new_member_options = newopts
- elif property == 'subject_prefix':
- # Convert any html entities to Unicode
- mlist.subject_prefix = Utils.canonstr(
- val, mlist.preferred_language)
- else:
- GUIBase._setValue(self, mlist, property, val, doc)
-
- def _escape(self, property, value):
- # The 'info' property allows HTML, but lets sanitize it to avoid XSS
- # exploits. Everything else should be fully escaped.
- if property <> 'info':
- return GUIBase._escape(self, property, value)
- # Sanitize <script> and </script> tags but nothing else. Not the best
- # solution, but expedient.
- return re.sub(r'<([/]?script.*?)>', r'&lt;\1&gt;', value)
-
- def _postValidate(self, mlist, doc):
- if not mlist.reply_to_address.strip() and \
- mlist.reply_goes_to_list == 2:
- # You can't go to an explicit address that is blank
- doc.addError(_("""You cannot add a Reply-To: to an explicit
- address if that address is blank. Resetting these values."""))
- mlist.reply_to_address = ''
- mlist.reply_goes_to_list = 0
-
- def getValue(self, mlist, kind, varname, params):
- if varname <> 'subject_prefix':
- return None
- # The subject_prefix may be Unicode
- return Utils.uncanonstr(mlist.subject_prefix, mlist.preferred_language)
diff --git a/mailman/web/Gui/Language.py b/mailman/web/Gui/Language.py
deleted file mode 100644
index 05824be5e..000000000
--- a/mailman/web/Gui/Language.py
+++ /dev/null
@@ -1,128 +0,0 @@
-# Copyright (C) 2001-2009 by the Free Software Foundation, Inc.
-#
-# This file is part of GNU Mailman.
-#
-# GNU Mailman 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 3 of the License, or (at your option)
-# any later version.
-#
-# GNU Mailman 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
-# GNU Mailman. If not, see <http://www.gnu.org/licenses/>.
-
-"""MailList mixin class managing the language options."""
-
-import codecs
-
-from Mailman import Utils
-from Mailman import i18n
-from Mailman.Gui.GUIBase import GUIBase
-from Mailman.configuration import config
-
-_ = i18n._
-
-
-
-class Language(GUIBase):
- def GetConfigCategory(self):
- return 'language', _('Language&nbsp;options')
-
- def GetConfigInfo(self, mlist, category, subcat=None):
- if category <> 'language':
- return None
- # Set things up for the language choices
- langs = mlist.language_codes
- langnames = [_(description) for description in config.enabled_names]
- try:
- langi = langs.index(mlist.preferred_language)
- except ValueError:
- # Someone must have deleted the list's preferred language. Could
- # be other trouble lurking!
- langi = 0
- # Only allow the admin to choose a language if the system has a
- # charset for it. I think this is the best way to test for that.
- def checkcodec(charset):
- try:
- codecs.lookup(charset)
- return 1
- except LookupError:
- return 0
-
- all = sorted(code for code in config.languages.enabled_codes
- if checkcodec(Utils.GetCharSet(code)))
- checked = [L in langs for L in all]
- allnames = [_(config.languages.get_description(code)) for code in all]
- return [
- _('Natural language (internationalization) options.'),
-
- ('preferred_language', config.Select,
- (langs, langnames, langi),
- 0,
- _('Default language for this list.'),
- _('''This is the default natural language for this mailing list.
- If <a href="?VARHELP=language/available_languages">more than one
- language</a> is supported then users will be able to select their
- own preferences for when they interact with the list. All other
- interactions will be conducted in the default language. This
- applies to both web-based and email-based messages, but not to
- email posted by list members.''')),
-
- ('available_languages', config.Checkbox,
- (allnames, checked, 0, all), 0,
- _('Languages supported by this list.'),
-
- _('''These are all the natural languages supported by this list.
- Note that the
- <a href="?VARHELP=language/preferred_language">default
- language</a> must be included.''')),
-
- ('encode_ascii_prefixes', config.Radio,
- (_('Never'), _('Always'), _('As needed')), 0,
- _("""Encode the
- <a href="?VARHELP=general/subject_prefix">subject
- prefix</a> even when it consists of only ASCII characters?"""),
-
- _("""If your mailing list's default language uses a non-ASCII
- character set and the prefix contains non-ASCII characters, the
- prefix will always be encoded according to the relevant
- standards. However, if your prefix contains only ASCII
- characters, you may want to set this option to <em>Never</em> to
- disable prefix encoding. This can make the subject headers
- slightly more readable for users with mail readers that don't
- properly handle non-ASCII encodings.
-
- <p>Note however, that if your mailing list receives both encoded
- and unencoded subject headers, you might want to choose <em>As
- needed</em>. Using this setting, Mailman will not encode ASCII
- prefixes when the rest of the header contains only ASCII
- characters, but if the original header contains non-ASCII
- characters, it will encode the prefix. This avoids an ambiguity
- in the standards which could cause some mail readers to display
- extra, or missing spaces between the prefix and the original
- header.""")),
-
- ]
-
- def _setValue(self, mlist, prop, val, doc):
- # If we're changing the list's preferred language, change the I18N
- # context as well
- if prop == 'preferred_language':
- i18n.set_language(val)
- doc.set_language(val)
- # Language codes must be wrapped
- if prop == 'available_languages':
- mlist.set_languages(*val)
- else:
- GUIBase._setValue(self, mlist, prop, val, doc)
-
- def getValue(self, mlist, kind, varname, params):
- if varname == 'available_languages':
- # Unwrap Language instances, to return just the code
- return [language.code for language in mlist.available_languages]
- # Returning None tells the infrastructure to use getattr
- return None
diff --git a/mailman/web/Gui/Membership.py b/mailman/web/Gui/Membership.py
deleted file mode 100644
index bbfdb438b..000000000
--- a/mailman/web/Gui/Membership.py
+++ /dev/null
@@ -1,34 +0,0 @@
-# Copyright (C) 2001-2009 by the Free Software Foundation, Inc.
-#
-# This file is part of GNU Mailman.
-#
-# GNU Mailman 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 3 of the License, or (at your option)
-# any later version.
-#
-# GNU Mailman 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
-# GNU Mailman. If not, see <http://www.gnu.org/licenses/>.
-
-"""MailList mixin class managing the membership pseudo-options."""
-
-from Mailman.i18n import _
-
-
-
-class Membership:
- def GetConfigCategory(self):
- return 'members', _('Membership&nbsp;Management...')
-
- def GetConfigSubCategories(self, category):
- if category == 'members':
- return [('list', _('Membership&nbsp;List')),
- ('add', _('Mass&nbsp;Subscription')),
- ('remove', _('Mass&nbsp;Removal')),
- ]
- return None
diff --git a/mailman/web/Gui/NonDigest.py b/mailman/web/Gui/NonDigest.py
deleted file mode 100644
index 92fb768ad..000000000
--- a/mailman/web/Gui/NonDigest.py
+++ /dev/null
@@ -1,158 +0,0 @@
-# Copyright (C) 2001-2009 by the Free Software Foundation, Inc.
-#
-# This file is part of GNU Mailman.
-#
-# GNU Mailman 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 3 of the License, or (at your option)
-# any later version.
-#
-# GNU Mailman 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
-# GNU Mailman. If not, see <http://www.gnu.org/licenses/>.
-
-"""GUI component for managing the non-digest delivery options."""
-
-from Mailman import Utils
-from Mailman import Defaults
-from Mailman.i18n import _
-from Mailman.configuration import config
-from Mailman.Gui.GUIBase import GUIBase
-
-from Mailman.Gui.Digest import ALLOWEDS
-PERSONALIZED_ALLOWEDS = ('user_address', 'user_delivered_to', 'user_password',
- 'user_name', 'user_optionsurl',
- )
-
-
-
-class NonDigest(GUIBase):
- def GetConfigCategory(self):
- return 'nondigest', _('Non-digest&nbsp;options')
-
- def GetConfigInfo(self, mlist, category, subcat=None):
- if category <> 'nondigest':
- return None
- WIDTH = config.TEXTFIELDWIDTH
-
- info = [
- _("Policies concerning immediately delivered list traffic."),
-
- ('nondigestable', Defaults.Toggle, (_('No'), _('Yes')), 1,
- _("""Can subscribers choose to receive mail immediately, rather
- than in batched digests?""")),
- ]
-
- if config.OWNERS_CAN_ENABLE_PERSONALIZATION:
- info.extend([
- ('personalize', Defaults.Radio,
- (_('No'), _('Yes'), _('Full Personalization')), 1,
-
- _('''Should Mailman personalize each non-digest delivery?
- This is often useful for announce-only lists, but <a
- href="?VARHELP=nondigest/personalize">read the details</a>
- section for a discussion of important performance
- issues.'''),
-
- _("""Normally, Mailman sends the regular delivery messages to
- the mail server in batches. This is much more efficent
- because it reduces the amount of traffic between Mailman and
- the mail server.
-
- <p>However, some lists can benefit from a more personalized
- approach. In this case, Mailman crafts a new message for
- each member on the regular delivery list. Turning this
- feature on may degrade the performance of your site, so you
- need to carefully consider whether the trade-off is worth it,
- or whether there are other ways to accomplish what you want.
- You should also carefully monitor your system load to make
- sure it is acceptable.
-
- <p>Select <em>No</em> to disable personalization and send
- messages to the members in batches. Select <em>Yes</em> to
- personalize deliveries and allow additional substitution
- variables in message headers and footers (see below). In
- addition, by selecting <em>Full Personalization</em>, the
- <code>To</code> header of posted messages will be modified to
- include the member's address instead of the list's posting
- address.
-
- <p>When personalization is enabled, a few more expansion
- variables that can be included in the <a
- href="?VARHELP=nondigest/msg_header">message header</a> and
- <a href="?VARHELP=nondigest/msg_footer">message footer</a>.
-
- <p>These additional substitution variables will be available
- for your headers and footers, when this feature is enabled:
-
- <ul><li><b>user_address</b> - The address of the user,
- coerced to lower case.
- <li><b>user_delivered_to</b> - The case-preserved address
- that the user is subscribed with.
- <li><b>user_password</b> - The user's password.
- <li><b>user_name</b> - The user's full name.
- <li><b>user_optionsurl</b> - The url to the user's option
- page.
- </ul>
- """))
- ])
- # BAW: for very dumb reasons, we want the `personalize' attribute to
- # show up before the msg_header and msg_footer attrs, otherwise we'll
- # get a bogus warning if the header/footer contains a personalization
- # substitution variable, and we're transitioning from no
- # personalization to personalization enabled.
- headfoot = Utils.maketext('headfoot.html', mlist=mlist, raw=1)
- if config.OWNERS_CAN_ENABLE_PERSONALIZATION:
- extra = _("""\
-When <a href="?VARHELP=nondigest/personalize">personalization</a> is enabled
-for this list, additional substitution variables are allowed in your headers
-and footers:
-
-<ul><li><b>user_address</b> - The address of the user,
- coerced to lower case.
- <li><b>user_delivered_to</b> - The case-preserved address
- that the user is subscribed with.
- <li><b>user_password</b> - The user's password.
- <li><b>user_name</b> - The user's full name.
- <li><b>user_optionsurl</b> - The url to the user's option
- page.
-</ul>
-""")
- else:
- extra = ''
-
- info.extend([('msg_header', Defaults.Text, (10, WIDTH), 0,
- _('Header added to mail sent to regular list members'),
- _('''Text prepended to the top of every immediately-delivery
- message. ''') + headfoot + extra),
-
- ('msg_footer', Defaults.Text, (10, WIDTH), 0,
- _('Footer added to mail sent to regular list members'),
- _('''Text appended to the bottom of every immediately-delivery
- message. ''') + headfoot + extra),
- ])
-
- info.extend([
- ('scrub_nondigest', Defaults.Toggle, (_('No'), _('Yes')), 0,
- _('Scrub attachments of regular delivery message?'),
- _('''When you scrub attachments, they are stored in archive
- area and links are made in the message so that the member can
- access via web browser. If you want the attachments totally
- disappear, you can use content filter options.''')),
- ])
- return info
-
- def _setValue(self, mlist, property, val, doc):
- alloweds = list(ALLOWEDS)
- if mlist.personalize:
- alloweds.extend(PERSONALIZED_ALLOWEDS)
- if property in ('msg_header', 'msg_footer'):
- val = self._convertString(mlist, property, alloweds, val, doc)
- if val is None:
- # There was a problem, so don't set it
- return
- GUIBase._setValue(self, mlist, property, val, doc)
diff --git a/mailman/web/Gui/Passwords.py b/mailman/web/Gui/Passwords.py
deleted file mode 100644
index b2fea0fb5..000000000
--- a/mailman/web/Gui/Passwords.py
+++ /dev/null
@@ -1,31 +0,0 @@
-# Copyright (C) 2001-2009 by the Free Software Foundation, Inc.
-#
-# This file is part of GNU Mailman.
-#
-# GNU Mailman 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 3 of the License, or (at your option)
-# any later version.
-#
-# GNU Mailman 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
-# GNU Mailman. If not, see <http://www.gnu.org/licenses/>.
-
-"""MailList mixin class managing the password pseudo-options."""
-
-from Mailman.i18n import _
-from Mailman.Gui.GUIBase import GUIBase
-
-
-
-class Passwords(GUIBase):
- def GetConfigCategory(self):
- return 'passwords', _('Passwords')
-
- def handleForm(self, mlist, category, subcat, cgidata, doc):
- # Nothing more needs to be done
- pass
diff --git a/mailman/web/Gui/Privacy.py b/mailman/web/Gui/Privacy.py
deleted file mode 100644
index 8d60f9203..000000000
--- a/mailman/web/Gui/Privacy.py
+++ /dev/null
@@ -1,537 +0,0 @@
-# Copyright (C) 2001-2009 by the Free Software Foundation, Inc.
-#
-# This file is part of GNU Mailman.
-#
-# GNU Mailman 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 3 of the License, or (at your option)
-# any later version.
-#
-# GNU Mailman 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
-# GNU Mailman. If not, see <http://www.gnu.org/licenses/>.
-
-"""MailList mixin class managing the privacy options."""
-
-import re
-
-from Mailman import Utils
-from Mailman.Gui.GUIBase import GUIBase
-from Mailman.configuration import config
-from Mailman.i18n import _
-
-
-
-class Privacy(GUIBase):
- def GetConfigCategory(self):
- return 'privacy', _('Privacy options...')
-
- def GetConfigSubCategories(self, category):
- if category == 'privacy':
- return [('subscribing', _('Subscription&nbsp;rules')),
- ('sender', _('Sender&nbsp;filters')),
- ('recipient', _('Recipient&nbsp;filters')),
- ('spam', _('Spam&nbsp;filters')),
- ]
- return None
-
- def GetConfigInfo(self, mlist, category, subcat=None):
- if category <> 'privacy':
- return None
- # Pre-calculate some stuff. Technically, we shouldn't do the
- # sub_cfentry calculation here, but it's too ugly to indent it any
- # further, and besides, that'll mess up i18n catalogs.
- WIDTH = config.TEXTFIELDWIDTH
- if config.ALLOW_OPEN_SUBSCRIBE:
- sub_cfentry = ('subscribe_policy', config.Radio,
- # choices
- (_('None'),
- _('Confirm'),
- _('Require approval'),
- _('Confirm and approve')),
- 0,
- _('What steps are required for subscription?<br>'),
- _('''None - no verification steps (<em>Not
- Recommended </em>)<br>
- Confirm (*) - email confirmation step required <br>
- Require approval - require list administrator
- Approval for subscriptions <br>
- Confirm and approve - both confirm and approve
-
- <p>(*) when someone requests a subscription,
- Mailman sends them a notice with a unique
- subscription request number that they must reply to
- in order to subscribe.<br>
-
- This prevents mischievous (or malicious) people
- from creating subscriptions for others without
- their consent.'''))
- else:
- sub_cfentry = ('subscribe_policy', config.Radio,
- # choices
- (_('Confirm'),
- _('Require approval'),
- _('Confirm and approve')),
- 1,
- _('What steps are required for subscription?<br>'),
- _('''Confirm (*) - email confirmation required <br>
- Require approval - require list administrator
- approval for subscriptions <br>
- Confirm and approve - both confirm and approve
-
- <p>(*) when someone requests a subscription,
- Mailman sends them a notice with a unique
- subscription request number that they must reply to
- in order to subscribe.<br> This prevents
- mischievous (or malicious) people from creating
- subscriptions for others without their consent.'''))
-
- # some helpful values
- admin = mlist.GetScriptURL('admin')
-
- subscribing_rtn = [
- _("""This section allows you to configure subscription and
- membership exposure policy. You can also control whether this
- list is public or not. See also the
- <a href="%(admin)s/archive">Archival Options</a> section for
- separate archive-related privacy settings."""),
-
- _('Subscribing'),
- ('advertised', config.Radio, (_('No'), _('Yes')), 0,
- _('''Advertise this list when people ask what lists are on this
- machine?''')),
-
- sub_cfentry,
-
- ('subscribe_auto_approval', config.EmailListEx, (10, WIDTH), 1,
- _("""List of addresses (or regexps) whose subscriptions do not
- require approval."""),
-
- _("""When subscription requires approval, addresses in this list
- are allowed to subscribe without administrator approval. Add
- addresses one per line. You may begin a line with a ^ character
- to designate a (case insensitive) regular expression match.""")),
-
- ('unsubscribe_policy', config.Radio, (_('No'), _('Yes')), 0,
- _("""Is the list moderator's approval required for unsubscription
- requests? (<em>No</em> is recommended)"""),
-
- _("""When members want to leave a list, they will make an
- unsubscription request, either via the web or via email.
- Normally it is best for you to allow open unsubscriptions so that
- users can easily remove themselves from mailing lists (they get
- really upset if they can't get off lists!).
-
- <p>For some lists though, you may want to impose moderator
- approval before an unsubscription request is processed. Examples
- of such lists include a corporate mailing list that all employees
- are required to be members of.""")),
-
- _('Ban list'),
- ('ban_list', config.EmailListEx, (10, WIDTH), 1,
- _("""List of addresses which are banned from membership in this
- mailing list."""),
-
- _("""Addresses in this list are banned outright from subscribing
- to this mailing list, with no further moderation required. Add
- addresses one per line; start the line with a ^ character to
- designate a regular expression match.""")),
-
- _("Membership exposure"),
- ('private_roster', config.Radio,
- (_('Anyone'), _('List members'), _('List admin only')), 0,
- _('Who can view subscription list?'),
-
- _('''When set, the list of subscribers is protected by member or
- admin password authentication.''')),
-
- ('obscure_addresses', config.Radio, (_('No'), _('Yes')), 0,
- _("""Show member addresses so they're not directly recognizable
- as email addresses?"""),
- _("""Setting this option causes member email addresses to be
- transformed when they are presented on list web pages (both in
- text and as links), so they're not trivially recognizable as
- email addresses. The intention is to prevent the addresses
- from being snarfed up by automated web scanners for use by
- spammers.""")),
- ]
-
- 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
- first approve the message or not. This section contains the
- controls for moderation of both member and non-member postings.
-
- <p>Member postings are held for moderation if their
- <b>moderation flag</b> is turned on. You can control whether
- member postings are moderated by default or not.
-
- <p>Non-member postings can be automatically
- <a href="?VARHELP=privacy/sender/accept_these_nonmembers"
- >accepted</a>,
- <a href="?VARHELP=privacy/sender/hold_these_nonmembers">held for
- moderation</a>,
- <a href="?VARHELP=privacy/sender/reject_these_nonmembers"
- >rejected</a> (bounced), or
- <a href="?VARHELP=privacy/sender/discard_these_nonmembers"
- >discarded</a>,
- either individually or as a group. Any
- posting from a non-member who is not explicitly accepted,
- rejected, or discarded, will have their posting filtered by the
- <a href="?VARHELP=privacy/sender/generic_nonmember_action">general
- non-member rules</a>.
-
- <p>In the text boxes below, add one address per line; start the
- line with a ^ character to designate a <a href=
- "http://www.python.org/doc/current/lib/module-re.html"
- >Python regular expression</a>. When entering backslashes, do so
- as if you were using Python raw strings (i.e. you generally just
- use a single backslash).
-
- <p>Note that non-regexp matches are always done first."""),
-
- _('Member filters'),
-
- ('default_member_moderation', config.Radio, (_('No'), _('Yes')),
- 0, _('By default, should new list member postings be moderated?'),
-
- _("""Each list member has a <em>moderation flag</em> which says
- whether messages from the list member can be posted directly to
- the list, or must first be approved by the list moderator. When
- the moderation flag is turned on, list member postings must be
- approved first. You, the list administrator can decide whether a
- specific individual's postings will be moderated or not.
-
- <p>When a new member is subscribed, their initial moderation flag
- takes its value from this option. Turn this option off to accept
- member postings by default. Turn this option on to, by default,
- moderate member postings first. You can always manually set an
- individual member's moderation bit by using the
- <a href="%(adminurl)s/members">membership management
- screens</a>.""")),
-
- ('member_moderation_action', config.Radio,
- (_('Hold'), _('Reject'), _('Discard')), 0,
- _("""Action to take when a moderated member posts to the
- list."""),
- _("""<ul><li><b>Hold</b> -- this holds the message for approval
- by the list moderators.
-
- <p><li><b>Reject</b> -- this automatically rejects the message by
- sending a bounce notice to the post's author. The text of the
- bounce notice can be <a
- href="?VARHELP=privacy/sender/member_moderation_notice"
- >configured by you</a>.
-
- <p><li><b>Discard</b> -- this simply discards the message, with
- no notice sent to the post's author.
- </ul>""")),
-
- ('member_moderation_notice', config.Text, (10, WIDTH), 1,
- _("""Text to include in any
- <a href="?VARHELP/privacy/sender/member_moderation_action"
- >rejection notice</a> to
- be sent to moderated members who post to this list.""")),
-
- _('Non-member filters'),
-
- ('accept_these_nonmembers', config.EmailListEx, (10, WIDTH), 1,
- _("""List of non-member addresses whose postings should be
- automatically accepted."""),
-
- _("""Postings from any of these non-members will be automatically
- accepted with no further moderation applied. Add member
- addresses one per line; start the line with a ^ character to
- designate a regular expression match.""")),
-
- ('hold_these_nonmembers', config.EmailListEx, (10, WIDTH), 1,
- _("""List of non-member addresses whose postings will be
- immediately held for moderation."""),
-
- _("""Postings from any of these non-members will be immediately
- and automatically held for moderation by the list moderators.
- The sender will receive a notification message which will allow
- them to cancel their held message. Add member addresses one per
- line; start the line with a ^ character to designate a regular
- expression match.""")),
-
- ('reject_these_nonmembers', config.EmailListEx, (10, WIDTH), 1,
- _("""List of non-member addresses whose postings will be
- automatically rejected."""),
-
- _("""Postings from any of these non-members will be automatically
- rejected. In other words, their messages will be bounced back to
- the sender with a notification of automatic rejection. This
- option is not appropriate for known spam senders; their messages
- should be
- <a href="?VARHELP=privacy/sender/discard_these_nonmembers"
- >automatically discarded</a>.
-
- <p>Add member addresses one per line; start the line with a ^
- character to designate a regular expression match.""")),
-
- ('discard_these_nonmembers', config.EmailListEx, (10, WIDTH), 1,
- _("""List of non-member addresses whose postings will be
- automatically discarded."""),
-
- _("""Postings from any of these non-members will be automatically
- discarded. That is, the message will be thrown away with no
- further processing or notification. The sender will not receive
- a notification or a bounce, however the list moderators can
- optionally <a href="?VARHELP=privacy/sender/forward_auto_discards"
- >receive copies of auto-discarded messages.</a>.
-
- <p>Add member addresses one per line; start the line with a ^
- character to designate a regular expression match.""")),
-
- ('generic_nonmember_action', config.Radio,
- (_('Accept'), _('Hold'), _('Reject'), _('Discard')), 0,
- _("""Action to take for postings from non-members for which no
- explicit action is defined."""),
-
- _("""When a post from a non-member is received, the message's
- sender is matched against the list of explicitly
- <a href="?VARHELP=privacy/sender/accept_these_nonmembers"
- >accepted</a>,
- <a href="?VARHELP=privacy/sender/hold_these_nonmembers">held</a>,
- <a href="?VARHELP=privacy/sender/reject_these_nonmembers"
- >rejected</a> (bounced), and
- <a href="?VARHELP=privacy/sender/discard_these_nonmembers"
- >discarded</a> addresses. If no match is found, then this action
- is taken.""")),
-
- ('forward_auto_discards', config.Radio, (_('No'), _('Yes')), 0,
- _("""Should messages from non-members, which are automatically
- discarded, be forwarded to the list moderator?""")),
-
- ('nonmember_rejection_notice', config.Text, (10, WIDTH), 1,
- _("""Text to include in any rejection notice to be sent to
- non-members who post to this list. This notice can include
- the list's owner address by %%(listowner)s and replaces the
- internally crafted default message.""")),
-
- ]
-
- recip_rtn = [
- _("""This section allows you to configure various filters based on
- the recipient of the message."""),
-
- _('Recipient filters'),
-
- ('require_explicit_destination', config.Radio,
- (_('No'), _('Yes')), 0,
- _("""Must posts have list named in destination (to, cc) field
- (or be among the acceptable alias names, specified below)?"""),
-
- _("""Many (in fact, most) spams do not explicitly name their
- myriad destinations in the explicit destination addresses - in
- fact often the To: field has a totally bogus address for
- obfuscation. The constraint applies only to the stuff in the
- address before the '@' sign, but still catches all such spams.
-
- <p>The cost is that the list will not accept unhindered any
- postings relayed from other addresses, unless
-
- <ol>
- <li>The relaying address has the same name, or
-
- <li>The relaying address name is included on the options that
- specifies acceptable aliases for the list.
-
- </ol>""")),
-
- ('acceptable_aliases', config.Text, (4, WIDTH), 0,
- _("""Alias names (regexps) which qualify as explicit to or cc
- destination names for this list."""),
-
- _("""Alternate addresses that are acceptable when
- `require_explicit_destination' is enabled. This option takes a
- list of regular expressions, one per line, which is matched
- against every recipient address in the message. The matching is
- performed with Python's re.match() function, meaning they are
- anchored to the start of the string.
-
- <p>For backwards compatibility with Mailman 1.1, if the regexp
- does not contain an `@', then the pattern is matched against just
- the local part of the recipient address. If that match fails, or
- if the pattern does contain an `@', then the pattern is matched
- against the entire recipient address.
-
- <p>Matching against the local part is deprecated; in a future
- release, the pattern will always be matched against the entire
- recipient address.""")),
-
- ('max_num_recipients', config.Number, 5, 0,
- _('Ceiling on acceptable number of recipients for a posting.'),
-
- _('''If a posting has this number, or more, of recipients, it is
- held for admin approval. Use 0 for no ceiling.''')),
- ]
-
- spam_rtn = [
- _("""This section allows you to configure various anti-spam
- filters posting filters, which can help reduce the amount of spam
- your list members end up receiving.
- """),
-
- _('Header filters'),
-
- ('header_filter_rules', config.HeaderFilter, 0, 0,
- _('Filter rules to match against the headers of a message.'),
-
- _("""Each header filter rule has two parts, a list of regular
- expressions, one per line, and an action to take. Mailman
- matches the message's headers against every regular expression in
- the rule and if any match, the message is rejected, held, or
- discarded based on the action you specify. Use <em>Defer</em> to
- temporarily disable a rule.
-
- You can have more than one filter rule for your list. In that
- case, each rule is matched in turn, with processing stopped after
- the first match.
-
- Note that headers are collected from all the attachments
- (except for the mailman administrivia message) and
- matched against the regular expressions. With this feature,
- you can effectively sort out messages with dangerous file
- types or file name extensions.""")),
-
- _('Legacy anti-spam filters'),
-
- ('bounce_matching_headers', config.Text, (6, WIDTH), 0,
- _('Hold posts with header value matching a specified regexp.'),
- _("""Use this option to prohibit posts according to specific
- header values. The target value is a regular-expression for
- matching against the specified header. The match is done
- disregarding letter case. Lines beginning with '#' are ignored
- as comments.
-
- <p>For example:<pre>to: .*@public.com </pre> says to hold all
- postings with a <em>To:</em> mail header containing '@public.com'
- anywhere among the addresses.
-
- <p>Note that leading whitespace is trimmed from the regexp. This
- can be circumvented in a number of ways, e.g. by escaping or
- bracketing it.""")),
- ]
-
- if subcat == 'sender':
- return sender_rtn
- elif subcat == 'recipient':
- return recip_rtn
- elif subcat == 'spam':
- return spam_rtn
- else:
- return subscribing_rtn
-
- def _setValue(self, mlist, property, val, doc):
- # Ignore any hdrfilter_* form variables
- if property.startswith('hdrfilter_'):
- return
- # For subscribe_policy when ALLOW_OPEN_SUBSCRIBE is true, we need to
- # add one to the value because the page didn't present an open list as
- # an option.
- if property == 'subscribe_policy' and not config.ALLOW_OPEN_SUBSCRIBE:
- val += 1
- setattr(mlist, property, val)
-
- # We need to handle the header_filter_rules widgets specially, but
- # everything else can be done by the base class's handleForm() method.
- # However, to do this we need an awful hack. _setValue() and
- # _getValidValue() will essentially ignore any hdrfilter_* form variables.
- # TK: we should call this function only in subcat == 'spam'
- def _handleForm(self, mlist, category, subcat, cgidata, doc):
- # TK: If there is no hdrfilter_* in cgidata, we should not touch
- # the header filter rules.
- if not cgidata.has_key('hdrfilter_rebox_01'):
- return
- # First deal with
- rules = []
- # We start i at 1 and keep going until we no longer find items keyed
- # with the marked tags.
- i = 1
- downi = None
- while True:
- deltag = 'hdrfilter_delete_%02d' % i
- reboxtag = 'hdrfilter_rebox_%02d' % i
- actiontag = 'hdrfilter_action_%02d' % i
- wheretag = 'hdrfilter_where_%02d' % i
- addtag = 'hdrfilter_add_%02d' % i
- newtag = 'hdrfilter_new_%02d' % i
- uptag = 'hdrfilter_up_%02d' % i
- downtag = 'hdrfilter_down_%02d' % i
- i += 1
- # Was this a delete? If so, we can just ignore this entry
- if cgidata.has_key(deltag):
- continue
- # Get the data for the current box
- pattern = cgidata.getvalue(reboxtag)
- try:
- action = int(cgidata.getvalue(actiontag))
- # We'll get a TypeError when the actiontag is missing and the
- # .getvalue() call returns None.
- except (ValueError, TypeError):
- action = config.DEFER
- if pattern is None:
- # We came to the end of the boxes
- break
- if cgidata.has_key(newtag) and not pattern:
- # This new entry is incomplete.
- if i == 2:
- # OK it is the first.
- continue
- doc.addError(_("""Header filter rules require a pattern.
- Incomplete filter rules will be ignored."""))
- continue
- # Make sure the pattern was a legal regular expression
- try:
- re.compile(pattern)
- except (re.error, TypeError):
- safepattern = Utils.websafe(pattern)
- doc.addError(_("""The header filter rule pattern
- '%(safepattern)s' is not a legal regular expression. This
- rule will be ignored."""))
- continue
- # Was this an add item?
- if cgidata.has_key(addtag):
- # Where should the new one be added?
- where = cgidata.getvalue(wheretag)
- if where == 'before':
- # Add a new empty rule box before the current one
- rules.append(('', config.DEFER, True))
- rules.append((pattern, action, False))
- # Default is to add it after...
- else:
- rules.append((pattern, action, False))
- rules.append(('', config.DEFER, True))
- # Was this an up movement?
- elif cgidata.has_key(uptag):
- # As long as this one isn't the first rule, move it up
- if rules:
- rules.insert(-1, (pattern, action, False))
- else:
- rules.append((pattern, action, False))
- # Was this the down movement?
- elif cgidata.has_key(downtag):
- downi = i - 2
- rules.append((pattern, action, False))
- # Otherwise, just retain this one in the list
- else:
- rules.append((pattern, action, False))
- # Move any down button filter rule
- if downi is not None:
- rule = rules[downi]
- del rules[downi]
- rules.insert(downi+1, rule)
- mlist.header_filter_rules = rules
-
- def handleForm(self, mlist, category, subcat, cgidata, doc):
- if subcat == 'spam':
- self._handleForm(mlist, category, subcat, cgidata, doc)
- # Everything else is dealt with by the base handler
- GUIBase.handleForm(self, mlist, category, subcat, cgidata, doc)
diff --git a/mailman/web/Gui/Topics.py b/mailman/web/Gui/Topics.py
deleted file mode 100644
index 00df988be..000000000
--- a/mailman/web/Gui/Topics.py
+++ /dev/null
@@ -1,162 +0,0 @@
-# Copyright (C) 2001-2009 by the Free Software Foundation, Inc.
-#
-# This file is part of GNU Mailman.
-#
-# GNU Mailman 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 3 of the License, or (at your option)
-# any later version.
-#
-# GNU Mailman 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
-# GNU Mailman. If not, see <http://www.gnu.org/licenses/>.
-
-import re
-
-from Mailman import Utils
-from Mailman.Gui.GUIBase import GUIBase
-from Mailman.configuration import config
-from Mailman.i18n import _
-
-OR = '|'
-
-
-
-class Topics(GUIBase):
- def GetConfigCategory(self):
- return 'topics', _('Topics')
-
- def GetConfigInfo(self, mlist, category, subcat=None):
- if category <> 'topics':
- return None
- WIDTH = config.TEXTFIELDWIDTH
-
- return [
- _('List topic keywords'),
-
- ('topics_enabled', config.Radio, (_('Disabled'), _('Enabled')), 0,
- _('''Should the topic filter be enabled or disabled?'''),
-
- _("""The topic filter categorizes each incoming email message
- according to <a
- href="http://www.python.org/doc/current/lib/module-re.html">regular
- expression filters</a> you specify below. If the message's
- <code>Subject:</code> or <code>Keywords:</code> header contains a
- match against a topic filter, the message is logically placed
- into a topic <em>bucket</em>. Each user can then choose to only
- receive messages from the mailing list for a particular topic
- bucket (or buckets). Any message not categorized in a topic
- bucket registered with the user is not delivered to the list.
-
- <p>Note that this feature only works with regular delivery, not
- digest delivery.
-
- <p>The body of the message can also be optionally scanned for
- <code>Subject:</code> and <code>Keywords:</code> headers, as
- specified by the <a
- href="?VARHELP=topics/topics_bodylines_limit">topics_bodylines_limit</a>
- configuration variable.""")),
-
- ('topics_bodylines_limit', config.Number, 5, 0,
- _('How many body lines should the topic matcher scan?'),
-
- _("""The topic matcher will scan this many lines of the message
- body looking for topic keyword matches. Body scanning stops when
- either this many lines have been looked at, or a non-header-like
- body line is encountered. By setting this value to zero, no body
- lines will be scanned (i.e. only the <code>Keywords:</code> and
- <code>Subject:</code> headers will be scanned). By setting this
- value to a negative number, then all body lines will be scanned
- until a non-header-like line is encountered.
- """)),
-
- ('topics', config.Topics, 0, 0,
- _('Topic keywords, one per line, to match against each message.'),
-
- _("""Each topic keyword is actually a regular expression, which is
- matched against certain parts of a mail message, specifically the
- <code>Keywords:</code> and <code>Subject:</code> message headers.
- Note that the first few lines of the body of the message can also
- contain a <code>Keywords:</code> and <code>Subject:</code>
- "header" on which matching is also performed.""")),
-
- ]
-
- def handleForm(self, mlist, category, subcat, cgidata, doc):
- # MAS: Did we come from the authentication page?
- if not cgidata.has_key('topic_box_01'):
- return
- topics = []
- # We start i at 1 and keep going until we no longer find items keyed
- # with the marked tags.
- i = 1
- while True:
- deltag = 'topic_delete_%02d' % i
- boxtag = 'topic_box_%02d' % i
- reboxtag = 'topic_rebox_%02d' % i
- desctag = 'topic_desc_%02d' % i
- wheretag = 'topic_where_%02d' % i
- addtag = 'topic_add_%02d' % i
- newtag = 'topic_new_%02d' % i
- i += 1
- # Was this a delete? If so, we can just ignore this entry
- if cgidata.has_key(deltag):
- continue
- # Get the data for the current box
- name = cgidata.getvalue(boxtag)
- pattern = cgidata.getvalue(reboxtag)
- desc = cgidata.getvalue(desctag)
- if name is None:
- # We came to the end of the boxes
- break
- if cgidata.has_key(newtag) and (not name or not pattern):
- # This new entry is incomplete.
- doc.addError(_("""Topic specifications require both a name and
- a pattern. Incomplete topics will be ignored."""))
- continue
- # Make sure the pattern was a legal regular expression
- name = Utils.websafe(name)
- try:
- orpattern = OR.join(pattern.splitlines())
- re.compile(orpattern)
- except (re.error, TypeError):
- safepattern = Utils.websafe(orpattern)
- doc.addError(_("""The topic pattern '%(safepattern)s' is not a
- legal regular expression. It will be discarded."""))
- continue
- # Was this an add item?
- if cgidata.has_key(addtag):
- # Where should the new one be added?
- where = cgidata.getvalue(wheretag)
- if where == 'before':
- # Add a new empty topics box before the current one
- topics.append(('', '', '', True))
- topics.append((name, pattern, desc, False))
- # Default is to add it after...
- else:
- topics.append((name, pattern, desc, False))
- topics.append(('', '', '', True))
- # Otherwise, just retain this one in the list
- else:
- topics.append((name, pattern, desc, False))
- # Add these topics to the mailing list object, and deal with other
- # options.
- mlist.topics = topics
- try:
- mlist.topics_enabled = int(cgidata.getvalue(
- 'topics_enabled',
- mlist.topics_enabled))
- except ValueError:
- # BAW: should really print a warning
- pass
- try:
- mlist.topics_bodylines_limit = int(cgidata.getvalue(
- 'topics_bodylines_limit',
- mlist.topics_bodylines_limit))
- except ValueError:
- # BAW: should really print a warning
- pass
diff --git a/mailman/web/Gui/Usenet.py b/mailman/web/Gui/Usenet.py
deleted file mode 100644
index 9c1b50809..000000000
--- a/mailman/web/Gui/Usenet.py
+++ /dev/null
@@ -1,140 +0,0 @@
-# Copyright (C) 2001-2009 by the Free Software Foundation, Inc.
-#
-# This file is part of GNU Mailman.
-#
-# GNU Mailman 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 3 of the License, or (at your option)
-# any later version.
-#
-# GNU Mailman 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
-# GNU Mailman. If not, see <http://www.gnu.org/licenses/>.
-
-from Mailman.Gui.GUIBase import GUIBase
-from Mailman.configuration import config
-from Mailman.i18n import _
-
-
-
-class Usenet(GUIBase):
- def GetConfigCategory(self):
- return 'gateway', _('Mail&lt;-&gt;News&nbsp;gateways')
-
- def GetConfigInfo(self, mlist, category, subcat=None):
- if category <> 'gateway':
- return None
-
- WIDTH = config.TEXTFIELDWIDTH
- VERTICAL = 1
-
- return [
- _('Mail-to-News and News-to-Mail gateway services.'),
-
- _('News server settings'),
-
- ('nntp_host', config.String, WIDTH, 0,
- _('The hostname of the machine your news server is running on.'),
- _('''This value may be either the name of your news server, or
- optionally of the format name:port, where port is a port number.
-
- The news server is not part of Mailman proper. You have to
- already have access to an NNTP server, and that NNTP server must
- recognize the machine this mailing list runs on as a machine
- capable of reading and posting news.''')),
-
- ('linked_newsgroup', config.String, WIDTH, 0,
- _('The name of the Usenet group to gateway to and/or from.')),
-
- ('gateway_to_news', config.Toggle, (_('No'), _('Yes')), 0,
- _('''Should new posts to the mailing list be sent to the
- newsgroup?''')),
-
- ('gateway_to_mail', config.Toggle, (_('No'), _('Yes')), 0,
- _('''Should new posts to the newsgroup be sent to the mailing
- list?''')),
-
- _('Forwarding options'),
-
- ('news_moderation', config.Radio,
- (_('None'), _('Open list, moderated group'), _('Moderated')),
- VERTICAL,
-
- _("""The moderation policy of the newsgroup."""),
-
- _("""This setting determines the moderation policy of the
- newsgroup and its interaction with the moderation policy of the
- mailing list. This only applies to the newsgroup that you are
- gatewaying <em>to</em>, so if you are only gatewaying from
- Usenet, or the newsgroup you are gatewaying to is not moderated,
- set this option to <em>None</em>.
-
- <p>If the newsgroup is moderated, you can set this mailing list
- up to be the moderation address for the newsgroup. By selecting
- <em>Moderated</em>, an additional posting hold will be placed in
- the approval process. All messages posted to the mailing list
- will have to be approved before being sent on to the newsgroup,
- or to the mailing list membership.
-
- <p><em>Note that if the message has an <tt>Approved</tt> header
- with the list's administrative password in it, this hold test
- will be bypassed, allowing privileged posters to send messages
- directly to the list and the newsgroup.</em>
-
- <p>Finally, if the newsgroup is moderated, but you want to have
- an open posting policy anyway, you should select <em>Open list,
- moderated group</em>. The effect of this is to use the normal
- Mailman moderation facilities, but to add an <tt>Approved</tt>
- header to all messages that are gatewayed to Usenet.""")),
-
- ('news_prefix_subject_too', config.Toggle, (_('No'), _('Yes')), 0,
- _('Prefix <tt>Subject:</tt> headers on postings gated to news?'),
- _("""Mailman prefixes <tt>Subject:</tt> headers with
- <a href="?VARHELP=general/subject_prefix">text you can
- customize</a> and normally, this prefix shows up in messages
- gatewayed to Usenet. You can set this option to <em>No</em> to
- disable the prefix on gated messages. Of course, if you turn off
- normal <tt>Subject:</tt> prefixes, they won't be prefixed for
- gated messages either.""")),
-
- _('Mass catch up'),
-
- ('_mass_catchup', config.Toggle, (_('No'), _('Yes')), 0,
- _('Should Mailman perform a <em>catchup</em> on the newsgroup?'),
- _('''When you tell Mailman to perform a catchup on the newsgroup,
- this means that you want to start gating messages to the mailing
- list with the next new message found. All earlier messages on
- the newsgroup will be ignored. This is as if you were reading
- the newsgroup yourself, and you marked all current messages as
- <em>read</em>. By catching up, your mailing list members will
- not see any of the earlier messages.''')),
-
- ]
-
- def _setValue(self, mlist, property, val, doc):
- # Watch for the special, immediate action attributes
- if property == '_mass_catchup' and val:
- mlist.usenet_watermark = None
- doc.AddItem(_('Mass catchup completed'))
- else:
- GUIBase._setValue(self, mlist, property, val, doc)
-
- def _postValidate(self, mlist, doc):
- # Make sure that if we're gating, that the newsgroups and host
- # information are not blank.
- if mlist.gateway_to_news or mlist.gateway_to_mail:
- # BAW: It's too expensive and annoying to ensure that both the
- # host is valid and that the newsgroup is a valid n.g. on the
- # server. This should be good enough.
- if not mlist.nntp_host or not mlist.linked_newsgroup:
- doc.addError(_("""You cannot enable gatewaying unless both the
- <a href="?VARHELP=gateway/nntp_host">news server field</a> and
- the <a href="?VARHELP=gateway/linked_newsgroup">linked
- newsgroup</a> fields are filled in."""))
- # And reset these values
- mlist.gateway_to_news = 0
- mlist.gateway_to_mail = 0
diff --git a/mailman/web/Gui/__init__.py b/mailman/web/Gui/__init__.py
deleted file mode 100644
index 2e12526c0..000000000
--- a/mailman/web/Gui/__init__.py
+++ /dev/null
@@ -1,33 +0,0 @@
-# Copyright (C) 2001-2009 by the Free Software Foundation, Inc.
-#
-# This file is part of GNU Mailman.
-#
-# GNU Mailman 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 3 of the License, or (at your option)
-# any later version.
-#
-# GNU Mailman 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
-# GNU Mailman. If not, see <http://www.gnu.org/licenses/>.
-
-from Archive import Archive
-from Autoresponse import Autoresponse
-from Bounce import Bounce
-from Digest import Digest
-from General import General
-from Membership import Membership
-from NonDigest import NonDigest
-from Passwords import Passwords
-from Privacy import Privacy
-from Topics import Topics
-from Usenet import Usenet
-from Language import Language
-from ContentFilter import ContentFilter
-
-# Don't export this symbol outside the package
-del GUIBase