diff options
-rwxr-xr-x | bin/add_members | 22 | ||||
-rwxr-xr-x | bin/check_perms | 45 | ||||
-rw-r--r-- | bin/genaliases | 52 | ||||
-rwxr-xr-x | bin/list_members | 26 | ||||
-rwxr-xr-x | bin/remove_members | 51 | ||||
-rwxr-xr-x | bin/transcheck | 15 |
6 files changed, 130 insertions, 81 deletions
diff --git a/bin/add_members b/bin/add_members index ad4f43b8..92b3ca04 100755 --- a/bin/add_members +++ b/bin/add_members @@ -1,19 +1,19 @@ #! @PYTHON@ # -# Copyright (C) 1998,1999,2000,2001,2002 by the Free Software Foundation, Inc. +# Copyright (C) 1998-2003 by the Free Software Foundation, Inc. # # This program 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 2 # of the License, or (at your option) any later version. -# +# # This program 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 this program; if not, write to the Free Software +# along with this program; if not, write to the Free Software # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. # # argv[1] should be the name of the list. @@ -38,13 +38,13 @@ Options: -n/--non-digest-members-file are deprecated synonyms for this option. --digest-members-file=file - -d=file + -d file Similar to above, but these people become digest members. --changes-msg=<y|n> - -c <y|n> - Set whether or not to send the list members the `there's going to be - big changes to your list' message. defaults to no. + -c <y|n> + Set whether or not to send the list members the `there's going to be + big changes to your list' message. defaults to no. --welcome-msg=<y|n> -w <y|n> @@ -174,7 +174,7 @@ def addall(mlist, members, digest, ack, outfp): print >> tee, _('Hostile address (illegal characters): %(member)s') else: print >> tee, _('Subscribed: %(member)s') - + def main(): @@ -186,7 +186,7 @@ def main(): 'non-digest-members-file=', 'digest-members-file=', 'changes-msg=', - 'welcome-msg=', + 'welcome-msg=', 'help']) except getopt.error, msg: usage(1, msg) @@ -235,7 +235,7 @@ def main(): admin_notif = 0 else: usage(1, _('Bad argument to -a/--admin-notify: %(arg)s')) - + if dfile is None and nfile is None: usage(1) diff --git a/bin/check_perms b/bin/check_perms index 44fbe547..4f976b06 100755 --- a/bin/check_perms +++ b/bin/check_perms @@ -26,12 +26,12 @@ permission problems found. With -v be verbose. """ -import sys import os -import errno -import getopt +import sys import pwd import grp +import errno +import getopt from stat import * try: @@ -55,11 +55,17 @@ PROGRAM = sys.argv[0] # Gotta check the archives/private/*/database/* files +try: + True, False +except NameError: + True = 1 + False = 0 + class State: - FIX = 0 - VERBOSE = 0 + FIX = False + VERBOSE = False ERRORS = 0 STATE = State() @@ -78,7 +84,13 @@ def statgidmode(path): stat = os.stat(path) return stat[ST_MODE], stat[ST_GID] +seen = {} + def checkwalk(arg, dirname, names): + # Short-circuit duplicates + if seen.has_key(dirname): + return + seen[dirname] = True for name in names: path = os.path.join(dirname, name) if arg.VERBOSE: @@ -151,10 +163,16 @@ def checkall(): prefix = mm_cfg.PREFIX print _('checking mode for %(prefix)s') dirs = {} - for d in (mm_cfg.PREFIX, mm_cfg.EXEC_PREFIX, mm_cfg.VAR_PREFIX): - dirs[d] = 1 + for d in (mm_cfg.PREFIX, mm_cfg.EXEC_PREFIX, mm_cfg.VAR_PREFIX, + mm_cfg.LOG_DIR): + dirs[d] = True for d in dirs.keys(): - mode = statmode(d) + try: + mode = statmode(d) + except OSError, e: + if e.errno <> errno.ENOENT: raise + print _('WARNING: directory does not exist: %(d)s') + continue if (mode & DIRPERMS) <> DIRPERMS: STATE.ERRORS += 1 print _('directory must be at least 02775: %(d)s'), @@ -166,7 +184,6 @@ def checkall(): # check all subdirs os.path.walk(d, checkwalk, STATE) - def checkarchives(): private = mm_cfg.PRIVATE_ARCHIVE_FILE_DIR if STATE.VERBOSE: @@ -185,7 +202,6 @@ def checkarchives(): MBOXPERMS = S_IRGRP | S_IWGRP | S_IRUSR | S_IWUSR - def checkmboxfile(mboxdir): absdir = os.path.join(mm_cfg.PRIVATE_ARCHIVE_FILE_DIR, mboxdir) for f in os.listdir(absdir): @@ -202,7 +218,6 @@ def checkmboxfile(mboxdir): else: print - def checkarchivedbs(): # The archives/private/listname/database file must not be other readable # or executable otherwise those files will be accessible when the archives @@ -226,7 +241,6 @@ def checkarchivedbs(): else: print - def checkcgi(): cgidir = os.path.join(mm_cfg.EXEC_PREFIX, 'cgi-bin') if STATE.VERBOSE: @@ -332,8 +346,7 @@ def usage(code, msg=''): if __name__ == '__main__': try: - opts, args = getopt.getopt(sys.argv[1:], - 'fvh', + opts, args = getopt.getopt(sys.argv[1:], 'fvh', ['fix', 'verbose', 'help']) except getopt.error, msg: usage(1, msg) @@ -342,9 +355,9 @@ if __name__ == '__main__': if opt in ('-h', '--help'): usage(0) elif opt in ('-f', '--fix'): - STATE.FIX = 1 + STATE.FIX = True elif opt in ('-v', '--verbose'): - STATE.VERBOSE = 1 + STATE.VERBOSE = True checkall() checkarchives() diff --git a/bin/genaliases b/bin/genaliases index 289c5bec..bda43ef5 100644 --- a/bin/genaliases +++ b/bin/genaliases @@ -1,37 +1,40 @@ #! @PYTHON@ # -# Copyright (C) 2001,2002 by the Free Software Foundation, Inc. +# Copyright (C) 2001-2003 by the Free Software Foundation, Inc. # # This program 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 2 # of the License, or (at your option) any later version. -# +# # This program 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 this program; if not, write to the Free Software +# along with this program; if not, write to the Free Software # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -"""Regenerate Postfix's data/aliases and data/aliases.db files from scratch. +"""Regenerate Mailman specific aliases from scratch. -Usage: - - genaliases [options] +The actual output depends on the value of the `MTA' variable in your mm_cfg.py +file. +Usage: genaliases [options] Options: + -q/--quiet + Some MTA output can include more verbose help text. Use this to tone + down the verbosity. + -h/--help Print this message and exit. """ -import sys import os +import sys import getopt -import fcntl import paths # path hacking from Mailman import mm_cfg @@ -39,6 +42,12 @@ from Mailman import Utils from Mailman import MailList from Mailman.i18n import _ +try: + True, False +except NameError: + True = 1 + False = 0 + def usage(code, msg=''): @@ -54,32 +63,35 @@ def usage(code, msg=''): def main(): + quiet = False try: - opts, args = getopt.getopt(sys.argv[1:], 'h', ['help']) + opts, args = getopt.getopt(sys.argv[1:], 'hq', + ['help', 'quiet']) except getopt.error, msg: usage(1, msg) for opt, arg in opts: if opt in ('-h', '--help'): usage(0) + elif opt in ('-q', '--quiet'): + quiet = True if args: usage(1) - # Open up the MTA specific module + # Import the MTA specific module modulename = 'Mailman.MTA.' + mm_cfg.MTA __import__(modulename) MTA = sys.modules[modulename] - # Open the text file and Berkeley DB files, truncating any data already - # there. We need to acquire a lock so nobody tries to update the files - # while we're doing it. + # We need to acquire a lock so nobody tries to update the files while + # we're doing it. lock = MTA.makelock() lock.lock() # Group lists by virtual hostname mlists = {} for listname in Utils.list_names(): - mlist = MailList.MailList(listname, lock=0) + mlist = MailList.MailList(listname, lock=False) mlists.setdefault(mlist.host_name, []).append(mlist) # Make sure the files are created rw-rw-xxx; it should be okay to be world # readable. @@ -87,14 +99,16 @@ def main(): try: MTA.clear() if not mlists: - MTA.create(None, nolock=1) + MTA.create(None, nolock=True, quiet=quiet) else: for hostname, vlists in mlists.items(): for mlist in vlists: - MTA.create(mlist, nolock=1) + MTA.create(mlist, nolock=True, quiet=quiet) + # Be verbose for only the first printed list + quiet = True finally: os.umask(omask) - lock.unlock(unconditionally=1) + lock.unlock(unconditionally=True) diff --git a/bin/list_members b/bin/list_members index 3ad10f51..b4fdbb27 100755 --- a/bin/list_members +++ b/bin/list_members @@ -1,6 +1,6 @@ #! @PYTHON@ # -# Copyright (C) 1998,1999,2000,2001,2002 by the Free Software Foundation, Inc. +# Copyright (C) 1998-2003 by the Free Software Foundation, Inc. # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License @@ -61,6 +61,7 @@ status. """ import sys +from types import UnicodeType import paths from Mailman import mm_cfg @@ -72,6 +73,8 @@ from Mailman.i18n import _ from email.Utils import formataddr PROGRAM = sys.argv[0] +ENC = sys.getdefaultencoding() + WHYCHOICES = {'enabled' : MemberAdaptor.ENABLED, 'unknown' : MemberAdaptor.UNKNOWN, 'byuser' : MemberAdaptor.BYUSER, @@ -92,6 +95,15 @@ def usage(code, msg=''): +def safe(s): + if not s: + return '' + if isinstance(s, UnicodeType): + return s.encode(ENC, 'replace') + return unicode(s, ENC, 'replace').encode(ENC, 'replace') + + + def whymatches(mlist, addr, why): # Return true if the `why' matches the reason the address is enabled, or # in the case of why is None, that they are disabled for any reason @@ -199,17 +211,15 @@ def main(): if regular: rmembers.sort() for addr in rmembers: - name = fullnames and mlist.getMemberName(addr) + name = fullnames and mlist.getMemberName(addr) or '' # Filter out nomails if nomail and not whymatches(mlist, addr, why): continue - enc = sys.getdefaultencoding() - s = formataddr((name, addr)).encode(enc, 'replace') - print >> fp, s + print >> fp, formataddr((safe(name), addr)) if digest: dmembers.sort() for addr in dmembers: - name = fullnames and mlist.getMemberName(addr) + name = fullnames and mlist.getMemberName(addr) or '' # Filter out nomails if nomail and not whymatches(mlist, addr, why): continue @@ -222,9 +232,7 @@ def main(): # They're getting MIME digests if kind == 'plain': continue - enc = sys.getdefaultencoding() - s = formataddr((name, addr)).encode(enc, 'replace') - print >> fp, s + print >> fp, formataddr((safe(name), addr)) diff --git a/bin/remove_members b/bin/remove_members index 888dfa51..b8f92f5e 100755 --- a/bin/remove_members +++ b/bin/remove_members @@ -1,6 +1,6 @@ #! @PYTHON@ # -# Copyright (C) 1998,1999,2000,2001,2002 by the Free Software Foundation, Inc. +# Copyright (C) 1998-2003 by the Free Software Foundation, Inc. # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License @@ -31,21 +31,23 @@ Options: --all -a Remove all members of the mailing list. - (mutually exclusive with --fromall) + (mutually exclusive with --fromall) --fromall - Removes the given addresses from all the lists on this system - regardless of virtual domains if you have any. This option cannot be - used -a/--all. Also, you should not specify a listname when using this - option. + Removes the given addresses from all the lists on this system + regardless of virtual domains if you have any. This option cannot be + used -a/--all. Also, you should not specify a listname when using + this option. --nouserack -n - Don't send the user acknowledgements. + Don't send the user acknowledgements. If not specified, the list + default value is used. --noadminack -N - Don't send the admin acknowledgements. + Don't send the admin acknowledgements. If not specified, the list + default value is used. --help -h @@ -66,6 +68,12 @@ from Mailman import Utils from Mailman import Errors from Mailman.i18n import _ +try: + True, False +except NameError: + True = 1 + False = 0 + def usage(code, msg=''): @@ -83,10 +91,10 @@ def ReadFile(filename): lines = [] if filename == "-": fp = sys.stdin - closep = 0 + closep = False else: fp = open(filename) - closep = 1 + closep = True lines = filter(None, [line.strip() for line in fp.readlines()]) if closep: fp.close() @@ -106,10 +114,11 @@ def main(): usage(1) filename = None - all = 0 - alllists = 0 - userack = 1 - admin_notif = 1 + all = False + alllists = False + # None means use list default + userack = None + admin_notif = None for opt, arg in opts: if opt in ('-h', '--help'): @@ -117,13 +126,13 @@ def main(): elif opt in ('-f', '--file'): filename = arg elif opt in ('-a', '--all'): - all = 1 + all = True elif opt == '--fromall': - alllists = 1 + alllists = True elif opt in ('-n', '--nouserack'): - userack = 0 + userack = False elif opt in ('-N', '--noadminack'): - admin_notif = 0 + admin_notif = False # You probably don't want to delete all the users of all the lists -- Marc if all and alllists: @@ -163,10 +172,8 @@ def main(): if not alllists: print _('No such member: %(addr)s') continue - mlist.ApprovedDeleteMember(addr, - 'bin/remove_members', - admin_notif, - userack) + mlist.ApprovedDeleteMember(addr, 'bin/remove_members', + admin_notif, userack) if alllists: print _("User `%(addr)s' removed from list: %(listname)s.") mlist.Save() diff --git a/bin/transcheck b/bin/transcheck index fbb0dcd8..78d1b6d1 100755 --- a/bin/transcheck +++ b/bin/transcheck @@ -55,14 +55,19 @@ def usage(code, msg=''): class TransChecker: "check a translation comparing with the original string" - def __init__(self, regexp): + def __init__(self, regexp, escaped=None): self.dict = {} self.errs = [] self.regexp = re.compile(regexp) + self.escaped = None + if escaped: + self.escaped = re.compile(escaped) def checkin(self, string): "scan a string from the original file" for key in self.regexp.findall(string): + if self.escaped and self.escaped.match(key): + continue if self.dict.has_key(key): self.dict[key] += 1 else: @@ -71,6 +76,8 @@ class TransChecker: def checkout(self, string): "scan a translated string" for key in self.regexp.findall(string): + if self.escaped and self.escaped.match(key): + continue if self.dict.has_key(key): self.dict[key] -= 1 else: @@ -273,9 +280,9 @@ def check_file(translatedFile, originalFile, html=0, quiet=0): search also <MM-*> tags if html is not zero""" if html: - c = TransChecker("(%\([^)]+\)[0-9]*[sd]|</?MM-[^>]+>)") + c = TransChecker("(%%|%\([^)]+\)[0-9]*[sd]|</?MM-[^>]+>)", "^%%$") else: - c = TransChecker("(%\([^)]+\)[0-9]*[sd])") + c = TransChecker("(%%|%\([^)]+\)[0-9]*[sd])", "^%%$") try: f = open(originalFile) @@ -319,7 +326,7 @@ def check_po(file, quiet=0): "scan the po file comparing msgids with msgstrs" n = 0 p = POParser(file) - c = TransChecker("(%\([^)]+\)[0-9]*[sdu]|%[0-9]*[sdu])") + c = TransChecker("(%%|%\([^)]+\)[0-9]*[sdu]|%[0-9]*[sdu])", "^%%$") while p.parse(): if p.msgstr: c.reset() |