aboutsummaryrefslogtreecommitdiffstats
path: root/Mailman
diff options
context:
space:
mode:
Diffstat (limited to 'Mailman')
-rwxr-xr-xMailman/Defaults.py.in9
-rw-r--r--Mailman/Digester.py24
-rw-r--r--Mailman/Gui/Archive.py14
-rw-r--r--Mailman/Gui/Digest.py38
-rw-r--r--Mailman/LockFile.py2
-rw-r--r--Mailman/Logging/StampedLogger.py26
-rw-r--r--Mailman/MailList.py2
-rw-r--r--Mailman/Message.py2
-rw-r--r--Mailman/Utils.py15
9 files changed, 73 insertions, 59 deletions
diff --git a/Mailman/Defaults.py.in b/Mailman/Defaults.py.in
index 5e158e5b..fabd95bd 100755
--- a/Mailman/Defaults.py.in
+++ b/Mailman/Defaults.py.in
@@ -166,6 +166,15 @@ HTML_TO_PLAIN_TEXT_COMMAND = '/usr/bin/lynx -dump %(filename)s'
# character that doesn't match this class. Do not include '/' in this list.
ACCEPTABLE_LISTNAME_CHARACTERS = '[-+_.=a-z0-9]'
+# The number of characters in the longest listname in the installation. The
+# fix for LP: #1780874 truncates list names in web URLs to this length to avoid
+# a content spoofing vulnerability. If this is left at its default value of
+# 0, the length of the longest listname is calculated on every web access.
+# This can have performance implications in installations with a very large
+# number of lists. To use this feature to avoid the calculation, set this to
+# a number equal to the length of the longest expected valid list name.
+MAX_LISTNAME_LENGTH = 0
+
# Shall the user's real names be displayed along with their email addresses
# in list rosters? Defaults to No to preserve prior behavior.
ROSTER_DISPLAY_REALNAME = No
diff --git a/Mailman/Digester.py b/Mailman/Digester.py
index 8a65043b..3dc7ce49 100644
--- a/Mailman/Digester.py
+++ b/Mailman/Digester.py
@@ -31,20 +31,20 @@ from Mailman.i18n import _
class Digester:
def InitVars(self):
- # Configurable
- self.digestable = mm_cfg.DEFAULT_DIGESTABLE
- self.digest_is_default = mm_cfg.DEFAULT_DIGEST_IS_DEFAULT
- self.mime_is_default_digest = mm_cfg.DEFAULT_MIME_IS_DEFAULT_DIGEST
- self.digest_size_threshhold = mm_cfg.DEFAULT_DIGEST_SIZE_THRESHHOLD
- self.digest_send_periodic = mm_cfg.DEFAULT_DIGEST_SEND_PERIODIC
- self.next_post_number = 1
- self.digest_header = mm_cfg.DEFAULT_DIGEST_HEADER
- self.digest_footer = mm_cfg.DEFAULT_DIGEST_FOOTER
+ # Configurable
+ self.digestable = mm_cfg.DEFAULT_DIGESTABLE
+ self.digest_is_default = mm_cfg.DEFAULT_DIGEST_IS_DEFAULT
+ self.mime_is_default_digest = mm_cfg.DEFAULT_MIME_IS_DEFAULT_DIGEST
+ self.digest_size_threshhold = mm_cfg.DEFAULT_DIGEST_SIZE_THRESHHOLD
+ self.digest_send_periodic = mm_cfg.DEFAULT_DIGEST_SEND_PERIODIC
+ self.next_post_number = 1
+ self.digest_header = mm_cfg.DEFAULT_DIGEST_HEADER
+ self.digest_footer = mm_cfg.DEFAULT_DIGEST_FOOTER
self.digest_volume_frequency = mm_cfg.DEFAULT_DIGEST_VOLUME_FREQUENCY
- # Non-configurable.
+ # Non-configurable.
self.one_last_digest = {}
- self.digest_members = {}
- self.next_digest_number = 1
+ self.digest_members = {}
+ self.next_digest_number = 1
self.digest_last_sent_at = 0
def send_digest_now(self):
diff --git a/Mailman/Gui/Archive.py b/Mailman/Gui/Archive.py
index fc313c00..8167a001 100644
--- a/Mailman/Gui/Archive.py
+++ b/Mailman/Gui/Archive.py
@@ -27,18 +27,18 @@ class Archive(GUIBase):
def GetConfigInfo(self, mlist, category, subcat=None):
if category <> 'archive':
return None
- return [
+ return [
_("List traffic archival policies."),
- ('archive', mm_cfg.Toggle, (_('No'), _('Yes')), 0,
- _('Archive messages?')),
+ ('archive', mm_cfg.Toggle, (_('No'), _('Yes')), 0,
+ _('Archive messages?')),
- ('archive_private', mm_cfg.Radio, (_('public'), _('private')), 0,
+ ('archive_private', mm_cfg.Radio, (_('public'), _('private')), 0,
_('Is archive file source for public or private archival?')),
- ('archive_volume_frequency', mm_cfg.Radio,
+ ('archive_volume_frequency', mm_cfg.Radio,
(_('Yearly'), _('Monthly'), _('Quarterly'),
_('Weekly'), _('Daily')),
0,
- _('How often should a new archive volume be started?')),
- ]
+ _('How often should a new archive volume be started?')),
+ ]
diff --git a/Mailman/Gui/Digest.py b/Mailman/Gui/Digest.py
index 55cee19d..9eafb1d2 100644
--- a/Mailman/Gui/Digest.py
+++ b/Mailman/Gui/Digest.py
@@ -40,37 +40,37 @@ class Digest(GUIBase):
return None
WIDTH = mm_cfg.TEXTFIELDWIDTH
- info = [
+ info = [
_("Batched-delivery digest characteristics."),
- ('digestable', mm_cfg.Toggle, (_('No'), _('Yes')), 1,
- _('Can list members choose to receive list traffic '
- 'bunched in digests?')),
+ ('digestable', mm_cfg.Toggle, (_('No'), _('Yes')), 1,
+ _('Can list members choose to receive list traffic '
+ 'bunched in digests?')),
- ('digest_is_default', mm_cfg.Radio,
- (_('Regular'), _('Digest')), 0,
- _('Which delivery mode is the default for new users?')),
+ ('digest_is_default', mm_cfg.Radio,
+ (_('Regular'), _('Digest')), 0,
+ _('Which delivery mode is the default for new users?')),
- ('mime_is_default_digest', mm_cfg.Radio,
- (_('Plain'), _('MIME')), 0,
- _('When receiving digests, which format is default?')),
+ ('mime_is_default_digest', mm_cfg.Radio,
+ (_('Plain'), _('MIME')), 0,
+ _('When receiving digests, which format is default?')),
- ('digest_size_threshhold', mm_cfg.Number, 3, 0,
- _('How big in Kb should a digest be before it gets sent out?'
+ ('digest_size_threshhold', mm_cfg.Number, 3, 0,
+ _('How big in Kb should a digest be before it gets sent out?'
' 0 implies no maximum size.')),
- ('digest_send_periodic', mm_cfg.Radio, (_('No'), _('Yes')), 1,
- _('Should a digest be dispatched daily when the size threshold '
- "isn't reached?")),
+ ('digest_send_periodic', mm_cfg.Radio, (_('No'), _('Yes')), 1,
+ _('Should a digest be dispatched daily when the size threshold '
+ "isn't reached?")),
('digest_header', mm_cfg.Text, (4, WIDTH), 0,
- _('Header added to every digest'),
+ _('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', mm_cfg.Text, (4, WIDTH), 0,
- _('Footer added to every digest'),
+ ('digest_footer', mm_cfg.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)),
@@ -89,7 +89,7 @@ class Digest(GUIBase):
('_send_digest_now', mm_cfg.Toggle, (_('No'), _('Yes')), 0,
_('''Should Mailman send the next digest right now, if it is not
empty?''')),
- ]
+ ]
## if mm_cfg.OWNERS_CAN_ENABLE_PERSONALIZATION:
## info.extend([
diff --git a/Mailman/LockFile.py b/Mailman/LockFile.py
index d7cd9252..45d92cd6 100644
--- a/Mailman/LockFile.py
+++ b/Mailman/LockFile.py
@@ -195,7 +195,7 @@ class LockFile:
self.__logprefix = os.path.split(self.__lockfile)[1]
# For transferring ownership across a fork.
self.__owned = True
-
+
def __repr__(self):
return '<LockFile %s: %s [%s: %ssec] pid=%s>' % (
id(self), self.__lockfile,
diff --git a/Mailman/Logging/StampedLogger.py b/Mailman/Logging/StampedLogger.py
index 2657d7fc..5d259e38 100644
--- a/Mailman/Logging/StampedLogger.py
+++ b/Mailman/Logging/StampedLogger.py
@@ -42,14 +42,14 @@ class StampedLogger(Logger):
"""
def __init__(self, category, label=None, manual_reprime=0, nofail=1,
immediate=1):
- """If specified, optional label is included after timestamp.
+ """If specified, optional label is included after timestamp.
Other options are passed to the Logger class initializer.
"""
- self.__label = label
+ self.__label = label
self.__manual_reprime = manual_reprime
self.__primed = 1
self.__bol = 1
- Logger.__init__(self, category, nofail, immediate)
+ Logger.__init__(self, category, nofail, immediate)
def reprime(self):
"""Reset so timestamp will be included with next write."""
@@ -77,13 +77,13 @@ class StampedLogger(Logger):
self.__bol = 0
def writelines(self, lines):
- first = 1
- for l in lines:
- if first:
- self.write(l)
- first = 0
- else:
- if l and l[0] not in [' ', '\t', '\n']:
- Logger.write(self, ' ' + l)
- else:
- Logger.write(self, l)
+ first = 1
+ for l in lines:
+ if first:
+ self.write(l)
+ first = 0
+ else:
+ if l and l[0] not in [' ', '\t', '\n']:
+ Logger.write(self, ' ' + l)
+ else:
+ Logger.write(self, l)
diff --git a/Mailman/MailList.py b/Mailman/MailList.py
index d74978af..f4b38b49 100644
--- a/Mailman/MailList.py
+++ b/Mailman/MailList.py
@@ -424,7 +424,7 @@ class MailList(HTMLFormatter, Deliverer, ListAdmin,
self.dmarc_none_moderation_action = (
mm_cfg.DEFAULT_DMARC_NONE_MODERATION_ACTION)
self.dmarc_moderation_notice = ''
- self.dmarc_moderation_addresses = []
+ self.dmarc_moderation_addresses = []
self.dmarc_wrapped_message_text = (
mm_cfg.DEFAULT_DMARC_WRAPPED_MESSAGE_TEXT)
self.equivalent_domains = (
diff --git a/Mailman/Message.py b/Mailman/Message.py
index 2d68fd8f..f4ca20c7 100644
--- a/Mailman/Message.py
+++ b/Mailman/Message.py
@@ -236,7 +236,7 @@ class Message(email.Message.Message):
Mailman.Message.Generator.
Operates like email.Message.Message.as_string, only
- using Mailman's Message.Generator class. Only the top headers will
+ using Mailman's Message.Generator class. Only the top headers will
get folded.
"""
fp = StringIO()
diff --git a/Mailman/Utils.py b/Mailman/Utils.py
index 605d0976..10629fc4 100644
--- a/Mailman/Utils.py
+++ b/Mailman/Utils.py
@@ -292,11 +292,16 @@ def GetPathPieces(envar='PATH_INFO'):
remote)
# Check for listname injections that won't be websafed.
pieces = [p for p in path.split('/') if p]
- # Get the longest listname or 20 if none.
- if list_names():
- longest = max([len(x) for x in list_names()])
+ # Get the longest listname or 20 if none or use MAX_LISTNAME_LENGTH if
+ # provided > 0.
+ if mm_cfg.MAX_LISTNAME_LENGTH > 0:
+ longest = mm_cfg.MAX_LISTNAME_LENGTH
else:
- longest = 20
+ lst_names = list_names()
+ if lst_names:
+ longest = max([len(x) for x in lst_names])
+ else:
+ longest = 20
if pieces and len(pieces[0]) > longest:
syslog('mischief',
'Hostile listname: listname=%s: remote=%s', pieces[0], remote)
@@ -1529,7 +1534,7 @@ def banned_ip(ip):
ptr = ipaddress.ip_address(uip).reverse_pointer
except ValueError:
return False
- lookup = '{0}.zen.spamhaus.org'.format('.'.join(ptr.split('.')[:-2]))
+ lookup = '{0}.zen.spamhaus.org'.format('.'.join(ptr.split('.')[:-2]))
else:
parts = ip.split('.')
if len(parts) != 4: