aboutsummaryrefslogtreecommitdiffstats
path: root/Mailman
diff options
context:
space:
mode:
Diffstat (limited to 'Mailman')
-rw-r--r--Mailman/Cgi/subscribe.py2
-rw-r--r--Mailman/Commands/cmd_confirm.py2
-rw-r--r--Mailman/Handlers/ToDigest.py39
-rw-r--r--Mailman/Queue/CommandRunner.py25
-rw-r--r--Mailman/Utils.py90
5 files changed, 92 insertions, 66 deletions
diff --git a/Mailman/Cgi/subscribe.py b/Mailman/Cgi/subscribe.py
index d0a477d7..8ae9564f 100644
--- a/Mailman/Cgi/subscribe.py
+++ b/Mailman/Cgi/subscribe.py
@@ -117,12 +117,10 @@ def process_form(mlist, doc, cgidata, lang):
remote = os.environ.get('REMOTE_HOST',
os.environ.get('REMOTE_ADDR',
'unidentified origin'))
-
# Was an attempt made to subscribe the list to itself?
if email == mlist.GetListEmail():
syslog('mischief', 'Attempt to self subscribe %s: %s', email, remote)
results.append(_('You may not subscribe a list to itself!'))
-
# If the user did not supply a password, generate one for him
password = cgidata.getvalue('pw')
confirmed = cgidata.getvalue('pw-conf')
diff --git a/Mailman/Commands/cmd_confirm.py b/Mailman/Commands/cmd_confirm.py
index f93e7b9b..e66c52b5 100644
--- a/Mailman/Commands/cmd_confirm.py
+++ b/Mailman/Commands/cmd_confirm.py
@@ -61,7 +61,7 @@ Your request has been forwarded to the list moderator for approval."""))
except Errors.NotAMemberError:
# They've already been unsubscribed
res.results.append(_("""\
-You are not current a member. Have you already unsubscribed or changed
+You are not currently a member. Have you already unsubscribed or changed
your email address?"""))
except Errors.HostileSubscriptionError:
res.results.append(_("""\
diff --git a/Mailman/Handlers/ToDigest.py b/Mailman/Handlers/ToDigest.py
index 79090051..3506beaa 100644
--- a/Mailman/Handlers/ToDigest.py
+++ b/Mailman/Handlers/ToDigest.py
@@ -55,6 +55,12 @@ _ = i18n._
UEMPTYSTRING = u''
EMPTYSTRING = ''
+try:
+ True, False
+except NameError:
+ True = 1
+ False = 0
+
def process(mlist, msg, msgdata):
@@ -68,7 +74,7 @@ def process(mlist, msg, msgdata):
finally:
os.umask(omask)
g = Generator(mboxfp)
- g.flatten(msg, unixfrom=1)
+ g.flatten(msg, unixfrom=True)
# Calculate the current size of the accumulation file. This will not tell
# us exactly how big the MIME, rfc1153, or any other generated digest
# message will be, but it's the most easily available metric to decide
@@ -88,30 +94,30 @@ def process(mlist, msg, msgdata):
def send_digests(mlist, mboxfp):
# Set the digest volume and time
if mlist.digest_last_sent_at:
- bump = 0
+ bump = False
# See if we should bump the digest volume number
timetup = time.localtime(mlist.digest_last_sent_at)
now = time.localtime(time.time())
freq = mlist.digest_volume_frequency
if freq == 0 and timetup[0] < now[0]:
# Yearly
- bump = 1
+ bump = True
elif freq == 1 and timetup[1] <> now[1]:
# Monthly, but we take a cheap way to calculate this. We assume
# that the clock isn't going to be reset backwards.
- bump = 1
+ bump = True
elif freq == 2 and (timetup[1] % 4 <> now[1] % 4):
# Quarterly, same caveat
- bump = 1
+ bump = True
elif freq == 3:
# Once again, take a cheap way of calculating this
weeknum_last = int(time.strftime('%W', timetup))
weeknum_now = int(time.strftime('%W', now))
if weeknum_now > weeknum_last or timetup[0] > now[0]:
- bump = 1
+ bump = True
elif freq == 4 and timetup[7] <> now[7]:
# Daily
- bump = 1
+ bump = True
if bump:
mlist.bump_digest_volume()
mlist.digest_last_sent_at = time.time()
@@ -230,11 +236,11 @@ def send_i18n_digests(mlist, mboxfp):
else:
slines[-1] += username
# Add this subject to the accumulating topics
- first = 1
+ first = True
for line in slines:
if first:
print >> toc, ' ', line
- first = 0
+ first = False
else:
print >> toc, ' ', line.lstrip()
# We do not want all the headers of the original message to leak
@@ -247,7 +253,7 @@ def send_i18n_digests(mlist, mboxfp):
all_keepers = {}
for header in (mm_cfg.MIME_DIGEST_KEEP_HEADERS +
mm_cfg.PLAIN_DIGEST_KEEP_HEADERS):
- all_keepers[header] = 1
+ all_keepers[header] = True
all_keepers = all_keepers.keys()
for keep in all_keepers:
keeper[keep] = msg.get_all(keep, [])
@@ -281,13 +287,13 @@ def send_i18n_digests(mlist, mboxfp):
# Now go through and add each message
mimedigest = MIMEBase('multipart', 'digest')
mimemsg.attach(mimedigest)
- first = 1
+ first = True
for msg in messages:
# MIME
mimedigest.attach(MIMEMessage(msg))
# rfc1153
if first:
- first = 0
+ first = False
else:
print >> plainmsg, separator30
print >> plainmsg
@@ -300,7 +306,10 @@ def send_i18n_digests(mlist, mboxfp):
uh = '\n\t'.join(uh.split('\n'))
print >> plainmsg, uh
print >> plainmsg
- print >> plainmsg, msg.get_payload(decode=1)
+ payload = msg.get_payload(decode=True)
+ print >> plainmsg, payload
+ if not payload.endswith('\n'):
+ print >> plainmsg
# Now add the footer
if mlist.digest_footer:
footertxt = decorate(mlist, mlist.digest_footer, _('digest footer'))
@@ -356,13 +365,13 @@ def send_i18n_digests(mlist, mboxfp):
virginq.enqueue(mimemsg,
recips=mimerecips,
listname=mlist.internal_name(),
- isdigest=1)
+ isdigest=True)
# RFC 1153
rfc1153msg.set_payload(plainmsg.getvalue(), lcset)
virginq.enqueue(rfc1153msg,
recips=plainrecips,
listname=mlist.internal_name(),
- isdigest=1)
+ isdigest=True)
diff --git a/Mailman/Queue/CommandRunner.py b/Mailman/Queue/CommandRunner.py
index 5bc1599b..524ea575 100644
--- a/Mailman/Queue/CommandRunner.py
+++ b/Mailman/Queue/CommandRunner.py
@@ -26,8 +26,8 @@
# BAW: get rid of this when we Python 2.2 is a minimum requirement.
from __future__ import nested_scopes
-import sys
import re
+import sys
from types import StringType, UnicodeType
from Mailman import mm_cfg
@@ -39,12 +39,19 @@ from Mailman.Queue.Runner import Runner
from Mailman.Logging.Syslog import syslog
from Mailman import LockFile
+from email.Header import decode_header, make_header, Header
from email.MIMEText import MIMEText
from email.MIMEMessage import MIMEMessage
from email.Iterators import typed_subpart_iterator
NL = '\n'
+try:
+ True, False
+except NameError:
+ True = 1
+ False = 0
+
class Results:
@@ -61,9 +68,13 @@ class Results:
self.ignored = []
self.lineno = 0
self.subjcmdretried = 0
- self.respond = 1
+ self.respond = True
+ # Extract the subject header and do RFC 2047 decoding. Note that
+ # Python 2.1's unicode() builtin doesn't call obj.__unicode__().
+ subj = msg.get('subject', '')
+ subj = make_header(decode_header(subj)).__unicode__()
# Always process the Subject: header first
- self.commands.append(msg.get('subject', ''))
+ self.commands.append(subj)
# Find the first text/plain part
part = None
for part in typed_subpart_iterator(msg, 'text', 'plain'):
@@ -86,7 +97,7 @@ class Results:
def process(self):
# Now, process each line until we find an error. The first
# non-command line found stops processing.
- stop = 0
+ stop = False
for line in self.commands:
if line and line.strip():
args = line.split()
@@ -195,14 +206,14 @@ class CommandRunner(Runner):
if ack <> 'yes' and precedence in ('bulk', 'junk', 'list'):
syslog('vette', 'Precedence: %s message discarded by: %s',
precedence, mlist.GetRequestEmail())
- return 0
+ return False
# Do replybot for commands
mlist.Load()
Replybot.process(mlist, msg, msgdata)
if mlist.autorespond_requests == 1:
syslog('vette', 'replied and discard')
# w/discard
- return 0
+ return False
# Now craft the response
res = Results(mlist, msg, msgdata)
# BAW: Not all the functions of this qrunner require the list to be
@@ -212,7 +223,7 @@ class CommandRunner(Runner):
mlist.Lock(timeout=mm_cfg.LIST_LOCK_TIMEOUT)
except LockFile.TimeOutError:
# Oh well, try again later
- return 1
+ return True
# This message will have been delivered to one of mylist-request,
# mylist-join, or mylist-leave, and the message metadata will contain
# a key to which one was used.
diff --git a/Mailman/Utils.py b/Mailman/Utils.py
index 57c87c36..ceb63f66 100644
--- a/Mailman/Utils.py
+++ b/Mailman/Utils.py
@@ -50,6 +50,12 @@ from Mailman import Errors
from Mailman import Site
from Mailman.SafeDict import SafeDict
+try:
+ True, False
+except NameError:
+ True = 1
+ False = 0
+
EMPTYSTRING = ''
NL = '\n'
DOT = '.'
@@ -74,8 +80,8 @@ def list_exists(listname):
for ext in ('.pck', '.pck.last', '.db', '.db.last'):
dbfile = os.path.join(basepath, 'config' + ext)
if os.path.exists(dbfile):
- return 1
- return 0
+ return True
+ return False
def list_names():
@@ -86,7 +92,7 @@ def list_names():
# a much more naive implementation than say, Emacs's fill-paragraph!
-def wrap(text, column=70, honor_leading_ws=1):
+def wrap(text, column=70, honor_leading_ws=True):
"""Wrap and fill the text to the specified column.
Wrapping is always in effect, although if it is not possible to wrap a
@@ -103,15 +109,15 @@ def wrap(text, column=70, honor_leading_ws=1):
for para in paras:
# fill
lines = []
- fillprev = 0
+ fillprev = False
for line in para.split(NL):
if not line:
lines.append(line)
continue
if honor_leading_ws and line[0] in whitespace:
- fillthis = 0
+ fillthis = False
else:
- fillthis = 1
+ fillthis = True
if fillprev and fillthis:
# if the previous line should be filled, then just append a
# single space, and the rest of the current line
@@ -130,33 +136,33 @@ def wrap(text, column=70, honor_leading_ws=1):
bol = column
# find the last whitespace character
while bol > 0 and text[bol] not in whitespace:
- bol = bol - 1
+ bol -= 1
# now find the last non-whitespace character
eol = bol
while eol > 0 and text[eol] in whitespace:
- eol = eol - 1
+ eol -= 1
# watch out for text that's longer than the column width
if eol == 0:
# break on whitespace after column
eol = column
while eol < len(text) and \
text[eol] not in whitespace:
- eol = eol + 1
+ eol += 1
bol = eol
while bol < len(text) and \
text[bol] in whitespace:
- bol = bol + 1
- bol = bol - 1
+ bol += 1
+ bol -= 1
line = text[:eol+1] + '\n'
# find the next non-whitespace character
- bol = bol + 1
+ bol += 1
while bol < len(text) and text[bol] in whitespace:
- bol = bol + 1
+ bol += 1
text = text[bol:]
- wrapped = wrapped + line
- wrapped = wrapped + '\n'
+ wrapped += line
+ wrapped += '\n'
# end while text
- wrapped = wrapped + '\n'
+ wrapped += '\n'
# end for text in lines
# the last two newlines are bogus
return wrapped[:-2]
@@ -218,7 +224,7 @@ def GetPathPieces(envar='PATH_INFO'):
-def ScriptURL(target, web_page_url=None, absolute=0):
+def ScriptURL(target, web_page_url=None, absolute=False):
"""target - scriptname only, nothing extra
web_page_url - the list's configvar of the same name
absolute - a flag which if set, generates an absolute url
@@ -267,15 +273,15 @@ def GetPossibleMatchingAddrs(name):
-def List2Dict(list, foldcase=0):
+def List2Dict(L, foldcase=False):
"""Return a dict keyed by the entries in the list passed to it."""
d = {}
if foldcase:
- for i in list:
- d[i.lower()] = 1
+ for i in L:
+ d[i.lower()] = True
else:
- for i in list:
- d[i] = 1
+ for i in L:
+ d[i] = True
return d
@@ -293,7 +299,7 @@ del c, v
def MakeRandomPassword(length=6):
syls = []
- while len(syls)*2 < length:
+ while len(syls) * 2 < length:
syls.append(random.choice(_syllables))
return EMPTYSTRING.join(syls)[:length]
@@ -302,20 +308,22 @@ def GetRandomSeed():
chr2 = int(random.random() * 52)
def mkletter(c):
if 0 <= c < 26:
- c = c + 65
+ c += 65
if 26 <= c < 52:
- c = c - 26 + 97
+ #c = c - 26 + 97
+ c += 71
return c
return "%c%c" % tuple(map(mkletter, (chr1, chr2)))
-def set_global_password(pw, siteadmin=1):
+def set_global_password(pw, siteadmin=True):
if siteadmin:
filename = mm_cfg.SITE_PW_FILE
else:
filename = mm_cfg.LISTCREATOR_PW_FILE
- omask = os.umask(026) # rw-r-----
+ # rw-r-----
+ omask = os.umask(026)
try:
fp = open(filename, 'w')
fp.write(sha.new(pw).hexdigest() + '\n')
@@ -324,7 +332,7 @@ def set_global_password(pw, siteadmin=1):
os.umask(omask)
-def get_global_password(siteadmin=1):
+def get_global_password(siteadmin=True):
if siteadmin:
filename = mm_cfg.SITE_PW_FILE
else:
@@ -340,7 +348,7 @@ def get_global_password(siteadmin=1):
return challenge
-def check_global_password(response, siteadmin=1):
+def check_global_password(response, siteadmin=True):
challenge = get_global_password(siteadmin)
if challenge is None:
return None
@@ -355,7 +363,7 @@ def websafe(s):
# Just changing these two functions should be enough to control the way
# that email address obscuring is handled.
-def ObscureEmail(addr, for_text=0):
+def ObscureEmail(addr, for_text=False):
"""Make email address unrecognizable to web spiders, but invertable.
When for_text option is set (not default), make a sentence fragment
@@ -373,7 +381,7 @@ def UnobscureEmail(addr):
-def maketext(templatefile, dict=None, raw=0, lang=None, mlist=None):
+def maketext(templatefile, dict=None, raw=False, lang=None, mlist=None):
# Make some text from a template file. The order of searches depends on
# whether mlist and lang are provided. Once the templatefile is found,
# string substitution is performed by interpolation in `dict'. If `raw'
@@ -508,12 +516,12 @@ def is_administrivia(msg):
if line.strip():
linecnt += 1
if linecnt > mm_cfg.DEFAULT_MAIL_COMMANDS_MAX_LINES:
- return 0
+ return False
lines.append(line)
bodytext = NL.join(lines)
# See if the body text has only one word, and that word is administrivia
if ADMINDATA.has_key(bodytext.strip().lower()):
- return 1
+ return True
# Look at the first N lines and see if there is any administrivia on the
# line. BAW: N is currently hardcoded to 5. str-ify the Subject: header
# because it may be an email.Header.Header instance rather than a string.
@@ -532,12 +540,12 @@ def is_administrivia(msg):
# here.
if words[0] == 'set' and words[2] not in ('on', 'off'):
continue
- return 1
- return 0
+ return True
+ return False
-def GetRequestURI(fallback=None, escape=1):
+def GetRequestURI(fallback=None, escape=True):
"""Return the full virtual path this CGI script was invoked with.
Newer web servers seems to supply this info in the REQUEST_URI
@@ -563,7 +571,7 @@ def GetRequestURI(fallback=None, escape=1):
# Wait on a dictionary of child pids
-def reap(kids, func=None, once=0):
+def reap(kids, func=None, once=False):
while kids:
if func:
func()
@@ -685,7 +693,7 @@ def dollar_identifiers(s):
"""Return the set (dictionary) of identifiers found in a $-string."""
d = {}
for name in filter(None, [b or c or None for a, b, c in dre.findall(s)]):
- d[name] = 1
+ d[name] = True
return d
@@ -693,7 +701,7 @@ def percent_identifiers(s):
"""Return the set (dictionary) of identifiers found in a %-string."""
d = {}
for name in cre.findall(s):
- d[name] = 1
+ d[name] = True
return d
@@ -708,7 +716,7 @@ def canonstr(s, lang=None):
newparts.append(chr(i))
else:
newparts.append(unichr(i))
- while 1:
+ while True:
newparts.append(parts.pop(0))
if not parts:
break
@@ -732,7 +740,7 @@ def canonstr(s, lang=None):
# English (us-ascii). This seems like a practical compromise so that
# non-ASCII characters in names can be used in English lists w/o having to
# change the global charset for English from us-ascii (which I
- # superstitiously think my have unintended consequences).
+ # superstitiously think may have unintended consequences).
if lang is None:
charset = 'iso-8859-1'
else: