Apply 79_archiver_slash.patch
[mspang/vmailman.git] / bin / find_member
1 #! @PYTHON@
2 #
3 # Copyright (C) 1998-2003 by the Free Software Foundation, Inc.
4 #
5 # This program is free software; you can redistribute it and/or
6 # modify it under the terms of the GNU General Public License
7 # as published by the Free Software Foundation; either version 2
8 # of the License, or (at your option) any later version.
9 #
10 # This program is distributed in the hope that it will be useful,
11 # but WITHOUT ANY WARRANTY; without even the implied warranty of
12 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 # GNU General Public License for more details.
14 #
15 # You should have received a copy of the GNU General Public License
16 # along with this program; if not, write to the Free Software
17 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
18
19 """Find all lists that a member's address is on.
20
21 Usage:
22     find_member [options] regex [regex [...]]
23
24 Where:
25     --listname=listname
26     -l listname
27         Include only the named list in the search.
28
29     --exclude=listname
30     -x listname
31         Exclude the named list from the search.
32
33     --owners
34     -w
35         Search list owners as well as members.
36
37     --help
38     -h
39         Print this help message and exit.
40
41     regex
42         A Python regular expression to match against.
43
44 The interaction between -l and -x is as follows.  If any -l option is given
45 then only the named list will be included in the search.  If any -x option is
46 given but no -l option is given, then all lists will be search except those
47 specifically excluded.
48
49 Regular expression syntax is Perl5-like, using the Python re module.  Complete
50 specifications are at:
51
52 http://www.python.org/doc/current/lib/module-re.html
53
54 Address matches are case-insensitive, but case-preserved addresses are
55 displayed.
56
57 """
58
59 import sys
60 import re
61 import getopt
62
63 import paths
64 from Mailman import Utils
65 from Mailman import MailList
66 from Mailman import Errors
67 from Mailman.i18n import _
68
69 AS_MEMBER = 0x01
70 AS_OWNER = 0x02
71
72
73 \f
74 def usage(code, msg=''):
75     if code:
76         fd = sys.stderr
77     else:
78         fd = sys.stdout
79     print >> fd, _(__doc__)
80     if msg:
81         print >> fd, msg
82     sys.exit(code)
83
84
85 \f
86 def scanlists(options):
87     cres = []
88     for r in options.regexps:
89         cres.append(re.compile(r, re.IGNORECASE))
90     #
91     # dictionary of {address, (listname, ownerp)}
92     matches = {}
93     for listname in options.listnames:
94         try:
95             mlist = MailList.MailList(listname, lock=0)
96         except Errors.MMListError:
97             print _('No such list: %(listname)s')
98             continue
99         if options.owners:
100             owners = mlist.owner
101         else:
102             owners = []
103         for cre in cres:
104             for member in mlist.getMembers():
105                 if cre.search(member):
106                     addr = mlist.getMemberCPAddress(member)
107                     entries = matches.get(addr, {})
108                     aswhat = entries.get(listname, 0)
109                     aswhat |=  AS_MEMBER
110                     entries[listname] = aswhat
111                     matches[addr] = entries
112             for owner in owners:
113                 if cre.search(owner):
114                     entries = matches.get(owner, {})
115                     aswhat = entries.get(listname, 0)
116                     aswhat |= AS_OWNER
117                     entries[listname] = aswhat
118                     matches[owner] = entries
119     return matches
120
121
122 \f
123 class Options:
124     listnames = Utils.list_names()
125     owners = None
126
127
128 def main():
129     try:
130         opts, args = getopt.getopt(sys.argv[1:], 'l:x:wh',
131                                    ['listname=', 'exclude=', 'owners',
132                                     'help'])
133     except getopt.error, msg:
134         usage(1, msg)
135
136     options = Options()
137     loptseen = 0
138     excludes = []
139     for opt, arg in opts:
140         if opt in ('-h', '--help'):
141             usage(0)
142         elif opt in ('-l', '--listname'):
143             if not loptseen:
144                 options.listnames = []
145                 loptseen = 1
146             options.listnames.append(arg.lower())
147         elif opt in ('-x', '--exclude'):
148             excludes.append(arg.lower())
149         elif opt in ('-w', '--owners'):
150             options.owners = 1
151
152     for ex in excludes:
153         try:
154             options.listnames.remove(ex)
155         except ValueError:
156             pass
157
158     if not args:
159         usage(1, _('Search regular expression required'))
160
161     options.regexps = args
162
163     if not options.listnames:
164         print _('No lists to search')
165         return
166
167     matches = scanlists(options)
168     addrs = matches.keys()
169     addrs.sort()
170     for k in addrs:
171         hits = matches[k]
172         lists = hits.keys()
173         print k, _('found in:')
174         for name in lists:
175             aswhat = hits[name]
176             if aswhat & AS_MEMBER:
177                 print '    ', name
178             if aswhat & AS_OWNER:
179                 print '    ', name, _('(as owner)')
180
181
182 \f
183 if __name__ == '__main__':
184     main()