Dammit -- wrong version. :-) Sorry. Try this one.

-jag

-- 
Joshua Ginsberg <[EMAIL PROTECTED]>
Free Software Foundation - Senior Systems Administrator
diff -rNu mailman-2.1.5.virgin/Mailman/Cgi/RPC2.py mailman-2.1.5/Mailman/Cgi/RPC2.py
--- mailman-2.1.5.virgin/Mailman/Cgi/RPC2.py	1969-12-31 19:00:00.000000000 -0500
+++ mailman-2.1.5/Mailman/Cgi/RPC2.py	2005-10-14 16:25:08.000000000 -0400
@@ -0,0 +1,49 @@
+'''RPC2.py
+
+An XML-RPC listener for interfacing with GNU/Mailman
+
+Joshua Ginsberg <[EMAIL PROTECTED]>
+'''
+
+import os, re, xmlrpclib
+from Mailman import XMLRPC, mm_cfg, MailList, Errors, i18n
+
+# Set up i18n
+_ = i18n._
+i18n.set_language(mm_cfg.DEFAULT_SERVER_LANGUAGE)
+
+def main():
+    #0: Make sure we look like a CGI-like environment
+    try:
+        cgi_version = os.environ['GATEWAY_INTERFACE']
+    except KeyError:
+        raise xmlrpclib.Fault(-32300, 
+            _('Listener must be run within a CGI environment.'))
+    if re.match('CGI/[0-9].[0-9]', cgi_version) is None:
+        raise xmlrpclib.Fault(-32300, 
+            _('Listener must be run within a CGI environment.'))
+    
+    #1: What is the HTTP method?
+    try:
+        cgi_method = os.environ['REQUEST_METHOD']
+    except KeyError:
+        raise xmlrpclib.Fault(-32300,
+            _('No HTTP method was found.'))
+    
+    if cgi_method == 'POST':
+
+        #2: Content-type = text/xml
+        try:
+            content_type = os.environ['CONTENT_TYPE']
+        except KeyError:
+            raise xmlrpclib.Fault(-32300, 
+                _('Webserver did not provide a content type.'))
+        if content_type != 'text/xml':
+            raise xmlrpclib.Fault(-32300, _('Content type must be text/xml'))
+        
+        XMLRPC.handler.handle_request()
+    
+    elif cgi_method == 'GET':
+        XMLRPC.handler.handle_get()
+    else:
+        raise xmlrpclib.Fault(-32300, _('Invalid HTTP Method.'))
diff -rNu mailman-2.1.5.virgin/Mailman/XMLRPC.py mailman-2.1.5/Mailman/XMLRPC.py
--- mailman-2.1.5.virgin/Mailman/XMLRPC.py	1969-12-31 19:00:00.000000000 -0500
+++ mailman-2.1.5/Mailman/XMLRPC.py	2005-10-14 16:25:06.000000000 -0400
@@ -0,0 +1,325 @@
+'''XMLRPC
+
+This library implements an XML-RPC interface to the GNU/Mailman list manager
+software (http://list.org).
+
+Joshua Ginsberg <[EMAIL PROTECTED]>
+'''
+
+from Mailman import MailList, mm_cfg, i18n, Errors, Utils
+from Mailman.Logging.Syslog import syslog
+import os, signal, sys, os.path, shutil, xmlrpclib, sha, traceback, cgi
+from DocXMLRPCServer import DocCGIXMLRPCRequestHandler
+
+# Set up i18n
+_ = i18n._
+i18n.set_language(mm_cfg.DEFAULT_SERVER_LANGUAGE)
+
+def __authenhandler__(username, password, siteadmin):
+    '''__authenhandler__(username, password, siteadmin)
+    
+    A helper script designed to verify the basic authentication data
+    
+    username -- the username provided
+    password -- the password provided
+    siteadmin -- If true, the username must be 'mailman' and the password must
+        be the site administrator password. If false, the username must be the
+        list to work with, and the password must be either the list admin
+        password or the site admin password.        
+
+    Raises MMAuthenticationError if the authentication fails. Returns True 
+    otherwise.
+    '''
+    if siteadmin and username != 'mailman':
+        raise Errors.MMBadUserError, _('This method requires site admin access.')
+    if not siteadmin and username == 'mailman':
+        raise Errors.MMBadUserError, \
+            _('This method requires a list as a username.')
+    if username == 'mailman':
+        # if username is mailman, the only authentication that can happen is
+        # as site administrator
+        if Utils.check_global_password(password):
+            return True
+        else:
+            raise Errors.MMAuthenticationError, _('Invalid login.')   
+    else:
+        try:
+            mlist = MailList.MailList(username, lock=0)
+        except Errors.MMListError, e:
+            # a missing list means a bad username
+            # plus, we don't want to confirm what lists do or don't exist by
+            # doing something different than if the u/p combination is bad
+            syslog('error', _('''Mailing list %s not found''') % (username,))
+            raise Errors.MMAuthenticationError, _('Invalid login.')
+        if mlist.WebAuthenticate((mm_cfg.AuthListAdmin, mm_cfg.AuthSiteAdmin), 
+            password):
+            return True
+        else:
+            raise Errors.MMAuthenticationError, _('Invalid login.')
+
+class BoboTheClown(object):
+    '''Bobo the Clown is dumb. Just like this class.'''
+    pass
+
+def add_member(listname, authpassword, address, fullname, password, digest, 
+    now):
+    '''add_member(listname, authpassword, address, fullname, password, digest, 
+    now):
+    
+    Subscribes the email address provided to the mailing list.
+    
+    listname -- the name of the list to add a member to
+    authpassword -- the site admin or list admin password for this list
+    address -- the email address to add
+    fullname -- the user's full name
+    password -- the password the user would like to have
+    digest -- True or False implying if they wish to receive batched digest
+        delivery 
+    now -- True or False implying whether to bypass normal mailing list rules
+        about confirmation/approval
+    
+    Returns True if everything succeeded
+    '''
+    
+    __authenhandler__(listname, authpassword, False)
+    ip = os.environ['REMOTE_ADDR']
+    
+    mlist = MailList.MailList(listname, lock=0)
+    # switch to mailing list preferred language
+    i18n.set_language(mlist.preferred_language)
+    # taking my cues from other Cgi scripts, notably admin.py
+    
+    def freak_out(signum, frame, mlist=mlist):
+        mlist.Unlock()
+        sys.exit(0)
+    
+    signal.signal(signal.SIGTERM, freak_out)
+    mlist.Lock()
+    try:
+        bobo = BoboTheClown()
+        for attr in ['address', 'fullname', 'password', 'digest']:
+            if eval(attr) is not None: setattr(bobo, attr, eval(attr))
+        if now:
+            mlist.ApprovedAddMember(bobo, whence='XMLRPC from %s' % (ip,))
+        else:
+            mlist.AddMember(bobo, remote='XMLRPC from %s' % (ip,))
+        mlist.Save()
+    finally:
+        mlist.Unlock()
+    return True
+
+def delete_member(listname, password, email, now):
+    '''delete_member(listname, password, email, now):
+    
+    Unsubscribes a member from the list.
+    
+    listname -- the name of the list to delete a member from
+    password -- the site admin or list admin password for this list
+    email -- The email address to unsubscribe
+    now -- True or False implying whether to bypass normal mailing list rules
+        about approval
+    
+    Returns True if everything succeeded
+    '''
+    
+    __authenhandler__(listname, password, False)
+    ip = os.environ['REMOTE_ADDR']
+    
+    mlist = MailList.MailList(listname, lock=0)
+    # switch to mailing list preferred language
+    i18n.set_language(mlist.preferred_language)
+    # taking my cues from other Cgi scripts, notably admin.py
+    
+    def freak_out(signum, frame, mlist=mlist):
+        mlist.Unlock()
+        sys.exit(0)
+    
+    signal.signal(signal.SIGTERM, freak_out)
+    mlist.Lock()
+    try:
+        if now:
+            mlist.ApprovedDeleteMember(email, whence='XMLRPC from %s' % (ip,))
+        else:
+            mlist.DeleteMember(email, whence='XMLRPC from %s' % (ip,))
+        mlist.Save()
+    finally:
+        mlist.Unlock()
+    return True
+
+def change_address(listname, password, old, new, keepold):
+    '''change_address(listname, password, old, new, keepold):
+    
+    Changes an existing member's email address.
+    
+    listname -- the name of the list to update
+    password -- the site admin or list admin password for this list
+    old -- the old address
+    new -- the new address
+    keepold -- True or False whether to keep the old address subscribed as well
+    
+    Returns True if everything succeeded
+    '''
+    
+    __authenhandler__(listname, password, False)
+    ip = os.environ['REMOTE_ADDR']
+    
+    mlist = MailList.MailList(listname, lock=0)
+    # switch to mailing list preferred language
+    i18n.set_language(mlist.preferred_language)
+    # taking my cues from other Cgi scripts, notably admin.py
+    
+    def freak_out(signum, frame, mlist=mlist):
+        mlist.Unlock()
+        sys.exit(0)
+    
+    signal.signal(signal.SIGTERM, freak_out)
+    mlist.Lock()    
+    
+    try:
+        mlist.ApprovedChangeMemberAddress(old, new, keepold)
+    finally:
+        mlist.Unlock()
+    return True
+
+def create_list(site_pw, listname, emaildomain, webhost, moderated, listadmin,
+    listadmin_pw, languages):
+    '''create_list(site_pw, listname, emaildomain, webhost, moderated, listadmin,
+    listadmin_pw, languages):
+    
+    Creates a new mailing list.
+    
+    site_pw -- the site administrator password
+    listname -- the name of the list you wish to create
+    emaildomain -- the email domain this list will appear to come from
+    webhost -- the hostname used to access the web interface for this list
+    moderated -- True or False implying whether new members of the list are
+        to be moderated by default
+    listadmin -- The list administrator's email address
+    listadmin_pw -- The list administrator's password
+    languages -- a list of two-letter language codes for this list to support
+    
+    You must be logged in as the site administrator (no username, site admin
+    password) for this method to be invoked.
+    
+    Returns True if everything succeded
+    '''
+    
+    __authenhandler__('mailman', site_pw, True)
+    ip = os.environ['REMOTE_ADDR']
+    
+    mlist = MailList.MailList()
+    try:
+        def freak_out(signum, frame, mlist=mlist):
+            mlist.Unlock()
+            sys.exit(0)
+        
+        signal.signal(signal.SIGTERM, freak_out)    
+        listadmin_pw = sha.new(listadmin_pw).hexdigest()
+        # okay, I'm just plagiarizing from Cgi/create.py here
+        oldmask = os.umask(002)
+        try:
+            mlist.Create(listname, listadmin, listadmin_pw, languages)
+        finally: 
+            os.umask(oldmask)
+        mlist.default_member_moderation = moderated
+        mlist.web_page_url = mm_cfg.DEFAULT_URL_PATTERN % webhost
+        mlist.host_name = emaildomain
+        mlist.Save()
+    finally:
+        mlist.Unlock()
+    return True
+
+def delete_list(site_pw, archives_too):
+    '''delete_list(archives_too):
+    
+    Delete a list and possibly its archives too.
+    
+    site_pw -- The site administrator password
+    archives_too -- True or False implying whether to remove the lists archives
+    
+    Returns True if everything succeded.
+    '''
+    
+    
+    __authenhandler__('mailman', site_pw, True)
+    ip = os.environ['REMOTE_ADDR']
+
+    mlist = MailList.MailList(listname, lock=0)
+
+    # pretty much straight ripping off bin/rmlist
+    if mm_cfg.MTA:
+        modname = 'Mailman.MTA.' + mm_cfg.MTA
+        __import__(modname)
+        sys.modules[modname].remove(mlist)
+
+    REMOVABLES = [os.path.join('lists', listname)]
+
+    # Remove any stale locks associated with the list
+    for filename in os.listdir(mm_cfg.LOCK_DIR):
+        fn_listname = filename.split('.')[0]
+        if fn_listname == listname:
+            REMOVABLES.append(os.path.join(mm_cfg.LOCK_DIR, filename))
+    if archives_too:
+        REMOVABLES.extend([
+            os.path.join('archives', 'private', listname),
+            os.path.join('archives', 'private', listname + '.mbox'),
+            os.path.join('archives', 'public', listname),
+            os.path.join('archives', 'public', listname + '.mbox')
+            ])
+
+    for dirtmpl in REMOVABLES:
+        filename = os.path.join(mm_cfg.VAR_PREFIX, dirtmpl)
+        if os.path.islink(filename):
+            os.unlink(filename)
+        elif os.path.isdir(filename):
+            shutil.rmtree(filename)
+        elif os.path.isfile(filename):
+            os.unlink(filename)
+    return True
+
+def __method_wrapper__(method_func):
+    '''__method_wrapper__(method_func):
+    
+    Python's XMLRPC library will catch any exceptions that are not of the class
+    xmlrpclib.Fault and wrap then as xmlrpclib.Fault exceptions with an error
+    code of 1. However, for XMLRPC Fault Interoperability, the code needs to be
+    -32500. This function wraps method execution, catches Mailman errors, and
+    raises them as xmlrpclib.Fault errors with the appropriate Fault code.
+    '''
+    
+    def foo_lambda(*args):
+        try:
+            return method_func(*args)
+        except Exception, e:
+            tb_type, tb_value, tb = sys.exc_info()
+            # default application error code is -32500
+            code = -32500
+            if tb_type == Errors.MMSubscribeNeedsConfirmation:
+                code = -32501
+            elif tb_type == Errors.MMNeedApproval:
+                code = -32502
+            elif tb_type == Errors.MMAuthenticationError:
+                code = -32503
+            error_message = str(e) + str(traceback.format_tb(tb))
+            error_message = cgi.escape(error_message)
+            raise xmlrpclib.Fault(code, error_message)
+    foo_lambda.__doc__ = method_func.__doc__
+    return foo_lambda
+
+# Set up the XMLRPC handler
+handler = DocCGIXMLRPCRequestHandler()
+handler.set_server_title(_('GNU/Mailman List Administration Interface'))
+handler.set_server_name(_('GNU/Mailman List Administration Interface'))
+handler.set_server_documentation = _(__doc__)
+handler.register_introspection_functions()
+
+__methodMap__ = {\
+    'Mailman.addMember': add_member,
+    'Mailman.deleteMember': delete_member,
+    'Mailman.changeMemberAddress': change_address, 
+    'Mailman.createList': create_list,
+    'Mailman.deleteList': delete_list}
+
+for method in __methodMap__.keys():
+    func = __methodMap__[method]
+    handler.register_function(__method_wrapper__(func), method)
diff -rNu mailman-2.1.5.virgin/src/Makefile.in mailman-2.1.5/src/Makefile.in
--- mailman-2.1.5.virgin/src/Makefile.in	2003-03-31 14:27:14.000000000 -0500
+++ mailman-2.1.5/src/Makefile.in	2005-10-14 16:25:10.000000000 -0400
@@ -71,7 +71,7 @@
 # Fixed definitions
 
 CGI_PROGS= admindb admin confirm create edithtml listinfo options \
-	private rmlist roster subscribe
+	private rmlist roster subscribe RPC2
 
 COMMONOBJS= common.o vsnprintf.o
 

Attachment: signature.asc
Description: This is a digitally signed message part

_______________________________________________
Mailman-Developers mailing list
[email protected]
http://mail.python.org/mailman/listinfo/mailman-developers
Mailman FAQ: http://www.python.org/cgi-bin/faqw-mm.py
Searchable Archives: http://www.mail-archive.com/mailman-users%40python.org/
Unsubscribe: 
http://mail.python.org/mailman/options/mailman-developers/archive%40jab.org

Security Policy: 
http://www.python.org/cgi-bin/faqw-mm.py?req=show&amp;file=faq01.027.htp

Reply via email to