[Zope-Checkins] CVS: Zope3/lib/python/Zope/Publisher/XMLRPC - IXMLRPCPublisher.py:1.1.4.1 MethodPublisher.py:1.1.4.1 XMLRPCRequest.py:1.1.2.1 XMLRPCResponse.py:1.1.2.1 __init__.py:1.1.4.1 metaConfigure.py:1.1.4.1 xmlrpc-meta.zcml:1.1.4.1

Stephan Richter srichter@cbu.edu
Wed, 27 Mar 2002 09:49:33 -0500


Update of /cvs-repository/Zope3/lib/python/Zope/Publisher/XMLRPC
In directory cvs.zope.org:/tmp/cvs-serv16355/XMLRPC

Added Files:
      Tag: Zope-3x-branch
	IXMLRPCPublisher.py MethodPublisher.py XMLRPCRequest.py 
	XMLRPCResponse.py __init__.py metaConfigure.py 
	xmlrpc-meta.zcml 
Log Message:
- Added XML-RPC support
- tweaked refactoring a little tp better support other HTTP sub-protocols
- Worked on security



=== Added File Zope3/lib/python/Zope/Publisher/XMLRPC/IXMLRPCPublisher.py ===
##############################################################################
#
# Copyright (c) 2001, 2002 Zope Corporation and Contributors. 
# All Rights Reserved.
# 
# This software is subject to the provisions of the Zope Public License,
# Version 2.0 (ZPL).  A copy of the ZPL should accompany this distribution.
# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
# FOR A PARTICULAR PURPOSE
# 
##############################################################################
"""

$Id: IXMLRPCPublisher.py,v 1.1.4.1 2002/03/27 14:49:32 srichter Exp $
"""
from Zope.Publisher.HTTP.IHTTPPublisher import IHTTPPublisher


class IXMLRPCPublisher(IHTTPPublisher):
    """This is identical to the regular HTTP version.

       This interface is used as marker.
    """



=== Added File Zope3/lib/python/Zope/Publisher/XMLRPC/MethodPublisher.py ===
##############################################################################
#
# Copyright (c) 2001, 2002 Zope Corporation and Contributors. 
# All Rights Reserved.
# 
# This software is subject to the provisions of the Zope Public License,
# Version 2.0 (ZPL).  A copy of the ZPL should accompany this distribution.
# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
# FOR A PARTICULAR PURPOSE
# 
##############################################################################
"""

$Id: MethodPublisher.py,v 1.1.4.1 2002/03/27 14:49:32 srichter Exp $
"""
from IXMLRPCPublisher import IXMLRPCPublisher
from Zope.Publisher.HTTP.DefaultPublisher import DefaultPublisher

class MethodPublisher(DefaultPublisher):
    """Simple XML-RPC publisher that is identical to the HTTP Default Publisher
       except that it implements the IXMLRPCPublisher interface. 
    """

    __implements__ = IXMLRPCPublisher


=== Added File Zope3/lib/python/Zope/Publisher/XMLRPC/XMLRPCRequest.py ===
##############################################################################
#
# Copyright (c) 2001, 2002 Zope Corporation and Contributors.
# All Rights Reserved.
# 
# This software is subject to the provisions of the Zope Public License,
# Version 2.0 (ZPL).  A copy of the ZPL should accompany this distribution.
# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
# FOR A PARTICULAR PURPOSE
# 
##############################################################################
"""

$Id: XMLRPCRequest.py,v 1.1.2.1 2002/03/27 14:49:32 srichter Exp $
"""

import xmlrpclib
from cgi import FieldStorage
from Zope.Publisher.HTTP.HTTPRequest import HTTPRequest
from IXMLRPCPublisher import IXMLRPCPublisher

from XMLRPCResponse import XMLRPCResponse

class XMLRPCRequest(HTTPRequest):

    __implements__ = HTTPRequest.__implements__

    # _viewtype is overridden from the BaseRequest 
    # to implement IXMLRPCPublisher
    _viewtype = IXMLRPCPublisher


    _args = ()


    def _createResponse(self, outstream):
        """Create a specific XML-RPC response object."""
        return XMLRPCResponse(outstream)

    
    ######################################
    # from: Zope.Publisher.IPublisherRequest.IPublisherRequest

    def processInputs(self):
        'See Zope.Publisher.IPublisherRequest.IPublisherRequest'

        # Parse the request XML structure
        self._args, function = xmlrpclib.loads(self._body_instream.read())
        # Translate '.' to '/' in function to represent object traversal.
        function = function.replace('.', '/')

        if function:
            self.setPathSuffix((function,))



class TestRequest(XMLRPCRequest):

    def __init__(self, body_instream=None, outstream=None, environ=None, **kw):

        _testEnv =  {
            'SERVER_URL':         'http://127.0.0.1',
            'HTTP_HOST':          '127.0.0.1',
            'CONTENT_LENGTH':     '0',
            'GATEWAY_INTERFACE':  'TestFooInterface/1.0',
            }

        if environ:
            _testEnv.update(environ)
        if kw:
            _testEnv.update(kw)
        if body_instream is None:
            from StringIO import StringIO
            body_instream = StringIO('')

        if outstream is None:
            outstream = StringIO()

        super(TestRequest, self).__init__(body_instream, outstream, _testEnv)
    


=== Added File Zope3/lib/python/Zope/Publisher/XMLRPC/XMLRPCResponse.py ===
##############################################################################
#
# Copyright (c) 2001, 2002 Zope Corporation and Contributors.
# All Rights Reserved.
# 
# This software is subject to the provisions of the Zope Public License,
# Version 2.0 (ZPL).  A copy of the ZPL should accompany this distribution.
# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
# FOR A PARTICULAR PURPOSE
# 
##############################################################################
"""

$Id: XMLRPCResponse.py,v 1.1.2.1 2002/03/27 14:49:32 srichter Exp $
"""

import sys
import xmlrpclib
from Zope.Publisher.HTTP.HTTPResponse import HTTPResponse
from Zope.Publisher.Exceptions import Redirect


class XMLRPCResponse(HTTPResponse):
    """XMLRPC response
    """

    def setBody(self, body):
        """Sets the body of the response
        
        Sets the return body equal to the (string) argument "body". Also
        updates the "content-length" return header.

        If the body is a 2-element tuple, then it will be treated
        as (title,body)
        
        If is_error is true then the HTML will be formatted as a Zope error
        message instead of a generic HTML page.
        """
        if isinstance(body, xmlrpclib.Fault):
            # Convert Fault object to XML-RPC response.
            body = xmlrpclib.dumps(body, methodresponse=1)
        else:
            # Marshall our body as an XML-RPC response. Strings will be sent
            # strings, integers as integers, etc. We do *not* convert
            # everything to a string first.
            if body is None:
                body = xmlrpclib.False # Argh, XML-RPC doesn't handle null
            try:
                body = xmlrpclib.dumps((body,), methodresponse=1)
            except:
                self.exception()
                return
        # Set our body to the XML-RPC message, and fix our MIME type.
        self.setHeader('content-type', 'text/xml')

        self._body = body
        self._updateContentLength()


    def handleException(self, exc_info):
        """
        """
        t, value = exc_info[:2]

        import traceback
        traceback.print_tb(exc_info[2])
        print t
        print value

        # Create an appropriate Fault object. Unfortunately, we throw away
        # most of the debugging information. More useful error reporting is
        # left as an exercise for the reader.
        Fault = xmlrpclib.Fault
        fault_text = None
        try:
            if isinstance(value, Fault):
                fault_text = value
            elif isinstance(value, Exception):
                fault_text = Fault(-1, "Unexpected Zope exception: " +
                                   str(value))
            else:
                fault_text = Fault(-2, "Unexpected Zope error value: " +
                                   str(value))
        except:
            fault_text = Fault(-3, "Unknown Zope fault type")

        # Do the damage.
        self.setBody(fault_text)
        self.setStatus(200)


=== Added File Zope3/lib/python/Zope/Publisher/XMLRPC/__init__.py ===
# Copyright (c) 2001 Zope Corporation and Contributors.  All Rights Reserved.
# 
# This software is subject to the provisions of the Zope Public License,
# Version 1.1 (ZPL).  A copy of the ZPL should accompany this distribution.
# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
# FOR A PARTICULAR PURPOSE.

#from IBrowserPublisher import IBrowserPublisher


=== Added File Zope3/lib/python/Zope/Publisher/XMLRPC/metaConfigure.py ===
##############################################################################
#
# Copyright (c) 2001, 2002 Zope Corporation and Contributors. 
# All Rights Reserved.
# 
# This software is subject to the provisions of the Zope Public License,
# Version 2.0 (ZPL).  A copy of the ZPL should accompany this distribution.
# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
# FOR A PARTICULAR PURPOSE
# 
##############################################################################
"""

$Id: metaConfigure.py,v 1.1.4.1 2002/03/27 14:49:32 srichter Exp $
"""
from Zope.ComponentArchitecture import provideView, setDefaultViewName
from Zope.Configuration.Action import Action
from IXMLRPCPublisher import IXMLRPCPublisher

    
def view(_context, name, factory, for_=None, layer=''):
    if for_ is not None:
        for_ = _context.resolve(for_)
    factory = map(_context.resolve, factory.split(' '))

    return [
        Action(
            discriminator = ('view', for_, name, IXMLRPCPublisher, layer),
            callable = provideView,
            args = (for_, name, IXMLRPCPublisher, factory, layer),
            )
        ]


=== Added File Zope3/lib/python/Zope/Publisher/XMLRPC/xmlrpc-meta.zcml ===
<zopeConfigure xmlns='http://namespaces.zope.org/zope'>
  
  <!-- Zope.Publisher.XMLRPC -->
  <directives namespace="http://namespaces.zope.org/xmlrpc">
    <directive name="view" attributes="factory, name, for"
       handler="Zope.Publisher.XMLRPC.metaConfigure.view" />
  </directives>

</zopeConfigure>