2 #***************************************************************************
3 #* Copyright (C) 2004 polytechnique.org *
4 #* http://opensource.polytechnique.org/ *
6 #* This program is free software; you can redistribute it and/or modify *
7 #* it under the terms of the GNU General Public License as published by *
8 #* the Free Software Foundation; either version 2 of the License, or *
9 #* (at your option) any later version. *
11 #* This program is distributed in the hope that it will be useful, *
12 #* but WITHOUT ANY WARRANTY; without even the implied warranty of *
13 #* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
14 #* GNU General Public License for more details. *
16 #* You should have received a copy of the GNU General Public License *
17 #* along with this program; if not, write to the Free Software *
18 #* Foundation, Inc., *
19 #* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA *
20 #***************************************************************************
22 import base64
, MySQLdb
, os
, getopt
, sys
, sha
, signal
, re
, shutil
, ConfigParser
23 import MySQLdb
.converters
26 sys
.path
.append('/usr/lib/mailman/bin')
28 from pwd
import getpwnam
29 from grp
import getgrnam
31 from SimpleXMLRPCServer
import SimpleXMLRPCServer
32 from SimpleXMLRPCServer
import SimpleXMLRPCRequestHandler
35 from Mailman
import MailList
36 from Mailman
import Utils
37 from Mailman
import Message
38 from Mailman
import Errors
39 from Mailman
import mm_cfg
40 from Mailman
import i18n
41 from Mailman
.UserDesc
import UserDesc
42 from Mailman
.ListAdmin
import readMessage
43 from email
.Iterators
import typed_subpart_iterator
44 from threading
import Lock
46 class AuthFailed(Exception): pass
48 ################################################################################
52 #------------------------------------------------
54 config
= ConfigParser
.ConfigParser()
55 config
.read(os
.path
.dirname(__file__
)+'/../configs/platal.conf')
57 def get_config(sec
,val
,default
=None):
59 return config
.get(sec
, val
)[1:-1]
60 except ConfigParser
.NoOptionError
, e
:
67 BASEURL
= get_config('Core', 'baseurl')
68 MYSQL_USER
= get_config('Core', 'dbuser')
69 MYSQL_PASS
= get_config('Core', 'dbpwd')
71 PLATAL_DOMAIN
= get_config('Mail', 'domain')
72 PLATAL_DOMAIN2
= get_config('Mail', 'domain2', '')
74 ML_OWNER
= get_config('Lists', 'admin_owner')
75 VHOST_SEP
= get_config('Lists', 'vhost_sep', '_')
76 ON_CREATE_CMD
= get_config('Lists', 'on_create', '')
78 ################################################################################
82 #------------------------------------------------
83 # Manage Basic authentication
86 class BasicAuthXMLRPCRequestHandler(SimpleXMLRPCRequestHandler
):
88 """XMLRPC Request Handler
89 This request handler is used to provide BASIC HTTP user authentication.
90 It first overloads the do_POST() function, authenticates the user, then
91 calls the super.do_POST().
93 Moreover, we override _dispatch, so that we call functions with as first
94 argument a UserDesc taken from the database, containing name, email and perms
97 def _dispatch(self
,method
,params
):
98 # TODO: subclass in SimpleXMLRPCDispatcher and not here.
99 new_params
= list(params
)
100 new_params
.insert(0,self
.data
[2])
101 new_params
.insert(0,self
.data
[1])
102 new_params
.insert(0,self
.data
[0])
103 return self
.server
._dispatch(method
,new_params
)
107 _
, auth
= self
.headers
["authorization"].split()
108 uid
, md5
= base64
.decodestring(auth
).strip().split(':')
109 vhost
= self
.path
.split('/')[1].lower()
110 self
.data
= self
.getUser(uid
,md5
,vhost
)
111 if self
.data
is None:
113 # Call super.do_POST() to do the actual work
114 SimpleXMLRPCRequestHandler
.do_POST(self
)
116 self
.send_response(401)
119 def getUser(self
, uid
, md5
, vhost
):
120 res
= mysql_fetchone ("""SELECT CONCAT(u.prenom, ' ',u.nom),a.alias,u.perms
121 FROM auth_user_md5 AS u
122 INNER JOIN aliases AS a ON ( a.id=u.user_id AND a.type='a_vie' )
123 WHERE u.user_id = '%s' AND u.password = '%s' AND u.perms IN ('admin','user')
124 LIMIT 1""" %( uid
, md5
) )
126 name
,forlife
,perms
= res
127 if vhost
!= PLATAL_DOMAIN
:
128 res
= mysql_fetchone ("""SELECT uid
129 FROM groupex.membres AS m
130 INNER JOIN groupex.asso AS a ON (m.asso_id = a.id)
131 WHERE perms='admin' AND uid='%s' AND mail_domain='%s'""" %( uid
, vhost
) )
132 if res
: perms
= 'admin'
133 userdesc
= UserDesc(forlife
+'@'+PLATAL_DOMAIN
, name
, None, 0)
134 return (userdesc
,perms
,vhost
)
138 ################################################################################
142 #-------------------------------------------------------------------------------
147 db
= MySQLdb
.connect(
151 unix_socket
='/var/run/mysqld/mysqld.sock')
155 def mysql_fetchone(query
):
160 if int(mysql
.rowcount
) > 0:
161 ret
= mysql
.fetchone()
166 def is_owner(userdesc
,perms
,mlist
):
167 return ( perms
== 'admin' and ML_OWNER
in mlist
.owner
) or ( userdesc
.address
in mlist
.owner
)
169 def is_admin_on(userdesc
,perms
,mlist
):
170 return ( perms
== 'admin' ) or ( userdesc
.address
in mlist
.owner
)
173 def quote(s
,is_header
=False):
175 h
= Utils
.oneline(s
,'iso-8859-1')
178 h
= str('').join(re
.split('[\x00-\x1f]+', s
))
179 return Utils
.uquote(h
.replace('&','&').replace('>','>').replace('<','<'))
181 def to_forlife(email
):
183 mbox
,fqdn
= email
.split('@')
187 if ( fqdn
== PLATAL_DOMAIN
) or ( fqdn
== PLATAL_DOMAIN2
):
188 res
= mysql_fetchone("""SELECT CONCAT(f.alias,'@%s'), CONCAT(u.prenom,' ',u.nom)
189 FROM auth_user_md5 AS u
190 INNER JOIN aliases AS f ON (f.id=u.user_id AND f.type='a_vie')
191 INNER JOIN aliases AS a ON (a.id=u.user_id AND a.alias='%s' AND a.type!='homonyme')
192 WHERE u.perms IN ('admin','user')
193 LIMIT 1""" %( PLATAL_DOMAIN
, mbox
) )
201 # see /usr/lib/mailman/bin/rmlist
203 def remove_it(listname
, filename
):
204 if os
.path
.islink(filename
) or os
.path
.isfile(filename
):
206 elif os
.path
.isdir(filename
):
207 shutil
.rmtree(filename
)
209 #-------------------------------------------------------------------------------
213 def get_list_info(userdesc
,perms
,mlist
,front_page
=0):
214 members
= mlist
.getRegularMemberKeys()
215 is_member
= userdesc
.address
in members
216 is_admin
= ML_OWNER
in mlist
.owner
217 is_owner
= ( perms
== 'admin' and is_admin
) or ( userdesc
.address
in mlist
.owner
)
218 if mlist
.advertised
or is_member
or is_owner
or (not front_page
and perms
== 'admin'):
220 if not is_member
and (mlist
.subscribe_policy
> 1):
223 for id in mlist
.GetSubscriptionIds():
224 if userdesc
.address
== mlist
.GetRecord(id)[1]:
232 host
= mlist
.internal_name().split(VHOST_SEP
)[0].lower()
234 'list' : mlist
.real_name
,
235 'addr' : mlist
.real_name
.lower() + '@' + host
,
237 'desc' : quote(mlist
.description
),
238 'info' : quote(mlist
.info
),
239 'diff' : (mlist
.default_member_moderation
>0) + (mlist
.generic_nonmember_action
>0),
240 'ins' : mlist
.subscribe_policy
> 1,
241 'priv' : (1-mlist
.advertised
)+2*is_admin
,
242 'sub' : 2*is_member
+ is_pending
,
244 'nbsub': len(members
)
246 return (details
,members
)
249 def get_options(userdesc
,perms
,vhost
,listname
,opts
):
251 mlist
= MailList
.MailList(vhost
+VHOST_SEP
+listname
.lower(),lock
=0)
255 if not is_admin_on(userdesc
, perms
, mlist
):
258 for (k
,v
) in mlist
.__dict__
.iteritems():
261 options
[k
] = quote(v
)
263 details
= get_list_info(userdesc
,perms
,mlist
)[0]
264 return (details
,options
)
268 def set_options(userdesc
,perms
,vhost
,listname
,opts
,vals
):
270 mlist
= MailList
.MailList(vhost
+VHOST_SEP
+listname
.lower(),lock
=0)
274 if not is_admin_on(userdesc
, perms
, mlist
):
277 for (k
,v
) in vals
.iteritems():
280 if k
== 'default_member_moderation':
281 for member
in mlist
.getMembers():
282 mlist
.setMemberOption(member
, mm_cfg
.Moderate
, int(v
))
283 t
= type(mlist
.__dict__
[k
])
284 if t
is bool: mlist
.__dict__
[k
] = bool(v
)
285 elif t
is int: mlist
.__dict__
[k
] = int(v
)
286 elif t
is str: mlist
.__dict__
[k
] = Utils
.uncanonstr(v
,'fr')
287 else: mlist
.__dict__
[k
] = v
295 #-------------------------------------------------------------------------------
296 # users procedures for [ index.php ]
299 def get_lists(userdesc
,perms
,vhost
,email
=None):
303 udesc
= UserDesc(email
, email
, None, 0)
304 prefix
= vhost
.lower()+VHOST_SEP
305 names
= Utils
.list_names()
309 if not name
.startswith(prefix
):
312 mlist
= MailList
.MailList(name
,lock
=0)
316 details
= get_list_info(udesc
,perms
,mlist
,(email
is None and vhost
== PLATAL_DOMAIN
))[0]
317 result
.append(details
)
322 def subscribe(userdesc
,perms
,vhost
,listname
):
324 mlist
= MailList
.MailList(vhost
+VHOST_SEP
+listname
.lower(),lock
=0)
329 if ( mlist
.subscribe_policy
in (0,1) ) or is_owner(userdesc
,perms
,mlist
):
330 mlist
.ApprovedAddMember(userdesc
)
335 mlist
.AddMember(userdesc
)
336 except Errors
.MMNeedApproval
:
344 def unsubscribe(userdesc
,perms
,vhost
,listname
):
346 mlist
= MailList
.MailList(vhost
+VHOST_SEP
+listname
.lower(),lock
=0)
351 mlist
.ApprovedDeleteMember(userdesc
.address
)
359 #-------------------------------------------------------------------------------
360 # users procedures for [ index.php ]
363 def get_members(userdesc
,perms
,vhost
,listname
):
365 mlist
= MailList
.MailList(vhost
+VHOST_SEP
+listname
.lower(),lock
=0)
369 details
,members
= get_list_info(userdesc
,perms
,mlist
)
371 members
= map(lambda member
: (quote(mlist
.getMemberName(member
)) or '', member
), members
)
372 return (details
,members
,mlist
.owner
)
376 #-------------------------------------------------------------------------------
377 # users procedures for [ trombi.php ]
380 def get_members_limit(userdesc
,perms
,vhost
,listname
,page
,nb_per_page
):
382 members
= get_members(userdesc
,perms
,vhost
,listname
.lower())[1]
385 i
= int(page
) * int(nb_per_page
)
386 return (len(members
), members
[i
:i
+int(nb_per_page
)])
388 def get_owners(userdesc
,perms
,vhost
,listname
):
390 details
,members
,owners
= get_members(userdesc
,perms
,vhost
,listname
.lower())
393 return (details
,owners
)
395 #-------------------------------------------------------------------------------
396 # owners procedures [ admin.php ]
399 def mass_subscribe(userdesc
,perms
,vhost
,listname
,users
):
401 mlist
= MailList
.MailList(vhost
+VHOST_SEP
+listname
.lower(),lock
=0)
405 if not is_admin_on(userdesc
, perms
, mlist
):
408 members
= mlist
.getRegularMemberKeys()
412 email
, name
= to_forlife(user
)
413 if ( email
is None ) or ( email
in members
):
415 userd
= UserDesc(email
, name
, None, 0)
416 mlist
.ApprovedAddMember(userd
)
417 added
.append( (quote(userd
.fullname
), userd
.address
) )
424 def mass_unsubscribe(userdesc
,perms
,vhost
,listname
,users
):
426 mlist
= MailList
.MailList(vhost
+VHOST_SEP
+listname
.lower(),lock
=0)
430 if not is_admin_on(userdesc
, perms
, mlist
):
434 map(lambda user
: mlist
.ApprovedDeleteMember(user
), users
)
441 def add_owner(userdesc
,perms
,vhost
,listname
,user
):
443 mlist
= MailList
.MailList(vhost
+VHOST_SEP
+listname
.lower(),lock
=0)
447 if not is_admin_on(userdesc
, perms
, mlist
):
449 email
= to_forlife(user
)[0]
452 if email
not in mlist
.owner
:
454 mlist
.owner
.append(email
)
461 def del_owner(userdesc
,perms
,vhost
,listname
,user
):
463 mlist
= MailList
.MailList(vhost
+VHOST_SEP
+listname
.lower(),lock
=0)
467 if not is_admin_on(userdesc
, perms
, mlist
):
469 if len(mlist
.owner
) < 2:
472 mlist
.owner
.remove(user
)
479 #-------------------------------------------------------------------------------
480 # owners procedures [ admin.php ]
483 def get_pending_ops(userdesc
,perms
,vhost
,listname
):
485 mlist
= MailList
.MailList(vhost
+VHOST_SEP
+listname
.lower(),lock
=0)
489 if not is_admin_on(userdesc
, perms
, mlist
):
497 for id in mlist
.GetSubscriptionIds():
498 time
, addr
, fullname
, passwd
, digest
, lang
= mlist
.GetRecord(id)
500 mlist
.HandleRequest(id, mm_cfg
.DISCARD
)
505 login
= re
.match("^[^.]*\.[^.]*\.\d\d\d\d$", addr
.split('@')[0]).group()
506 subs
.append({'id': id, 'name': quote(fullname
), 'addr': addr
, 'login': login
})
508 subs
.append({'id': id, 'name': quote(fullname
), 'addr': addr
})
511 for id in mlist
.GetHeldMessageIds():
512 ptime
, sender
, subject
, reason
, filename
, msgdata
= mlist
.GetRecord(id)
514 size
= os
.path
.getsize(os
.path
.join(mm_cfg
.DATA_DIR
, filename
))
516 if e
.errno
<> errno
.ENOENT
: raise
520 'sender': quote(sender
, True),
522 'subj' : quote(subject
, True),
525 if dosave
: mlist
.Save()
533 def handle_request(userdesc
,perms
,vhost
,listname
,id,value
,comment
):
535 mlist
= MailList
.MailList(vhost
+VHOST_SEP
+listname
.lower(),lock
=0)
539 if not is_admin_on(userdesc
, perms
, mlist
):
542 mlist
.HandleRequest(int(id),int(value
),comment
)
551 def get_pending_mail(userdesc
,perms
,vhost
,listname
,id,raw
=0):
553 mlist
= MailList
.MailList(vhost
+VHOST_SEP
+listname
.lower(),lock
=0)
557 if not is_admin_on(userdesc
, perms
, mlist
):
560 ptime
, sender
, subject
, reason
, filename
, msgdata
= mlist
.GetRecord(int(id))
561 fpath
= os
.path
.join(mm_cfg
.DATA_DIR
, filename
)
562 size
= os
.path
.getsize(fpath
)
563 msg
= readMessage(fpath
)
569 for part
in typed_subpart_iterator(msg
,'text','plain'):
570 c
= part
.get_payload()
571 if c
is not None: results
.append (c
)
572 results
= map(lambda x
: quote(x
), results
)
574 'sender': quote(sender
, True),
576 'subj' : quote(subject
, True),
583 #-------------------------------------------------------------------------------
584 # owner options [ options.php ]
587 owner_opts
= ['accept_these_nonmembers', 'admin_notify_mchanges', 'description', \
588 'default_member_moderation', 'generic_nonmember_action', 'info', \
589 'subject_prefix', 'goodbye_msg', 'send_goodbye_msg', 'subscribe_policy', \
592 def get_owner_options(userdesc
,perms
,vhost
,listname
):
593 return get_options(userdesc
,perms
,vhost
,listname
.lower(),owner_opts
)
595 def set_owner_options(userdesc
,perms
,vhost
,listname
,values
):
596 return set_options(userdesc
,perms
,vhost
,listname
.lower(),owner_opts
,values
)
598 def add_to_wl(userdesc
,perms
,vhost
,listname
,addr
):
600 mlist
= MailList
.MailList(vhost
+VHOST_SEP
+listname
.lower(),lock
=0)
604 if not is_admin_on(userdesc
, perms
, mlist
):
607 mlist
.accept_these_nonmembers
.append(addr
)
615 def del_from_wl(userdesc
,perms
,vhost
,listname
,addr
):
617 mlist
= MailList
.MailList(vhost
+VHOST_SEP
+listname
.lower(),lock
=0)
621 if not is_admin_on(userdesc
, perms
, mlist
):
624 mlist
.accept_these_nonmembers
.remove(addr
)
632 def get_bogo_level(userdesc
,perms
,vhost
,listname
):
634 mlist
= MailList
.MailList(vhost
+VHOST_SEP
+listname
.lower(),lock
=0)
638 if not is_admin_on(userdesc
, perms
, mlist
):
640 if mlist
.header_filter_rules
== []:
642 action
= mlist
.header_filter_rules
[0][1]
643 if action
== mm_cfg
.HOLD
:
645 if action
== mm_cfg
.DISCARD
:
650 def set_bogo_level(userdesc
,perms
,vhost
,listname
,level
):
652 mlist
= MailList
.MailList(vhost
+VHOST_SEP
+listname
.lower(),lock
=0)
656 if not is_admin_on(userdesc
, perms
, mlist
):
660 hfr
.append(('X-Spam-Flag: Yes, tests=bogofilter', mm_cfg
.HOLD
, False))
661 elif int(level
) is 2:
662 hfr
.append(('X-Spam-Flag: Yes, tests=bogofilter', mm_cfg
.DISCARD
, False))
663 if mlist
.header_filter_rules
!= hfr
:
665 mlist
.header_filter_rules
= hfr
673 #-------------------------------------------------------------------------------
674 # admin procedures [ soptions.php ]
677 admin_opts
= [ 'advertised', 'archive', \
678 'max_message_size', 'msg_footer', 'msg_header']
680 def get_admin_options(userdesc
,perms
,vhost
,listname
):
683 return get_options(userdesc
,perms
,vhost
,listname
.lower(),admin_opts
)
685 def set_admin_options(userdesc
,perms
,vhost
,listname
,values
):
688 return set_options(userdesc
,perms
,vhost
,listname
.lower(),admin_opts
,values
)
690 #-------------------------------------------------------------------------------
691 # admin procedures [ check.php ]
695 'acceptable_aliases' : '',
696 'admin_immed_notify' : True,
697 'administrivia' : True,
698 'anonymous_list' : False,
699 'autorespond_admin' : False,
700 'autorespond_postings' : False,
701 'autorespond_requests' : False,
702 'available_languages' : ['fr'],
704 'bounce_matching_headers' : '',
705 'bounce_processing' : False,
706 'convert_html_to_plaintext' : False,
707 'digestable' : False,
708 'digest_is_default' : False,
709 'discard_these_nonmembers' : [],
711 'encode_ascii_prefixes' : 2,
712 'filter_content' : False,
713 'first_strip_reply_to' : False,
714 'forward_auto_discards' : True,
715 'hold_these_nonmembers' : [],
716 'host_name' : 'listes.polytechnique.org',
717 'include_list_post_header' : False,
718 'include_rfc2369_headers' : False,
719 'max_num_recipients' : 0,
720 'new_member_options' : 256,
721 'nondigestable' : True,
722 'obscure_addresses' : True,
723 'preferred_language' : 'fr',
724 'reject_these_nonmembers' : [],
725 'reply_goes_to_list' : 0,
726 'reply_to_address' : '',
727 'require_explicit_destination' : False,
728 'send_reminders' : 0,
729 'send_welcome_msg' : True,
730 'topics_enabled' : False,
731 'umbrella_list' : False,
732 'unsubscribe_policy' : 0,
735 def check_options(userdesc
,perms
,vhost
,listname
,correct
=False):
737 mlist
= MailList
.MailList(vhost
+VHOST_SEP
+listname
.lower(),lock
=0)
741 if perms
!= 'admin': return 0
745 for (k
,v
) in check_opts
.iteritems():
746 if mlist
.__dict__
[k
] != v
:
747 options
[k
] = v
,mlist
.__dict__
[k
]
748 if correct
: mlist
.__dict__
[k
] = v
749 if mlist
.real_name
.lower() != listname
:
750 options
['real_name'] = listname
, mlist
.real_name
751 if correct
: mlist
.real_name
= listname
755 details
= get_list_info(userdesc
,perms
,mlist
)[0]
756 return (details
,options
)
758 if correct
: mlist
.Unlock()
761 #-------------------------------------------------------------------------------
762 # super-admin procedures
765 def get_all_lists(userdesc
,perms
,vhost
):
766 prefix
= vhost
.lower()+VHOST_SEP
767 names
= Utils
.list_names()
771 if not name
.startswith(prefix
):
773 result
.append(name
.replace(prefix
,''))
776 def create_list(userdesc
,perms
,vhost
,listname
,desc
,advertise
,modlevel
,inslevel
,owners
,members
):
779 name
= vhost
.lower()+VHOST_SEP
+listname
.lower();
780 if Utils
.list_exists(name
):
785 email
= to_forlife(o
)[0]
786 if email
is not None:
791 mlist
= MailList
.MailList()
793 oldmask
= os
.umask(002)
794 pw
= sha
.new('foobar').hexdigest()
797 mlist
.Create(name
, owner
[0], pw
)
801 mlist
.real_name
= listname
802 mlist
.host_name
= 'listes.polytechnique.org'
803 mlist
.description
= desc
805 mlist
.advertised
= int(advertise
) is 0
806 mlist
.default_member_moderation
= int(modlevel
) is 2
807 mlist
.generic_nonmember_action
= int(modlevel
) > 0
808 mlist
.subscribe_policy
= 2 * (int(inslevel
) is 1)
809 mlist
.admin_notify_mchanges
= (mlist
.subscribe_policy
or mlist
.generic_nonmember_action
or mlist
.default_member_moderation
or not mlist
.advertised
)
813 mlist
.subject_prefix
= '['+listname
+'] '
814 mlist
.max_message_size
= 0
816 mlist
.msg_footer
= "_______________________________________________\n" \
817 + "Liste de diffusion %(real_name)s\n"
819 mlist
.header_filter_rules
= []
820 mlist
.header_filter_rules
.append(('X-Spam-Flag: Yes, tests=bogofilter', mm_cfg
.HOLD
, False))
826 check_options(userdesc
,perms
,vhost
,listname
.lower(),True)
827 mass_subscribe(userdesc
,perms
,vhost
,listname
.lower(),members
)
829 # avoid the "-1 mail to moderate" bug
830 mlist
= MailList
.MailList(name
)
831 mlist
._UpdateRecords()
834 if ON_CREATE_CMD
!= '':
835 try: os
.system(ON_CREATE_CMD
+ ' ' + name
)
845 def delete_list(userdesc
,perms
,vhost
,listname
,del_archives
=0):
846 lname
= vhost
+VHOST_SEP
+listname
.lower()
848 mlist
= MailList
.MailList(lname
,lock
=0)
852 if not is_admin_on(userdesc
, perms
, mlist
):
855 REMOVABLES
= [ os
.path
.join('lists', lname
), ]
856 # remove stalled locks
857 for filename
in os
.listdir(mm_cfg
.LOCK_DIR
):
858 fn_lname
= filename
.split('.')[0]
859 if fn_lname
== lname
:
860 REMOVABLES
.append(os
.path
.join(mm_cfg
.LOCK_DIR
, filename
))
864 os
.path
.join('archives', 'private', lname
),
865 os
.path
.join('archives', 'private', lname
+'.mbox'),
866 os
.path
.join('archives', 'public', lname
),
867 os
.path
.join('archives', 'public', lname
+'.mbox')
869 map(lambda dir: remove_it(lname
, os
.path
.join(mm_cfg
.VAR_PREFIX
, dir)), REMOVABLES
)
874 def kill(userdesc
,perms
,vhost
,alias
,del_from_promo
):
876 if not del_from_promo
:
877 exclude
.append(PLATAL_DOMAIN
+VHOST_SEP
+'promo'+alias
[-4:])
878 for list in Utils
.list_names():
879 if list in exclude
: continue
881 mlist
= MailList
.MailList(list,lock
=0)
886 mlist
.ApprovedDeleteMember(alias
+'@'+PLATAL_DOMAIN
,None,0,0)
894 #-------------------------------------------------------------------------------
897 class FastXMLRPCServer(SocketServer
.ThreadingMixIn
, SimpleXMLRPCServer
):
898 allow_reuse_address
= True
900 ################################################################################
904 #-------------------------------------------------------------------------------
905 # use Mailman user and group (not root)
906 # fork in background if asked to
909 uid
= getpwnam(mm_cfg
.MAILMAN_USER
)[2]
910 gid
= getgrnam(mm_cfg
.MAILMAN_GROUP
)[2]
916 signal
.signal(signal
.SIGHUP
, signal
.SIG_IGN
)
918 if ( os
.getuid() is not uid
) or ( os
.getgid() is not gid
):
921 opts
, args
= getopt
.getopt(sys
.argv
[1:], 'f')
923 if o
== '-f' and os
.fork():
926 i18n
.set_language('fr')
930 #-------------------------------------------------------------------------------
933 server
= FastXMLRPCServer(("localhost", 4949), BasicAuthXMLRPCRequestHandler
)
936 server
.register_function(get_lists
)
937 server
.register_function(subscribe
)
938 server
.register_function(unsubscribe
)
940 server
.register_function(get_members
)
942 server
.register_function(get_members_limit
)
943 server
.register_function(get_owners
)
945 server
.register_function(mass_subscribe
)
946 server
.register_function(mass_unsubscribe
)
947 server
.register_function(add_owner
)
948 server
.register_function(del_owner
)
950 server
.register_function(get_pending_ops
)
951 server
.register_function(handle_request
)
952 server
.register_function(get_pending_mail
)
954 server
.register_function(get_owner_options
)
955 server
.register_function(set_owner_options
)
956 server
.register_function(add_to_wl
)
957 server
.register_function(del_from_wl
)
958 server
.register_function(get_bogo_level
)
959 server
.register_function(set_bogo_level
)
961 server
.register_function(get_admin_options
)
962 server
.register_function(set_admin_options
)
964 server
.register_function(check_options
)
966 server
.register_function(get_all_lists
)
967 server
.register_function(create_list
)
968 server
.register_function(delete_list
)
970 server
.register_function(kill
)
972 server
.serve_forever()