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

Stephan Richter srichter@cbu.edu
Sun, 3 Mar 2002 23:36:14 -0500


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

Added Files:
      Tag: srichter-OFS_Formulator-branch
	IXMLRPCPublisher.py MethodPublisher.py XMLRPCPayload.py 
	__init__.py metaConfigure.py xmlrpc-meta.zcml 
Log Message:
Here are some of the changes made:

- Payload now keeps trakc of View Type

- Reimplementation of {set|get}ViewType in HTTPRequest, to overload the 
  standard BaseRequest one to look in the payload vor the View Type

- Implemented XMLRPCPayload

- Created IXMLRPCPublisher interface

- Implemenyed new Publisher interface in MethodPublisher

- Created xmlrpc ZCML namespace

- Move Payloads out of HTTP directory into Browser and XMLRPC


ToDo:

- Write and update tests. (nothing done yet)

- Update interfaces and create new ones

- Work on Authentication of XML-RPC

- Get rid of the 'Hacker' lines

- More refactoring needs to be done.



=== 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.2.1 2002/03/04 04:36:13 srichter Exp $
"""
from Interface import Interface


class IXMLRPCPublisher(Interface):
    """This is very similar to the Browser version;
    """

    def xmlrpc_traverse(request, name):
        """Lookup a name
        """


    def xmlrpc_default(request):
        """Provide the default object

        """



=== 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.2.1 2002/03/04 04:36:13 srichter Exp $
"""
from IXMLRPCPublisher import IXMLRPCPublisher

class MethodPublisher:

    __implements__ = IXMLRPCPublisher

    # Implementation methods for interface
    # Zope.Publisher.XMLRPC.IXMLRPCPublisher.

    def xmlrpc_traverse(self, request, name):
        '''See interface IXMLRPCPublisher'''

        return getattr(self, name)


    def xmlrpc_default(self, request):
        '''See interface IXMLRPCPublisher'''
        return self, ("info",)


=== Added File Zope3/lib/python/Zope/Publisher/XMLRPC/XMLRPCPayload.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
# 
##############################################################################
"""
XML-RPC Request/Response Handler

$Id: XMLRPCPayload.py,v 1.1.2.1 2002/03/04 04:36:13 srichter Exp $
"""
from types import ClassType, ListType, StringType
from cgi import FieldStorage, escape
from Zope.Publisher.HTTP.cgi_names import hide_key
import xmlrpclib

from Zope.Publisher.HTTP.IPayload import IRequestPayload, IResponsePayload
from Zope.Publisher.Converters import get_converter
from Zope.Publisher.Exceptions import Redirect, Unauthorized

from IXMLRPCPublisher import IXMLRPCPublisher 

class XMLRPCRequestPayload:
    """
    Works with the body of a XML-RPC request.
    """

    __implements__ = IRequestPayload


    # XXX HACK!!!! This should be implemented via some nice
    #     methods and interface
    _viewtype = IXMLRPCPublisher
    

    def __init__(self, publication):
        self.publication = publication


    def processInputs(self, request, fs=None):
        """
        Processes form data
        """
        environ = request.environ
        form = request.form
        other = request.other
        method = environ.get('REQUEST_METHOD', 'GET')

        if fs is None:
            if method != 'GET':
                # Process form if not a GET request.
                fp = request.body_instream
            else:
                fp = None
            fs = FieldStorage(fp=fp, environ=environ, keep_blank_values=1)

        # Parse the request XML structure
        request.args, function = xmlrpclib.loads(fs.value)
        # Translate '.' to '/' in function to represent object traversal.
        function = function.replace('.', '/')

        other['REQUEST_METHOD']='' # We don't want index_html!
                     
        other.update(form)
        if function:
            request.setRequestDefault(function)


    def getPublication(self, request):
        return self.publication


    def debugInfo(self, request):
        result = "<p>URL: %s</p>" % request.URL
        result = result + "<p>SERVER_URL: %s</p>" % request.SERVER_URL
        return result

            

class XMLRPCResponsePayload:
    """Customized Response that handles XML-RPC-specific details.

    We override setBody to marhsall Python objects into XML-RPC. We
    also override exception to convert errors to XML-RPC faults.

    If these methods stop getting called, make sure that ZPublisher is
    using the xmlrpc.Response object created above and not the original
    HTTPResponse object from which it was cloned.

    It's probably possible to improve the 'exception' method quite a bit.
    The current implementation, however, should suffice for now.
    """

    __implements__ = IResponsePayload


    def setBody(self, response, body):
        """ """
        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.
        response.body = body
        response.setHeader('content-type', 'text/xml')
        return response


    def handleException(self, response, 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.
        response.setBody(fault_text)
        response.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.2.1 2002/03/04 04:36:13 srichter Exp $
"""
from Zope.ComponentArchitecture import provideView, setDefaultViewName
from Zope.Configuration.name import resolve
from Zope.Configuration.Action import Action
from IXMLRPCPublisher import IXMLRPCPublisher


def defaultView(name, factory, for_=None, layer=''):
    if for_ is not None:
        for_ = resolve(for_)
    factory = map(resolve, factory.split(' '))
    
    return [
        Action(
            discriminator = ('view', for_, name, IXMLRPCPublisher),
            callable = provideView, 
            args = (for_, name, IXMLRPCPublisher, factory, layer),
            ),
        Action(
            discriminator = ('defaultViewName', for_, name, IXMLRPCPublisher),
            callable = setDefaultViewName,
            args = (for_, IXMLRPCPublisher, name),
            )
        ]

    
def view(name, factory, for_=None, layer=''):
    if for_ is not None:
        for_ = resolve(for_)
    factory = map(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" />
    <directive name="defaultView" attributes="factory, name, for"
       handler="Zope.Publisher.XMLRPC.metaConfigure.defaultView" />
  </directives>

</zopeConfigure>