[Checkins] SVN: z3c.soap/ soap in zope2. initial import

Jean-Fran�ois Roche jfroche at jfroche.be
Thu Nov 13 07:18:52 EST 2008


Log message for revision 92902:
  soap in zope2. initial import

Changed:
  A   z3c.soap/
  A   z3c.soap/branches/
  A   z3c.soap/tags/
  A   z3c.soap/trunk/
  A   z3c.soap/trunk/bootstrap.py
  A   z3c.soap/trunk/buildout.cfg
  A   z3c.soap/trunk/docs/
  A   z3c.soap/trunk/docs/HISTORY.txt
  A   z3c.soap/trunk/setup.cfg
  A   z3c.soap/trunk/setup.py
  A   z3c.soap/trunk/z3c/
  A   z3c.soap/trunk/z3c/__init__.py
  A   z3c.soap/trunk/z3c/soap/
  A   z3c.soap/trunk/z3c/soap/HTTPRequest.py
  A   z3c.soap/trunk/z3c/soap/README.txt
  A   z3c.soap/trunk/z3c/soap/__init__.py
  A   z3c.soap/trunk/z3c/soap/ftesting.zcml
  A   z3c.soap/trunk/z3c/soap/ftests.py
  A   z3c.soap/trunk/z3c/soap/interfaces.py
  A   z3c.soap/trunk/z3c/soap/meta.zcml
  A   z3c.soap/trunk/z3c/soap/metaconfigure.py
  A   z3c.soap/trunk/z3c/soap/metadirectives.py
  A   z3c.soap/trunk/z3c/soap/patch.py
  A   z3c.soap/trunk/z3c/soap/publisher.py
  A   z3c.soap/trunk/z3c/soap/soap.py
  A   z3c.soap/trunk/z3c/soap/tests/
  A   z3c.soap/trunk/z3c/soap/tests/__init__.py
  A   z3c.soap/trunk/z3c/soap/tests/mailvalidation.py
  A   z3c.soap/trunk/z3c/soap/tests/soap.zcml
  A   z3c.soap/trunk/z3c/soap/tests/soap_error.zcml
  A   z3c.soap/trunk/z3c/soap/tests/test_directives.py
  A   z3c.soap/trunk/z3c/soap/tests/test_soappublication.py
  A   z3c.soap/trunk/z3c/soap/tests/test_soaprequest.py

-=-
Added: z3c.soap/trunk/bootstrap.py
===================================================================
--- z3c.soap/trunk/bootstrap.py	                        (rev 0)
+++ z3c.soap/trunk/bootstrap.py	2008-11-13 12:18:51 UTC (rev 92902)
@@ -0,0 +1,52 @@
+##############################################################################
+#
+# Copyright (c) 2006 Zope Corporation and Contributors.
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.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.
+#
+##############################################################################
+"""Bootstrap a buildout-based project
+
+Simply run this script in a directory containing a buildout.cfg.
+The script accepts buildout command-line options, so you can
+use the -c option to specify an alternate configuration file.
+
+$Id$
+"""
+
+import os, shutil, sys, tempfile, urllib2
+
+tmpeggs = tempfile.mkdtemp()
+
+ez = {}
+exec urllib2.urlopen('http://peak.telecommunity.com/dist/ez_setup.py'
+                     ).read() in ez
+ez['use_setuptools'](to_dir=tmpeggs, download_delay=0)
+
+import pkg_resources
+
+cmd = 'from setuptools.command.easy_install import main; main()'
+if sys.platform == 'win32':
+    cmd = '"%s"' % cmd # work around spawn lamosity on windows
+
+ws = pkg_resources.working_set
+assert os.spawnle(
+    os.P_WAIT, sys.executable, sys.executable,
+    '-c', cmd, '-mqNxd', tmpeggs, 'zc.buildout',
+    dict(os.environ,
+         PYTHONPATH=
+         ws.find(pkg_resources.Requirement.parse('setuptools')).location
+         ),
+    ) == 0
+
+ws.add_entry(tmpeggs)
+ws.require('zc.buildout')
+import zc.buildout.buildout
+zc.buildout.buildout.main(sys.argv[1:] + ['bootstrap'])
+shutil.rmtree(tmpeggs)


Property changes on: z3c.soap/trunk/bootstrap.py
___________________________________________________________________
Added: svn:keywords
   + Id

Added: z3c.soap/trunk/buildout.cfg
===================================================================
--- z3c.soap/trunk/buildout.cfg	                        (rev 0)
+++ z3c.soap/trunk/buildout.cfg	2008-11-13 12:18:51 UTC (rev 92902)
@@ -0,0 +1,41 @@
+[buildout]
+parts =
+    instance
+    test
+
+find-links =
+
+develop =
+    .
+
+eggs =
+    ZSI
+
+unzip = true
+
+[zope2]
+recipe = plone.recipe.zope2install
+url = http://www.zope.org/Products/Zope/2.10.6/Zope-2.10.6-final.tgz
+fake-zope-eggs = true
+skip-fake-eggs = zope.testing
+
+[instance]
+recipe = plone.recipe.zope2instance
+zope2-location = ${zope2:location}
+user = admin:admin
+verbose-security = on
+debug-mode = on
+eggs =
+    ${buildout:eggs}
+    zope.testing
+    z3c.soap
+
+zcml =
+    z3c.soap-meta
+
+[test]
+recipe = zc.recipe.testrunner
+eggs = z3c.soap
+defaults = ['--tests-pattern', '^f?tests$', '-c', '--module=z3c.soap']
+extra-paths = ${zope2:location}/lib/python
+

Added: z3c.soap/trunk/docs/HISTORY.txt
===================================================================
--- z3c.soap/trunk/docs/HISTORY.txt	                        (rev 0)
+++ z3c.soap/trunk/docs/HISTORY.txt	2008-11-13 12:18:51 UTC (rev 92902)
@@ -0,0 +1,8 @@
+Changelog
+=========
+
+0.1 - Unreleased
+----------------
+
+* Initial release
+


Property changes on: z3c.soap/trunk/docs/HISTORY.txt
___________________________________________________________________
Added: svn:eol-style
   + native

Added: z3c.soap/trunk/setup.cfg
===================================================================
--- z3c.soap/trunk/setup.cfg	                        (rev 0)
+++ z3c.soap/trunk/setup.cfg	2008-11-13 12:18:51 UTC (rev 92902)
@@ -0,0 +1,3 @@
+[egg_info]
+#tag_build = dev
+#tag_svn_revision = true

Added: z3c.soap/trunk/setup.py
===================================================================
--- z3c.soap/trunk/setup.py	                        (rev 0)
+++ z3c.soap/trunk/setup.py	2008-11-13 12:18:51 UTC (rev 92902)
@@ -0,0 +1,36 @@
+from setuptools import setup, find_packages
+import os
+
+version = '0.1'
+
+setup(name='z3c.soap',
+      version=version,
+      description="Soap using ZSI in Zope 2",
+      long_description=open(os.path.join("z3c", "soap",
+                                         "README.txt")).read() + "\n" +
+                       open(os.path.join("docs", "HISTORY.txt")).read(),
+      classifiers=[
+        "Environment :: Web Environment",
+        "Framework :: Zope2",
+        "Framework :: Zope3",
+        "License :: OSI Approved :: Zope Public License",
+        "Operating System :: OS Independent",
+        "Programming Language :: Python",
+        "Topic :: Internet :: WWW/HTTP :: Site Management",
+        "Topic :: Software Development :: Libraries :: Python Modules"],
+      keywords='Zope2 SOAP ZSI',
+      author='Jean-Francois Roche',
+      author_email='jfroche at affinitic.be',
+      url='http://svn.zope.org/z3c.soap',
+      license='ZPL 2.1',
+      packages=find_packages(exclude=['ez_setup']),
+      namespace_packages=['z3c'],
+      include_package_data=True,
+      zip_safe=False,
+      install_requires=[
+          'setuptools',
+          'ZSI'],
+      entry_points="""
+      # -*- Entry points: -*-
+      """,
+      )


Property changes on: z3c.soap/trunk/setup.py
___________________________________________________________________
Added: svn:keywords
   + Id

Added: z3c.soap/trunk/z3c/__init__.py
===================================================================
--- z3c.soap/trunk/z3c/__init__.py	                        (rev 0)
+++ z3c.soap/trunk/z3c/__init__.py	2008-11-13 12:18:51 UTC (rev 92902)
@@ -0,0 +1,6 @@
+# See http://peak.telecommunity.com/DevCenter/setuptools#namespace-packages
+try:
+    __import__('pkg_resources').declare_namespace(__name__)
+except ImportError:
+    from pkgutil import extend_path
+    __path__ = extend_path(__path__, __name__)


Property changes on: z3c.soap/trunk/z3c/__init__.py
___________________________________________________________________
Added: svn:keywords
   + Id

Added: z3c.soap/trunk/z3c/soap/HTTPRequest.py
===================================================================
--- z3c.soap/trunk/z3c/soap/HTTPRequest.py	                        (rev 0)
+++ z3c.soap/trunk/z3c/soap/HTTPRequest.py	2008-11-13 12:18:51 UTC (rev 92902)
@@ -0,0 +1,726 @@
+##############################################################################
+#
+# Copyright (c) 2001 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
+#
+##############################################################################
+
+__version__='$Revision: 1.90.2.6 $'[11:-2]
+
+import re
+from cgi import FieldStorage, escape
+from ZPublisher.Converters import get_converter
+from ZPublisher.HTTPRequest import *
+from z3c.soap.interfaces import ISOAPRequest
+from ZPublisher.TaintedString import TaintedString
+from zope.interface import directlyProvides
+xmlrpc=None # Placeholder for module that we'll import if we have to.
+soap=None
+
+def processInputs(
+        self,
+        # "static" variables that we want to be local for speed
+        SEQUENCE=1,
+        DEFAULT=2,
+        RECORD=4,
+        RECORDS=8,
+        REC=12, # RECORD|RECORDS
+        EMPTY=16,
+        CONVERTED=32,
+        hasattr=hasattr,
+        getattr=getattr,
+        setattr=setattr,
+        search_type=re.compile('(:[a-zA-Z][-a-zA-Z0-9_]+|\\.[xy])$').search,
+        ):
+        """Process request inputs
+
+        We need to delay input parsing so that it is done under
+        publisher control for error handling purposes.
+        """
+        response=self.response
+        environ=self.environ
+        method=environ.get('REQUEST_METHOD','GET')
+
+        if method != 'GET': fp=self.stdin
+        else:               fp=None
+
+        form=self.form
+        other=self.other
+        taintedform=self.taintedform
+
+        meth=None
+        fs=FieldStorage(fp=fp,environ=environ,keep_blank_values=1)
+        if not hasattr(fs,'list') or fs.list is None:
+            contentType = None
+            if fs.headers.has_key('content-type'):
+              contentType = fs.headers['content-type']
+              # cut off a possible charset definition
+              if contentType.find(';') >= 0:
+                contentType = contentType[0:contentType.find(';')]
+            # Hm, maybe it's an SOAP
+            # SOAP 1.1 has HTTP SOAPAction Field
+            # SOAP 1.2 has Content-Type application/soap+xml
+            #
+            # found a Content-Type of text/xml-SOAP on a Microsoft page
+            # this page points 3 HTTP-Fields for SOAP Requests:
+            # MethodName, InterfaceName (opt) and MessageCall
+            #
+            if (environ.has_key('HTTP_SOAPACTION') or
+                (contentType in ['application/soap+xml',
+                                'text/xml',
+                                 'text/xml-SOAP']) and fs.value.find('SOAP-ENV:Body') > 0):
+                global soap
+                if soap is None:
+                      import soap
+                fp.seek(0)
+                directlyProvides(self, ISOAPRequest)
+                sparser = soap.SOAPParser(fp.read())
+                meth = sparser.method
+                self.args = sparser.parse()
+                response = soap.SOAPResponse(response)
+                response._soap11 = environ.has_key('HTTP_SOAPACTION')
+                response._soap12 = (contentType == 'application/soap+xml')
+                response._contentType = contentType
+                response._method = meth
+                response._error_format = 'text/xml'
+                other['RESPONSE'] = self.response = response
+                other['REQUEST_METHOD'] = method
+                self.maybe_webdav_client = 0
+
+            # Hm, maybe it's an XML-RPC
+            # check for a real XML-RPC methodCall !
+            # This allows to post normal text/xml files to Zope !
+            elif (contentType == 'text/xml' and method == 'POST' and fs.value.find('<methodCall>') > 0):
+                # Ye haaa, XML-RPC!
+                global xmlrpc
+                if xmlrpc is None: from ZPublisher import xmlrpc
+                meth, self.args = xmlrpc.parse_input(fs.value)
+                response=xmlrpc.response(response)
+                other['RESPONSE']=self.response=response
+                self.maybe_webdav_client = 0
+            else:
+                self._file=fs.file
+        else:
+            fslist=fs.list
+            tuple_items={}
+            lt=type([])
+            CGI_name=isCGI_NAME
+            defaults={}
+            tainteddefaults={}
+            converter=None
+
+            for item in fslist:
+
+                isFileUpload = 0
+                key=item.name
+                if (hasattr(item,'file') and hasattr(item,'filename')
+                    and hasattr(item,'headers')):
+                    if (item.file and
+                        (item.filename is not None
+                         # RFC 1867 says that all fields get a content-type.
+                         # or 'content-type' in map(lower, item.headers.keys())
+                         )):
+                        item=FileUpload(item)
+                        isFileUpload = 1
+                    else:
+                        item=item.value
+
+                flags=0
+                character_encoding = ''
+                # Variables for potentially unsafe values.
+                tainted = None
+                converter_type = None
+
+                # Loop through the different types and set
+                # the appropriate flags
+
+                # We'll search from the back to the front.
+                # We'll do the search in two steps.  First, we'll
+                # do a string search, and then we'll check it with
+                # a re search.
+
+
+                l=key.rfind(':')
+                if l >= 0:
+                    mo = search_type(key,l)
+                    if mo: l=mo.start(0)
+                    else:  l=-1
+
+                    while l >= 0:
+                        type_name=key[l+1:]
+                        key=key[:l]
+                        c=get_converter(type_name, None)
+
+                        if c is not None:
+                            converter=c
+                            converter_type = type_name
+                            flags=flags|CONVERTED
+                        elif type_name == 'list':
+                            flags=flags|SEQUENCE
+                        elif type_name == 'tuple':
+                            tuple_items[key]=1
+                            flags=flags|SEQUENCE
+                        elif (type_name == 'method' or type_name == 'action'):
+                            if l: meth=key
+                            else: meth=item
+                        elif (type_name == 'default_method' or type_name == \
+                              'default_action'):
+                            if not meth:
+                                if l: meth=key
+                                else: meth=item
+                        elif type_name == 'default':
+                            flags=flags|DEFAULT
+                        elif type_name == 'record':
+                            flags=flags|RECORD
+                        elif type_name == 'records':
+                            flags=flags|RECORDS
+                        elif type_name == 'ignore_empty':
+                            if not item: flags=flags|EMPTY
+                        elif has_codec(type_name):
+                            character_encoding = type_name
+
+                        l=key.rfind(':')
+                        if l < 0: break
+                        mo=search_type(key,l)
+                        if mo: l = mo.start(0)
+                        else:  l = -1
+
+
+
+                # Filter out special names from form:
+                if CGI_name(key) or key[:5]=='HTTP_': continue
+
+                # If the key is tainted, mark it so as well.
+                tainted_key = key
+                if '<' in key:
+                    tainted_key = TaintedString(key)
+
+                if flags:
+
+                    # skip over empty fields
+                    if flags&EMPTY: continue
+
+                    #Split the key and its attribute
+                    if flags&REC:
+                        key=key.split(".")
+                        key, attr=".".join(key[:-1]), key[-1]
+
+                        # Update the tainted_key if necessary
+                        tainted_key = key
+                        if '<' in key:
+                            tainted_key = TaintedString(key)
+
+                        # Attributes cannot hold a <.
+                        if '<' in attr:
+                            raise ValueError(
+                                "%s is not a valid record attribute name" %
+                                escape(attr))
+
+                    # defer conversion
+                    if flags&CONVERTED:
+                        try:
+                            if character_encoding:
+                                # We have a string with a specified character encoding.
+                                # This gets passed to the converter either as unicode, if it can
+                                # handle it, or crunched back down to latin-1 if it can not.
+                                item = unicode(item,character_encoding)
+                                if hasattr(converter,'convert_unicode'):
+                                    item = converter.convert_unicode(item)
+                                else:
+                                    item = converter(item.encode('iso-8859-15'))
+                            else:
+                                item=converter(item)
+
+                            # Flag potentially unsafe values
+                            if converter_type in ('string', 'required', 'text',
+                                                  'ustring', 'utext'):
+                                if not isFileUpload and '<' in item:
+                                    tainted = TaintedString(item)
+                            elif converter_type in ('tokens', 'lines',
+                                                    'utokens', 'ulines'):
+                                is_tainted = 0
+                                tainted = item[:]
+                                for i in range(len(tainted)):
+                                    if '<' in tainted[i]:
+                                        is_tainted = 1
+                                        tainted[i] = TaintedString(tainted[i])
+                                if not is_tainted:
+                                    tainted = None
+
+                        except:
+                            if (not item and not (flags&DEFAULT) and
+                                defaults.has_key(key)):
+                                item = defaults[key]
+                                if flags&RECORD:
+                                    item=getattr(item,attr)
+                                if flags&RECORDS:
+                                    item = getattr(item[-1], attr)
+                                if tainteddefaults.has_key(tainted_key):
+                                    tainted = tainteddefaults[tainted_key]
+                                    if flags&RECORD:
+                                        tainted = getattr(tainted, attr)
+                                    if flags&RECORDS:
+                                        tainted = getattr(tainted[-1], attr)
+                            else:
+                                raise
+
+                    elif not isFileUpload and '<' in item:
+                        # Flag potentially unsafe values
+                        tainted = TaintedString(item)
+
+                    # If the key is tainted, we need to store stuff in the
+                    # tainted dict as well, even if the value is safe.
+                    if '<' in tainted_key and tainted is None:
+                        tainted = item
+
+                    #Determine which dictionary to use
+                    if flags&DEFAULT:
+                        mapping_object = defaults
+                        tainted_mapping = tainteddefaults
+                    else:
+                        mapping_object = form
+                        tainted_mapping = taintedform
+
+                    #Insert in dictionary
+                    if mapping_object.has_key(key):
+                        if flags&RECORDS:
+                            #Get the list and the last record
+                            #in the list. reclist is mutable.
+                            reclist = mapping_object[key]
+                            x = reclist[-1]
+
+                            if tainted:
+                                # Store a tainted copy as well
+                                if not tainted_mapping.has_key(tainted_key):
+                                    tainted_mapping[tainted_key] = deepcopy(
+                                        reclist)
+                                treclist = tainted_mapping[tainted_key]
+                                lastrecord = treclist[-1]
+
+                                if not hasattr(lastrecord, attr):
+                                    if flags&SEQUENCE: tainted = [tainted]
+                                    setattr(lastrecord, attr, tainted)
+                                else:
+                                    if flags&SEQUENCE:
+                                        getattr(lastrecord,
+                                            attr).append(tainted)
+                                    else:
+                                        newrec = record()
+                                        setattr(newrec, attr, tainted)
+                                        treclist.append(newrec)
+
+                            elif tainted_mapping.has_key(tainted_key):
+                                # If we already put a tainted value into this
+                                # recordset, we need to make sure the whole
+                                # recordset is built.
+                                treclist = tainted_mapping[tainted_key]
+                                lastrecord = treclist[-1]
+                                copyitem = item
+
+                                if not hasattr(lastrecord, attr):
+                                    if flags&SEQUENCE: copyitem = [copyitem]
+                                    setattr(lastrecord, attr, copyitem)
+                                else:
+                                    if flags&SEQUENCE:
+                                        getattr(lastrecord,
+                                            attr).append(copyitem)
+                                    else:
+                                        newrec = record()
+                                        setattr(newrec, attr, copyitem)
+                                        treclist.append(newrec)
+
+                            if not hasattr(x,attr):
+                                #If the attribute does not
+                                #exist, setit
+                                if flags&SEQUENCE: item=[item]
+                                setattr(x,attr,item)
+                            else:
+                                if flags&SEQUENCE:
+                                    # If the attribute is a
+                                    # sequence, append the item
+                                    # to the existing attribute
+                                    y = getattr(x, attr)
+                                    y.append(item)
+                                    setattr(x, attr, y)
+                                else:
+                                    # Create a new record and add
+                                    # it to the list
+                                    n=record()
+                                    setattr(n,attr,item)
+                                    mapping_object[key].append(n)
+                        elif flags&RECORD:
+                            b=mapping_object[key]
+                            if flags&SEQUENCE:
+                                item=[item]
+                                if not hasattr(b,attr):
+                                    # if it does not have the
+                                    # attribute, set it
+                                    setattr(b,attr,item)
+                                else:
+                                    # it has the attribute so
+                                    # append the item to it
+                                    setattr(b,attr,getattr(b,attr)+item)
+                            else:
+                                # it is not a sequence so
+                                # set the attribute
+                                setattr(b,attr,item)
+
+                            # Store a tainted copy as well if necessary
+                            if tainted:
+                                if not tainted_mapping.has_key(tainted_key):
+                                    tainted_mapping[tainted_key] = deepcopy(
+                                        mapping_object[key])
+                                b = tainted_mapping[tainted_key]
+                                if flags&SEQUENCE:
+                                    seq = getattr(b, attr, [])
+                                    seq.append(tainted)
+                                    setattr(b, attr, seq)
+                                else:
+                                    setattr(b, attr, tainted)
+
+                            elif tainted_mapping.has_key(tainted_key):
+                                # If we already put a tainted value into this
+                                # record, we need to make sure the whole record
+                                # is built.
+                                b = tainted_mapping[tainted_key]
+                                if flags&SEQUENCE:
+                                    seq = getattr(b, attr, [])
+                                    seq.append(item)
+                                    setattr(b, attr, seq)
+                                else:
+                                    setattr(b, attr, item)
+
+                        else:
+                            # it is not a record or list of records
+                            found=mapping_object[key]
+
+                            if tainted:
+                                # Store a tainted version if necessary
+                                if not tainted_mapping.has_key(tainted_key):
+                                    copied = deepcopy(found)
+                                    if isinstance(copied, lt):
+                                        tainted_mapping[tainted_key] = copied
+                                    else:
+                                        tainted_mapping[tainted_key] = [copied]
+                                tainted_mapping[tainted_key].append(tainted)
+
+                            elif tainted_mapping.has_key(tainted_key):
+                                # We may already have encountered a tainted
+                                # value for this key, and the tainted_mapping
+                                # needs to hold all the values.
+                                tfound = tainted_mapping[tainted_key]
+                                if isinstance(tfound, lt):
+                                    tainted_mapping[tainted_key].append(item)
+                                else:
+                                    tainted_mapping[tainted_key] = [tfound,
+                                                                    item]
+
+                            if type(found) is lt:
+                                found.append(item)
+                            else:
+                                found=[found,item]
+                                mapping_object[key]=found
+                    else:
+                        # The dictionary does not have the key
+                        if flags&RECORDS:
+                            # Create a new record, set its attribute
+                            # and put it in the dictionary as a list
+                            a = record()
+                            if flags&SEQUENCE: item=[item]
+                            setattr(a,attr,item)
+                            mapping_object[key]=[a]
+
+                            if tainted:
+                                # Store a tainted copy if necessary
+                                a = record()
+                                if flags&SEQUENCE: tainted = [tainted]
+                                setattr(a, attr, tainted)
+                                tainted_mapping[tainted_key] = [a]
+
+                        elif flags&RECORD:
+                            # Create a new record, set its attribute
+                            # and put it in the dictionary
+                            if flags&SEQUENCE: item=[item]
+                            r = mapping_object[key]=record()
+                            setattr(r,attr,item)
+
+                            if tainted:
+                                # Store a tainted copy if necessary
+                                if flags&SEQUENCE: tainted = [tainted]
+                                r = tainted_mapping[tainted_key] = record()
+                                setattr(r, attr, tainted)
+                        else:
+                            # it is not a record or list of records
+                            if flags&SEQUENCE: item=[item]
+                            mapping_object[key]=item
+
+                            if tainted:
+                                # Store a tainted copy if necessary
+                                if flags&SEQUENCE: tainted = [tainted]
+                                tainted_mapping[tainted_key] = tainted
+
+                else:
+                    # This branch is for case when no type was specified.
+                    mapping_object = form
+
+                    if not isFileUpload and '<' in item:
+                        tainted = TaintedString(item)
+                    elif '<' in key:
+                        tainted = item
+
+                    #Insert in dictionary
+                    if mapping_object.has_key(key):
+                        # it is not a record or list of records
+                        found=mapping_object[key]
+
+                        if tainted:
+                            # Store a tainted version if necessary
+                            if not taintedform.has_key(tainted_key):
+                                copied = deepcopy(found)
+                                if isinstance(copied, lt):
+                                    taintedform[tainted_key] = copied
+                                else:
+                                    taintedform[tainted_key] = [copied]
+                            elif not isinstance(taintedform[tainted_key], lt):
+                                taintedform[tainted_key] = [
+                                    taintedform[tainted_key]]
+                            taintedform[tainted_key].append(tainted)
+
+                        elif taintedform.has_key(tainted_key):
+                            # We may already have encountered a tainted value
+                            # for this key, and the taintedform needs to hold
+                            # all the values.
+                            tfound = taintedform[tainted_key]
+                            if isinstance(tfound, lt):
+                                taintedform[tainted_key].append(item)
+                            else:
+                                taintedform[tainted_key] = [tfound, item]
+
+                        if type(found) is lt:
+                            found.append(item)
+                        else:
+                            found=[found,item]
+                            mapping_object[key]=found
+                    else:
+                        mapping_object[key]=item
+                        if tainted:
+                            taintedform[tainted_key] = tainted
+
+            #insert defaults into form dictionary
+            if defaults:
+                for key, value in defaults.items():
+                    tainted_key = key
+                    if '<' in key: tainted_key = TaintedString(key)
+
+                    if not form.has_key(key):
+                        # if the form does not have the key,
+                        # set the default
+                        form[key]=value
+
+                        if tainteddefaults.has_key(tainted_key):
+                            taintedform[tainted_key] = \
+                                tainteddefaults[tainted_key]
+                    else:
+                        #The form has the key
+                        tdefault = tainteddefaults.get(tainted_key, value)
+                        if isinstance(value, record):
+                            # if the key is mapped to a record, get the
+                            # record
+                            r = form[key]
+
+                            # First deal with tainted defaults.
+                            if taintedform.has_key(tainted_key):
+                                tainted = taintedform[tainted_key]
+                                for k, v in tdefault.__dict__.items():
+                                    if not hasattr(tainted, k):
+                                        setattr(tainted, k, v)
+
+                            elif tainteddefaults.has_key(tainted_key):
+                                # Find out if any of the tainted default
+                                # attributes needs to be copied over.
+                                missesdefault = 0
+                                for k, v in tdefault.__dict__.items():
+                                    if not hasattr(r, k):
+                                        missesdefault = 1
+                                        break
+                                if missesdefault:
+                                    tainted = deepcopy(r)
+                                    for k, v in tdefault.__dict__.items():
+                                        if not hasattr(tainted, k):
+                                            setattr(tainted, k, v)
+                                    taintedform[tainted_key] = tainted
+
+                            for k, v in value.__dict__.items():
+                                # loop through the attributes and value
+                                # in the default dictionary
+                                if not hasattr(r, k):
+                                    # if the form dictionary doesn't have
+                                    # the attribute, set it to the default
+                                    setattr(r,k,v)
+                            form[key] = r
+
+                        elif isinstance(value, lt):
+                            # the default value is a list
+                            l = form[key]
+                            if not isinstance(l, lt):
+                                l = [l]
+
+                            # First deal with tainted copies
+                            if taintedform.has_key(tainted_key):
+                                tainted = taintedform[tainted_key]
+                                if not isinstance(tainted, lt):
+                                    tainted = [tainted]
+                                for defitem in tdefault:
+                                    if isinstance(defitem, record):
+                                        for k, v in defitem.__dict__.items():
+                                            for origitem in tainted:
+                                                if not hasattr(origitem, k):
+                                                    setattr(origitem, k, v)
+                                    else:
+                                        if not defitem in tainted:
+                                            tainted.append(defitem)
+                                taintedform[tainted_key] = tainted
+
+                            elif tainteddefaults.has_key(tainted_key):
+                                missesdefault = 0
+                                for defitem in tdefault:
+                                    if isinstance(defitem, record):
+                                        try:
+                                            for k, v in \
+                                                defitem.__dict__.items():
+                                                for origitem in l:
+                                                    if not hasattr(origitem, k):
+                                                        missesdefault = 1
+                                                        raise NestedLoopExit
+                                        except NestedLoopExit:
+                                            break
+                                    else:
+                                        if not defitem in l:
+                                            missesdefault = 1
+                                            break
+                                if missesdefault:
+                                    tainted = deepcopy(l)
+                                    for defitem in tdefault:
+                                        if isinstance(defitem, record):
+                                            for k, v in defitem.__dict__.items():
+                                                for origitem in tainted:
+                                                    if not hasattr(origitem, k):
+                                                        setattr(origitem, k, v)
+                                        else:
+                                            if not defitem in tainted:
+                                                tainted.append(defitem)
+                                    taintedform[tainted_key] = tainted
+
+                            for x in value:
+                                # for each x in the list
+                                if isinstance(x, record):
+                                    # if the x is a record
+                                    for k, v in x.__dict__.items():
+
+                                        # loop through each
+                                        # attribute and value in
+                                        # the record
+
+                                        for y in l:
+
+                                            # loop through each
+                                            # record in the form
+                                            # list if it doesn't
+                                            # have the attributes
+                                            # in the default
+                                            # dictionary, set them
+
+                                            if not hasattr(y, k):
+                                                setattr(y, k, v)
+                                else:
+                                    # x is not a record
+                                    if not x in l:
+                                        l.append(x)
+                            form[key] = l
+                        else:
+                            # The form has the key, the key is not mapped
+                            # to a record or sequence so do nothing
+                            pass
+
+            # Convert to tuples
+            if tuple_items:
+                for key in tuple_items.keys():
+                    # Split the key and get the attr
+                    k=key.split( ".")
+                    k,attr='.'.join(k[:-1]), k[-1]
+                    a = attr
+                    new = ''
+                    # remove any type_names in the attr
+                    while not a=='':
+                        a=a.split( ":")
+                        a,new=':'.join(a[:-1]), a[-1]
+                    attr = new
+                    if form.has_key(k):
+                        # If the form has the split key get its value
+                        tainted_split_key = k
+                        if '<' in k: tainted_split_key = TaintedString(k)
+                        item =form[k]
+                        if isinstance(item, record):
+                            # if the value is mapped to a record, check if it
+                            # has the attribute, if it has it, convert it to
+                            # a tuple and set it
+                            if hasattr(item,attr):
+                                value=tuple(getattr(item,attr))
+                                setattr(item,attr,value)
+                        else:
+                            # It is mapped to a list of  records
+                            for x in item:
+                                # loop through the records
+                                if hasattr(x, attr):
+                                    # If the record has the attribute
+                                    # convert it to a tuple and set it
+                                    value=tuple(getattr(x,attr))
+                                    setattr(x,attr,value)
+
+                        # Do the same for the tainted counterpart
+                        if taintedform.has_key(tainted_split_key):
+                            tainted = taintedform[tainted_split_key]
+                            if isinstance(item, record):
+                                seq = tuple(getattr(tainted, attr))
+                                setattr(tainted, attr, seq)
+                            else:
+                                for trec in tainted:
+                                    if hasattr(trec, attr):
+                                        seq = getattr(trec, attr)
+                                        seq = tuple(seq)
+                                        setattr(trec, attr, seq)
+                    else:
+                        # the form does not have the split key
+                        tainted_key = key
+                        if '<' in key: tainted_key = TaintedString(key)
+                        if form.has_key(key):
+                            # if it has the original key, get the item
+                            # convert it to a tuple
+                            item=form[key]
+                            item=tuple(form[key])
+                            form[key]=item
+
+                        if taintedform.has_key(tainted_key):
+                            tainted = tuple(taintedform[tainted_key])
+                            taintedform[tainted_key] = tainted
+
+        if meth:
+            if environ.has_key('PATH_INFO'):
+                path=environ['PATH_INFO']
+                while path[-1:]=='/': path=path[:-1]
+            else: path=''
+            other['PATH_INFO']=path="%s/%s" % (path,meth)
+            self._hacked_path=1
+
+HTTPRequest.processInputs = processInputs
+import logging
+logger = logging.getLogger('Zope')
+logger.info("""SOAPSupport: modified ZPublisher.HTTPRequest.processInputs, Dirk Datzert, 2007-02-06, version for Zope-2.8.x/Zope-2.9.x/Zope-2.10.x\n""")
+
+# vi:ts=4


Property changes on: z3c.soap/trunk/z3c/soap/HTTPRequest.py
___________________________________________________________________
Added: svn:keywords
   + Id

Added: z3c.soap/trunk/z3c/soap/README.txt
===================================================================
--- z3c.soap/trunk/z3c/soap/README.txt	                        (rev 0)
+++ z3c.soap/trunk/z3c/soap/README.txt	2008-11-13 12:18:51 UTC (rev 92902)
@@ -0,0 +1,654 @@
+SOAP Support
+============
+
+This SOAP implementation allows you provide SOAP views for objects. The
+SOAP layer is based on `ZSI <http://pywebsvcs.sourceforge.net/>`__.
+
+The package requires ZSI 2.0 or better.
+
+SOAP support is implemented in a way very similar to the standard Zope
+XML-RPC support.  To call methods via SOAP, you need to create and
+register SOAP views.
+
+This package is largely inspired from Zope 3 SOAP (http://svn.zope.org/soap).
+
+Let's write a simple SOAP view that echoes various types of input:
+
+  >>> from Products.Five import BrowserView
+  >>> class EchoView(BrowserView):
+  ...
+  ...     def echoString(self, value):
+  ...         return value
+  ...
+  ...     def echoStringArray(self, value):
+  ...         return value
+  ...
+  ...     def echoInteger(self, value):
+  ...         return value
+  ...
+  ...     def echoIntegerArray(self, value):
+  ...         return value
+  ...
+  ...     def echoFloat(self, value):
+  ...         return value
+  ...
+  ...     def echoFloatArray(self, value):
+  ...         return value
+  ...
+  ...     def echoStruct(self, value):
+  ...         return value
+  ...
+  ...     def echoStructArray(self, value):
+  ...         return value
+  ...
+  ...     def echoVoid(self):
+  ...         return
+  ...
+  ...     def echoBase64(self, value):
+  ...         import base64
+  ...         return base64.encodestring(value)
+  ...
+  ...     def echoDate(self, value):
+  ...         import time
+  ...         return time.gmtime(time.mktime(value))
+  ...
+  ...     def echoDecimal(self, value):
+  ...         return value
+  ...
+  ...     def echoBoolean(self, value):
+  ...         return value
+  ...
+  ...     def ValidateEmailRequest(self, requestData, response):
+  ...         mail = requestData._Email
+  ...         response._Status = '%s is OK' % mail
+  ...         return response
+
+
+Now we'll register it as a SOAP view. For now we'll just register the
+view for folder objects and call it on the root folder:
+
+  >>> from zope.configuration import xmlconfig
+  >>> ignored = xmlconfig.string("""
+  ... <configure
+  ...     xmlns="http://namespaces.zope.org/zope"
+  ...     xmlns:browser="http://namespaces.zope.org/browser"
+  ...     xmlns:soap="http://namespaces.zope.org/soap"
+  ...     >
+  ...
+  ...   <!-- We only need to do this include in this example,
+  ...        Normally the include has already been done for us. -->
+  ...
+  ...   <include package="z3c.soap" file="meta.zcml" />
+  ...   <include package="Products.Five" file="meta.zcml" />
+  ...
+  ...   <soap:view
+  ...       for="OFS.interfaces.IFolder"
+  ...       methods="echoString echoStringArray echoInteger echoIntegerArray
+  ...                echoFloat echoFloatArray echoStruct echoVoid echoBase64
+  ...                echoDate echoDecimal echoBoolean ValidateEmailRequest"
+  ...       class="z3c.soap.README.EchoView"
+  ...       permission="cmf.ManageProperties"
+  ...       />
+  ...
+  ...   <utility
+  ...       factory="z3c.soap.tests.mailvalidation.validateEmailIn"
+  ...       name="ValidateEmailRequest"
+  ...       provides="z3c.soap.interfaces.IZSIRequestType"/>
+  ...
+  ...   <utility
+  ...       factory="z3c.soap.tests.mailvalidation.validateEmailOut"
+  ...       name="ValidateEmailRequest"
+  ...       provides="z3c.soap.interfaces.IZSIResponseType"/>
+  ...
+  ...
+  ... </configure>
+  ... """)
+
+
+And call our SOAP method:
+
+  >>> from Testing.ZopeTestCase import user_name, user_password
+  >>> self.setRoles(['Manager'])
+
+  >>> print http(r"""
+  ... POST /test_folder_1_ HTTP/1.0
+  ... Authorization: Basic %s:%s
+  ... Content-Length: 102
+  ... Content-Type: text/xml
+  ... SOAPAction: /
+  ...
+  ... <?xml version="1.0"?>
+  ... <SOAP-ENV:Envelope
+  ...  SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"
+  ...  xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/"
+  ...  xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"
+  ...  xmlns:xsd="http://www.w3.org/2001/XMLSchema"
+  ...  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
+  ...  <SOAP-ENV:Body>
+  ...    <m:echoString xmlns:m="http://www.soapware.org/">
+  ...      <arg1 xsi:type="xsd:string">hello</arg1>
+  ...    </m:echoString>
+  ...  </SOAP-ENV:Body>
+  ... </SOAP-ENV:Envelope>
+  ... """ % (user_name, user_password), handle_errors=True)
+  HTTP/1.0 200 OK
+  Content-Length: ...
+  Content-Type: text/xml
+  <BLANKLINE>
+  ...hello...
+
+
+Note that we get an unauthorized error if we don't supply authentication
+credentials, because we protected the view with the ManageContent permission
+when we registered it:
+
+  >>> self.logout()
+  >>> print http(r"""
+  ... POST /test_folder_1_ HTTP/1.0
+  ... Content-Length: 102
+  ... Content-Type: text/xml
+  ... SOAPAction: /
+  ...
+  ... <?xml version="1.0"?>
+  ... <SOAP-ENV:Envelope
+  ...  SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"
+  ...  xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/"
+  ...  xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"
+  ...  xmlns:xsd="http://www.w3.org/2001/XMLSchema"
+  ...  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
+  ...  <SOAP-ENV:Body>
+  ...    <m:echoString xmlns:m="http://www.soapware.org/">
+  ...      <arg1 xsi:type="xsd:string">hello</arg1>
+  ...    </m:echoString>
+  ...  </SOAP-ENV:Body>
+  ... </SOAP-ENV:Envelope>
+  ... """)
+  HTTP/1.0 401 Unauthorized
+  ...
+
+
+Parameters
+----------
+
+SOAP views can take any parameters that ZSI can understand. The following
+demonstrate the use of primitive SOAP-defined types:
+
+  >>> print http(r"""
+  ... POST /test_folder_1_ HTTP/1.0
+  ... Authorization: Basic %s:%s
+  ... Content-Length: 102
+  ... Content-Type: text/xml
+  ... SOAPAction: /
+  ...
+  ... <?xml version="1.0"?>
+  ... <SOAP-ENV:Envelope
+  ...  SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"
+  ...  xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/"
+  ...  xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"
+  ...  xmlns:xsd="http://www.w3.org/2001/XMLSchema"
+  ...  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
+  ...  <SOAP-ENV:Body>
+  ...    <m:echoString xmlns:m="http://www.soapware.org/">
+  ...      <arg1 xsi:type="xsd:string">hello</arg1>
+  ...    </m:echoString>
+  ...  </SOAP-ENV:Body>
+  ... </SOAP-ENV:Envelope>
+  ... """ % (user_name, user_password))
+  HTTP/1.0 200 OK
+  Content-Length: ...
+  Content-Type: text/xml...
+  <BLANKLINE>
+  ...hello...
+
+
+  >>> print http(r"""
+  ... POST /test_folder_1_ HTTP/1.0
+  ... Authorization: Basic %s:%s
+  ... Content-Length: 102
+  ... Content-Type: text/xml
+  ... SOAPAction: /
+  ...
+  ... <?xml version="1.0"?>
+  ... <SOAP-ENV:Envelope
+  ...  SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"
+  ...  xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/"
+  ...  xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"
+  ...  xmlns:xsd="http://www.w3.org/2001/XMLSchema"
+  ...  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
+  ...  <SOAP-ENV:Body>
+  ...    <m:echoStringArray xmlns:m="http://www.soapware.org/">
+  ...    <param SOAP-ENC:arrayType="xsd:ur-type[4]" xsi:type="SOAP-ENC:Array">
+  ...    <item xsi:type="xsd:string">one</item>
+  ...    <item xsi:type="xsd:string">two</item>
+  ...    <item xsi:type="xsd:string">three</item>
+  ...    <item xsi:type="xsd:string">four</item>
+  ...    </param>
+  ...    </m:echoStringArray>
+  ...  </SOAP-ENV:Body>
+  ... </SOAP-ENV:Envelope>
+  ... """ % (user_name, user_password))
+  HTTP/1.0 200 OK
+  Content-Length: ...
+  Content-Type: text/xml...
+  <BLANKLINE>
+  ...one...two...three...four...
+
+
+  >>> print http(r"""
+  ... POST /test_folder_1_ HTTP/1.0
+  ... Authorization: Basic %s:%s
+  ... Content-Length: 102
+  ... Content-Type: text/xml
+  ... SOAPAction: /
+  ...
+  ... <?xml version="1.0"?>
+  ... <SOAP-ENV:Envelope
+  ...  SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"
+  ...  xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/"
+  ...  xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"
+  ...  xmlns:xsd="http://www.w3.org/2001/XMLSchema"
+  ...  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
+  ...  <SOAP-ENV:Body>
+  ...    <m:echoInteger xmlns:m="http://www.soapware.org/">
+  ...      <arg1 xsi:type="xsd:int">42</arg1>
+  ...    </m:echoInteger>
+  ...  </SOAP-ENV:Body>
+  ... </SOAP-ENV:Envelope>
+  ... """ % (user_name, user_password))
+  HTTP/1.0 200 OK
+  Content-Length: ...
+  Content-Type: text/xml...
+  <BLANKLINE>
+  ...42...
+
+
+  >>> print http(r"""
+  ... POST /test_folder_1_ HTTP/1.0
+  ... Authorization: Basic %s:%s
+  ... Content-Length: 102
+  ... Content-Type: text/xml
+  ... SOAPAction: /
+  ...
+  ... <?xml version="1.0"?>
+  ... <SOAP-ENV:Envelope
+  ...  SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"
+  ...  xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/"
+  ...  xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"
+  ...  xmlns:xsd="http://www.w3.org/2001/XMLSchema"
+  ...  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
+  ...  <SOAP-ENV:Body>
+  ...    <m:echoIntegerArray xmlns:m="http://www.soapware.org/">
+  ...    <param SOAP-ENC:arrayType="xsd:ur-type[4]" xsi:type="SOAP-ENC:Array">
+  ...    <item xsi:type="xsd:int">1</item>
+  ...    <item xsi:type="xsd:int">2</item>
+  ...    <item xsi:type="xsd:int">3</item>
+  ...    <item xsi:type="xsd:int">4</item>
+  ...    </param>
+  ...    </m:echoIntegerArray>
+  ...  </SOAP-ENV:Body>
+  ... </SOAP-ENV:Envelope>
+  ... """ % (user_name, user_password))
+  HTTP/1.0 200 OK
+  Content-Length: ...
+  Content-Type: text/xml...
+  <BLANKLINE>
+  ...1...2...3...4...
+
+
+Note that floats are returned as xsd:decimal values:
+
+  >>> print http(r"""
+  ... POST /test_folder_1_ HTTP/1.0
+  ... Authorization: Basic %s:%s
+  ... Content-Length: 102
+  ... Content-Type: text/xml
+  ... SOAPAction: /
+  ...
+  ... <?xml version="1.0"?>
+  ... <SOAP-ENV:Envelope
+  ...  SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"
+  ...  xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/"
+  ...  xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"
+  ...  xmlns:xsd="http://www.w3.org/2001/XMLSchema"
+  ...  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
+  ...  <SOAP-ENV:Body>
+  ...    <m:echoFloat xmlns:m="http://www.soapware.org/">
+  ...      <arg1 xsi:type="xsd:float">42.2</arg1>
+  ...    </m:echoFloat>
+  ...  </SOAP-ENV:Body>
+  ... </SOAP-ENV:Envelope>
+  ... """ % (user_name, user_password))
+  HTTP/1.0 200 OK
+  Content-Length: ...
+  Content-Type: text/xml
+  <BLANKLINE>
+  ...xsi:type="xsd:float">42.200000</...
+
+
+Even if they're in float arrays:
+
+  >>> print http(r"""
+  ... POST /test_folder_1_ HTTP/1.0
+  ... Authorization: Basic %s:%s
+  ... Content-Length: 102
+  ... Content-Type: text/xml
+  ... SOAPAction: /
+  ...
+  ... <?xml version="1.0"?>
+  ... <SOAP-ENV:Envelope
+  ...  SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"
+  ...  xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/"
+  ...  xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"
+  ...  xmlns:xsd="http://www.w3.org/2001/XMLSchema"
+  ...  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
+  ...  <SOAP-ENV:Body>
+  ...    <m:echoFloatArray xmlns:m="http://www.soapware.org/">
+  ...    <param SOAP-ENC:arrayType="xsd:ur-type[4]" xsi:type="SOAP-ENC:Array">
+  ...    <item xsi:type="xsd:float">1.1</item>
+  ...    <item xsi:type="xsd:float">2.2</item>
+  ...    <item xsi:type="xsd:float">3.3</item>
+  ...    <item xsi:type="xsd:float">4.4</item>
+  ...    </param>
+  ...    </m:echoFloatArray>
+  ...  </SOAP-ENV:Body>
+  ... </SOAP-ENV:Envelope>
+  ... """ % (user_name, user_password))
+  HTTP/1.0 200 OK
+  Content-Length: ...
+  Content-Type: text/xml
+  <BLANKLINE>
+  ...xsi:type="xsd:float">1.100000</...
+  ...xsi:type="xsd:float">2.200000</...
+  ...xsi:type="xsd:float">3.300000</...
+  ...xsi:type="xsd:float">4.400000</...
+
+
+  >>> result = http(r"""
+  ... POST /test_folder_1_ HTTP/1.0
+  ... Authorization: Basic %s:%s
+  ... Content-Length: 102
+  ... Content-Type: text/xml
+  ... SOAPAction: /
+  ...
+  ... <?xml version="1.0"?>
+  ... <SOAP-ENV:Envelope
+  ...  SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"
+  ...  xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/"
+  ...  xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"
+  ...  xmlns:xsd="http://www.w3.org/2001/XMLSchema"
+  ...  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
+  ...  <SOAP-ENV:Body>
+  ...    <m:echoStruct xmlns:m="http://www.soapware.org/">
+  ...      <param>
+  ...      <first xsi:type="xsd:string">first 1</first>
+  ...      <last xsi:type="xsd:string">last 1</last>
+  ...      </param>
+  ...    </m:echoStruct>
+  ...  </SOAP-ENV:Body>
+  ... </SOAP-ENV:Envelope>
+  ... """ % (user_name, user_password))
+
+  >>> result = str(result)
+  >>> assert(result.find('first 1') > -1)
+  >>> assert(result.find('last 1') > -1)
+
+
+Note that arrays of structs (at least per the interop suite) do not
+seem to work:
+
+  >>> print http(r"""
+  ... POST /test_folder_1_ HTTP/1.0
+  ... Authorization: Basic %s:%s
+  ... Content-Length: 102
+  ... Content-Type: text/xml
+  ... SOAPAction: /
+  ...
+  ... <?xml version="1.0"?>
+  ... <SOAP-ENV:Envelope
+  ...  SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"
+  ...  xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/"
+  ...  xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"
+  ...  xmlns:xsd="http://www.w3.org/2001/XMLSchema"
+  ...  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+  ...  xmlns:so="http://soapinterop.org/">
+  ...  <SOAP-ENV:Body>
+  ...    <m:echoStructArray xmlns:m="http://www.soapware.org/xsd">
+  ...    <inputArray SOAP-ENC:arrayType="so:SOAPStruct[2]"
+  ...                xsi:type="SOAP-ENC:Array">
+  ...      <item xsi:type="so:SOAPStruct">
+  ...      <varString xsi:type="xsd:string">str 1</varString>
+  ...      <varInt xsi:type="xsd:int">1</varInt>
+  ...      </item>
+  ...      <item xsi:type="so:SOAPStruct">
+  ...      <varString xsi:type="xsd:string">str 2</varString>
+  ...      <varInt xsi:type="xsd:int">2</varInt>
+  ...      </item>
+  ...    </inputArray>
+  ...    </m:echoStructArray>
+  ...  </SOAP-ENV:Body>
+  ... </SOAP-ENV:Envelope>
+  ... """ % (user_name, user_password), handle_errors=True)
+  HTTP/1.0 500 Internal Server Error
+  Content-Length: ...
+  Content-Type: text/xml
+  <BLANKLINE>
+  <SOAP-ENV:Envelope ...
+  ...
+  >>> print http(r"""
+  ... POST /test_folder_1_ HTTP/1.0
+  ... Authorization: Basic %s:%s
+  ... Content-Length: 102
+  ... Content-Type: text/xml
+  ... SOAPAction: /
+  ...
+  ... <?xml version="1.0"?>
+  ... <SOAP-ENV:Envelope
+  ...  SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"
+  ...  xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/"
+  ...  xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"
+  ...  xmlns:xsd="http://www.w3.org/2001/XMLSchema"
+  ...  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
+  ...  <SOAP-ENV:Body>
+  ...    <m:echoVoid xmlns:m="http://www.soapware.org/">
+  ...    </m:echoVoid>
+  ...  </SOAP-ENV:Body>
+  ... </SOAP-ENV:Envelope>
+  ... """ % (user_name, user_password))
+  HTTP/1.0 200 OK
+  Content-Length: ...
+  Content-Type: text/xml
+  <BLANKLINE>
+  ...echoVoidResponse...
+
+
+  >>> print http(r"""
+  ... POST /test_folder_1_ HTTP/1.0
+  ... Authorization: Basic %s:%s
+  ... Content-Length: 102
+  ... Content-Type: text/xml
+  ... SOAPAction: /
+  ...
+  ... <?xml version="1.0"?>
+  ... <SOAP-ENV:Envelope
+  ...  SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"
+  ...  xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/"
+  ...  xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"
+  ...  xmlns:xsd="http://www.w3.org/2001/XMLSchema"
+  ...  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
+  ...  <SOAP-ENV:Body>
+  ...    <m:echoBase64 xmlns:m="http://www.soapware.org/">
+  ...      <arg1 xsi:type="SOAP-ENC:base64">AAECAwQF</arg1>
+  ...    </m:echoBase64>
+  ...  </SOAP-ENV:Body>
+  ... </SOAP-ENV:Envelope>
+  ... """ % (user_name, user_password))
+  HTTP/1.0 200 OK
+  Content-Length: ...
+  Content-Type: text/xml...
+  <BLANKLINE>
+  ...AAECAwQF...
+
+
+Datetimes appear to work:
+
+  >>> print http(r"""
+  ... POST /test_folder_1_ HTTP/1.0
+  ... Authorization: Basic %s:%s
+  ... Content-Length: 102
+  ... Content-Type: text/xml
+  ... SOAPAction: /
+  ...
+  ... <?xml version="1.0"?>
+  ... <SOAP-ENV:Envelope
+  ...  SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"
+  ...  xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/"
+  ...  xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"
+  ...  xmlns:xsd="http://www.w3.org/2001/XMLSchema"
+  ...  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
+  ...  <SOAP-ENV:Body>
+  ...    <m:echoDate xmlns:m="http://www.soapware.org/">
+  ...      <arg1 xsi:type="xsd:dateTime">1970-11-27T11:34:56.000Z</arg1>
+  ...    </m:echoDate>
+  ...  </SOAP-ENV:Body>
+  ... </SOAP-ENV:Envelope>
+  ... """ % (user_name, user_password))
+  HTTP/1.0 200 OK
+  Content-Length: ...
+  Content-Type: text/xml...
+  <BLANKLINE>
+  ...1970-11-27T10:34:56...
+
+  >>> print http(r"""
+  ... POST /test_folder_1_ HTTP/1.0
+  ... Authorization: Basic %s:%s
+  ... Content-Length: 102
+  ... Content-Type: text/xml
+  ... SOAPAction: /
+  ...
+  ... <?xml version="1.0"?>
+  ... <SOAP-ENV:Envelope
+  ...  SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"
+  ...  xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/"
+  ...  xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"
+  ...  xmlns:xsd="http://www.w3.org/2001/XMLSchema"
+  ...  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
+  ...  <SOAP-ENV:Body>
+  ...    <m:echoDecimal xmlns:m="http://www.soapware.org/">
+  ...      <arg1 xsi:type="xsd:float">123456789.0123</arg1>
+  ...    </m:echoDecimal>
+  ...  </SOAP-ENV:Body>
+  ... </SOAP-ENV:Envelope>
+  ... """ % (user_name, user_password))
+  HTTP/1.0 200 OK
+  Content-Length: ...
+  Content-Type: text/xml...
+  <BLANKLINE>
+  ...123456789.0123...
+
+
+  >>> print http(r"""
+  ... POST /test_folder_1_ HTTP/1.0
+  ... Authorization: Basic %s:%s
+  ... Content-Length: 102
+  ... Content-Type: text/xml
+  ... SOAPAction: /
+  ...
+  ... <?xml version="1.0"?>
+  ... <SOAP-ENV:Envelope
+  ...  SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"
+  ...  xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/"
+  ...  xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"
+  ...  xmlns:xsd="http://www.w3.org/2001/XMLSchema"
+  ...  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
+  ...  <SOAP-ENV:Body>
+  ...    <m:echoBoolean xmlns:m="http://www.soapware.org/">
+  ...      <arg1 xsi:type="xsd:boolean">1</arg1>
+  ...    </m:echoBoolean>
+  ...  </SOAP-ENV:Body>
+  ... </SOAP-ENV:Envelope>
+  ... """ % (user_name, user_password))
+  HTTP/1.0 200 OK
+  Content-Length: ...
+  Content-Type: text/xml...
+  <BLANKLINE>
+  ...1...
+
+
+
+Complex Types
+-------------
+
+For ZSI to successfully marshal complex values (instances of classes),
+you must define a typecode that describes the object (see the ZSI docs
+for details on defining typecodes). Once the typecode is defined, it must
+be accessible through an instance via the attribute name 'typecode' to
+be automatically marshalled.
+
+
+Faults
+------
+
+If you need to raise an error, you can either raise an exception as usual
+or (if you need more control over fault info) return a `ZSI.Fault` object
+directly. Either case causes a fault response to be returned:
+
+  >>> print http(r"""
+  ... POST /test_folder_1_ HTTP/1.0
+  ... Authorization: Basic %s:%s
+  ... Content-Length: 104
+  ... Content-Type: text/xml
+  ... SOAPAction: /
+  ...
+  ... <?xml version="1.0"?>
+  ... <SOAP-ENV:Envelope
+  ...  SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"
+  ...  xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/"
+  ...  xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"
+  ...  xmlns:xsd="http://www.w3.org/2001/XMLSchema"
+  ...  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
+  ...  <SOAP-ENV:Body>
+  ...    <m:echoInteger xmlns:m="http://www.soapware.org/">
+  ...      <arg1 xsi:type="xsd:int">hello</arg1>
+  ...    </m:echoInteger>
+  ...  </SOAP-ENV:Body>
+  ... </SOAP-ENV:Envelope>
+  ... """ % (user_name, user_password), handle_errors=True)
+  HTTP/1.0 500 Internal Server Error
+  Content-Length: ...
+  Content-Type: text/xml
+  <BLANKLINE>
+  <SOAP-ENV:Envelope ...
+  Processing Failure
+  <BLANKLINE>
+  Unparseable integer
+  ...
+
+
+Complex Types
+-------------
+
+  >>> print http(r"""
+  ... POST /test_folder_1_ HTTP/1.0
+  ... Authorization: Basic %s:%s
+  ... Content-Length: 104
+  ... Content-Type: text/xml
+  ... SOAPAction: /
+  ...
+  ... <SOAP-ENV:Envelope
+  ...  xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/"
+  ...  xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"
+  ...  xmlns:ZSI="http://www.zolera.com/schemas/ZSI/"
+  ...  xmlns:xsd="http://www.w3.org/2001/XMLSchema"
+  ...  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
+  ... <SOAP-ENV:Header></SOAP-ENV:Header>
+  ... <SOAP-ENV:Body xmlns:ns1="urn:ws-xwebservices-com:XWebEmailValidation:EmailValidation:v2:Messages">
+  ...   <ns1:ValidateEmailRequest>
+  ...     <ns1:Email>jfroche at affinitic.be</ns1:Email>
+  ...   </ns1:ValidateEmailRequest>
+  ... </SOAP-ENV:Body>
+  ... </SOAP-ENV:Envelope>""" % (user_name, user_password))
+  HTTP/1.0 200 OK
+  Content-Length: ...
+  Content-Type: text/xml
+  <BLANKLINE>
+  ...jfroche at affinitic.be is OK...


Property changes on: z3c.soap/trunk/z3c/soap/README.txt
___________________________________________________________________
Added: svn:eol-style
   + native

Added: z3c.soap/trunk/z3c/soap/__init__.py
===================================================================
--- z3c.soap/trunk/z3c/soap/__init__.py	                        (rev 0)
+++ z3c.soap/trunk/z3c/soap/__init__.py	2008-11-13 12:18:51 UTC (rev 92902)
@@ -0,0 +1,4 @@
+#NOCHECK
+# This is a Python package.
+import HTTPRequest
+from patch import *


Property changes on: z3c.soap/trunk/z3c/soap/__init__.py
___________________________________________________________________
Added: svn:keywords
   + Id

Added: z3c.soap/trunk/z3c/soap/ftesting.zcml
===================================================================
--- z3c.soap/trunk/z3c/soap/ftesting.zcml	                        (rev 0)
+++ z3c.soap/trunk/z3c/soap/ftesting.zcml	2008-11-13 12:18:51 UTC (rev 92902)
@@ -0,0 +1,11 @@
+<configure xmlns="http://namespaces.zope.org/zope"
+           xmlns:browser="http://namespaces.zope.org/browser"
+           xmlns:meta="http://namespaces.zope.org/meta"
+           i18n_domain="z3c.soap">
+
+     <include package="Products.Five"/>
+
+     <include package="z3c.soap" file="meta.zcml" />
+
+</configure>
+

Added: z3c.soap/trunk/z3c/soap/ftests.py
===================================================================
--- z3c.soap/trunk/z3c/soap/ftests.py	                        (rev 0)
+++ z3c.soap/trunk/z3c/soap/ftests.py	2008-11-13 12:18:51 UTC (rev 92902)
@@ -0,0 +1,108 @@
+##############################################################################
+#
+# Copyright (c) 2005 Zope Corporation and Contributors.
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.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.
+#
+##############################################################################
+"""
+Functional tests for SOAP.
+
+$Id$
+"""
+
+import sys
+import os
+import zope.interface
+from zope.testing import doctest
+from zope.app.folder.folder import IFolder
+from zope.app.testing.functional import ZCMLLayer
+from zope.app.testing import ztapi
+from z3c.soap.interfaces import ISOAPRequest
+
+
+# Evil hack to make pickling work with classes defined in doc tests
+
+
+class NoCopyDict(dict):
+
+    def copy(self):
+        return self
+
+
+class FakeModule:
+
+    def __init__(self, dict):
+        self.__dict = dict
+
+    def __getattr__(self, name):
+        try:
+            return self.__dict[name]
+        except KeyError:
+            raise AttributeError(name)
+
+
+globs = NoCopyDict()
+name = 'z3c.soap.README'
+
+
+def setUp(test):
+    globs['__name__'] = name
+    sys.modules[name] = FakeModule(globs)
+
+
+def tearDown(test):
+    # clean up the views we registered:
+
+    # we use the fact that registering None unregisters whatever is
+    # registered. We can't use an unregistration call because that
+    # requires the object that was registered and we don't have that handy.
+    # (OK, we could get it if we want. Maybe later.)
+
+    ztapi.provideView(IFolder,
+                        ISOAPRequest,
+                        zope.interface,
+                        'contents',
+                        None,
+                        )
+    ztapi.provideView(IFolder,
+                        ISOAPRequest,
+                        zope.interface,
+                        'contents',
+                        None,
+                        )
+
+    globs.clear()
+    del sys.modules[name]
+
+
+dir = os.path.abspath(os.path.dirname(__file__))
+filename = os.path.join(dir, 'ftesting.zcml')
+
+z3c_soap_functional_layer = ZCMLLayer(filename,
+                                          __name__,
+                                          'z3c.soap_functional_layer')
+
+
+def test_suite():
+    #from zope.app.testing.functional import FunctionalDocFileSuite
+    from Testing.ZopeTestCase import FunctionalDocFileSuite
+    ftest = FunctionalDocFileSuite(
+        'README.txt',
+        optionflags=doctest.ELLIPSIS|
+                    doctest.REPORT_NDIFF|
+                    doctest.REPORT_ONLY_FIRST_FAILURE|
+                    doctest.NORMALIZE_WHITESPACE,
+        setUp=setUp, tearDown=tearDown, globs=globs)
+    ftest.layer = z3c_soap_functional_layer
+    return ftest
+
+if __name__ == '__main__':
+    import unittest
+    unittest.main(defaultTest='test_suite')


Property changes on: z3c.soap/trunk/z3c/soap/ftests.py
___________________________________________________________________
Added: svn:keywords
   + Id

Added: z3c.soap/trunk/z3c/soap/interfaces.py
===================================================================
--- z3c.soap/trunk/z3c/soap/interfaces.py	                        (rev 0)
+++ z3c.soap/trunk/z3c/soap/interfaces.py	2008-11-13 12:18:51 UTC (rev 92902)
@@ -0,0 +1,59 @@
+##############################################################################
+#
+# Copyright (c) 2005 Zope Corporation and Contributors.
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.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.
+#
+##############################################################################
+"""
+SOAP interfaces.
+
+$Id$
+"""
+
+from zope.publisher.interfaces.http import IHTTPRequest, IHTTPResponse
+from zope.component.interfaces import IView, IPresentation
+from zope.publisher.interfaces import IPublishTraverse
+from zope.publisher.interfaces import IPublication
+from zope.interface import Interface
+
+
+class ISOAPPublisher(IPublishTraverse):
+    """SOAP Publisher"""
+
+
+class ISOAPPublication(IPublication):
+    """Object publication framework."""
+
+    def getDefaultTraversal(request, ob):
+        """Get the default published object for the request."""
+
+
+class ISOAPRequest(IHTTPRequest):
+    """SOAP Request"""
+
+
+class ISOAPResponse(IHTTPResponse):
+    """SOAP Response"""
+
+
+class ISOAPPresentation(IPresentation):
+    """SOAP presentation"""
+
+
+class ISOAPView(ISOAPPresentation, IView):
+    """SOAP View"""
+
+
+class IZSIRequestType(Interface):
+    """Resolver for complex request"""
+
+
+class IZSIResponseType(Interface):
+    """Resolver for complex response"""


Property changes on: z3c.soap/trunk/z3c/soap/interfaces.py
___________________________________________________________________
Added: svn:keywords
   + Id

Added: z3c.soap/trunk/z3c/soap/meta.zcml
===================================================================
--- z3c.soap/trunk/z3c/soap/meta.zcml	                        (rev 0)
+++ z3c.soap/trunk/z3c/soap/meta.zcml	2008-11-13 12:18:51 UTC (rev 92902)
@@ -0,0 +1,11 @@
+<configure 
+    xmlns:meta="http://namespaces.zope.org/meta"
+    xmlns="http://namespaces.zope.org/zope">
+  
+  <meta:directive 
+       namespace="http://namespaces.zope.org/soap"
+       name="view" 
+       schema=".metadirectives.IViewDirective"
+       handler=".metaconfigure.view" />
+
+</configure>

Added: z3c.soap/trunk/z3c/soap/metaconfigure.py
===================================================================
--- z3c.soap/trunk/z3c/soap/metaconfigure.py	                        (rev 0)
+++ z3c.soap/trunk/z3c/soap/metaconfigure.py	2008-11-13 12:18:51 UTC (rev 92902)
@@ -0,0 +1,173 @@
+##############################################################################
+#
+# Copyright (c) 2005 Zope Corporation and Contributors.
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.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.
+#
+##############################################################################
+"""
+SOAP configuration code
+
+$Id$
+"""
+
+from zope.interface import Interface
+from zope.security.checker import CheckerPublic #, Checker
+#from zope.location import Location
+from zope.component.interface import provideInterface
+from Products.Five.security import protectClass, protectName
+from zope.app.publisher.browser.viewmeta import _handle_for
+
+# XXX handler is non-public.  Should call directives instead
+from zope.app.component.metaconfigure import handler
+
+from inspect import ismethod
+from interfaces import ISOAPRequest
+from Globals import InitializeClass as initializeClass
+from Products.Five.security import getSecurityInfo
+from Products.Five.metaclass import makeClass
+
+from Products.Five.browser import BrowserView
+from Products.Five.browser.metaconfigure import ViewMixinForAttributes
+from Products.Five.security import CheckerPrivateId
+
+
+def view(_context, for_=None, interface=None, methods=None,
+         class_=None, permission=None, name=None):
+
+    interface = interface or []
+    methods = methods or []
+
+    # If there were special permission settings provided, then use them
+    if permission == 'zope.Public':
+        permission = CheckerPublic
+
+    require = {}
+    for attr_name in methods:
+        require[attr_name] = permission
+
+    if interface:
+        for iface in interface:
+            for field_name in iface:
+                require[field_name] = permission
+            _context.action(
+                discriminator = None,
+                callable = provideInterface,
+                args = ('', for_))
+
+    cdict = getSecurityInfo(class_)
+
+    if name:
+        # Register a single view
+#        if permission:
+#            checker = Checker(require)
+#
+#            def proxyView(context, request, class_=class_, checker=checker):
+#                view = class_(context, request)
+#                # We need this in case the resource gets unwrapped and
+#                # needs to be rewrapped
+#                view.__Security_checker__ = checker
+#                return view
+#
+#            class_ = proxyView
+        cdict = getSecurityInfo(class_)
+        cdict['__name__'] = name
+        new_class = makeClass(class_.__name__,
+                              (class_, BrowserView), cdict)
+
+        _handle_for(_context, for_)
+        # Register the new view.
+        _context.action(
+            discriminator = ('view', (for_, ), name, ISOAPRequest),
+            callable = handler,
+            args = ('registerAdapter',
+                    new_class, (for_, ISOAPRequest),
+                    Interface, name,
+                    _context.info)
+            )
+        _context.action(
+            discriminator = ('five:protectClass', new_class),
+            callable = protectClass,
+            args = (new_class, permission))
+
+        for name in require:
+            _context.action(
+                discriminator = ('five:protectName', new_class, name),
+                callable = protectName,
+                args = (new_class, name, permission))
+
+        #else its private:
+        allowed = require
+        private_attrs = [name for name in dir(new_class)
+                         if (not name.startswith('_')) and
+                            (name not in allowed) and
+                            ismethod(getattr(new_class, name))]
+        for attr in private_attrs:
+            _context.action(
+                discriminator = ('five:protectName', new_class, attr),
+                callable = protectName,
+                args = (new_class, attr, CheckerPrivateId))
+
+    else:
+#        if permission:
+#            checker = Checker({'__call__': permission})
+#        else:
+        for name in require:
+            # create a new callable class with a security checker; mix
+            # in zope.app.location.Location so that the view inherits
+            # a security context
+            cdict.update({'__page_attribute__': name,
+                          '__name__': name})
+            new_class = makeClass(class_.__name__,
+                                  (class_, ViewMixinForAttributes),
+                                  cdict)
+
+            # in case the attribute does not provide a docstring,
+            # ZPublisher refuses to publish it.  So, as a workaround,
+            # we provide a stub docstring
+            func = getattr(new_class, name)
+            if not func.__doc__:
+                # cannot test for MethodType/UnboundMethod here
+                # because of ExtensionClass
+                if hasattr(func, 'im_func'):
+                    # you can only set a docstring on functions, not
+                    # on method objects
+                    func = func.im_func
+                func.__doc__ = "Stub docstring to make ZPublisher work"
+
+            _context.action(
+                discriminator = ('view', (for_, ), name, ISOAPRequest),
+                callable = handler,
+                args = ('registerAdapter',
+                        new_class,
+                        (for_, ISOAPRequest), Interface, name,
+                        _context.info))
+
+            _context.action(
+                discriminator = ('five:protectClass', new_class),
+                callable = protectClass,
+                args = (new_class, permission))
+
+            _context.action(
+                discriminator = ('five:protectName', new_class, name),
+                callable = protectName,
+                args = (new_class, name, permission))
+
+            _context.action(
+                discriminator = ('five:initialize:class', new_class),
+                callable = initializeClass,
+                args = (new_class, )
+                )
+
+    # Register the used interfaces with the interface service
+    if for_ is not None:
+        _context.action(
+            discriminator = None,
+            callable = provideInterface,
+            args = ('', for_))


Property changes on: z3c.soap/trunk/z3c/soap/metaconfigure.py
___________________________________________________________________
Added: svn:keywords
   + Id

Added: z3c.soap/trunk/z3c/soap/metadirectives.py
===================================================================
--- z3c.soap/trunk/z3c/soap/metadirectives.py	                        (rev 0)
+++ z3c.soap/trunk/z3c/soap/metadirectives.py	2008-11-13 12:18:51 UTC (rev 92902)
@@ -0,0 +1,84 @@
+##############################################################################
+#
+# Copyright (c) 2005 Zope Corporation and Contributors.
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.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.
+#
+##############################################################################
+"""
+SOAP ZCML Namespace Schemas
+
+$Id$
+"""
+
+import zope.configuration.fields
+from zope.security.zcml import Permission
+from zope.interface import Interface
+from zope.schema import TextLine
+
+
+class IViewDirective(Interface):
+    """View Directive for SOAP methods."""
+
+    for_ = zope.configuration.fields.GlobalObject(
+        title=u"Published Object Type",
+        description=u"""The types of objects to be published via SOAP
+
+        This can be expressed with either a class or an interface
+        """,
+        required=True)
+
+    interface = zope.configuration.fields.Tokens(
+        title=u"Interface to be published.",
+        required=False,
+        value_type=zope.configuration.fields.GlobalInterface())
+
+    methods = zope.configuration.fields.Tokens(
+        title=u"Methods (or attributes) to be published",
+        required=False,
+        value_type=zope.configuration.fields.PythonIdentifier())
+
+    class_ = zope.configuration.fields.GlobalObject(
+        title=u"Class",
+        description=u"A class that provides attributes used by the view.",
+        required=False)
+
+    permission = Permission(
+        title=u"Permission",
+        description=u"""The permission needed to use the view.
+
+        If this option is used and a name is given for the view, then
+        the names defined by the given methods or interfaces will be
+        under the given permission.
+
+        If a name is not given for the view, then, this option is
+        required and the the given permission is required to call the
+        individual views defined by the given interface and methods.
+
+        (See the name attribute.)
+
+        If no permission is given, then permissions should be declared
+        for the view using other means, such as the class directive.
+        """,
+        required=False, )
+
+    name = TextLine(
+        title=u"The name of the view.",
+        description=u"""
+        If a name is given, then rpc methods are accessed by
+        traversing the name and then accessing the methods.  In this
+        case, the class should implement
+        zope.pubisher.interfaces.IPublishTraverse.
+
+        If no name is provided, then the names given by the attributes
+        and interfaces are published directly as callable views.
+
+        """,
+        required=False,
+        )


Property changes on: z3c.soap/trunk/z3c/soap/metadirectives.py
___________________________________________________________________
Added: svn:keywords
   + Id

Added: z3c.soap/trunk/z3c/soap/patch.py
===================================================================
--- z3c.soap/trunk/z3c/soap/patch.py	                        (rev 0)
+++ z3c.soap/trunk/z3c/soap/patch.py	2008-11-13 12:18:51 UTC (rev 92902)
@@ -0,0 +1,144 @@
+# -*- coding: utf-8 -*-
+"""
+z3c.soap
+
+Licensed under the GPL license, see LICENCE.txt for more details.
+Copyright by Affinitic sprl
+
+$Id$
+"""
+import sys
+from zExceptions import Redirect
+from ZPublisher.mapply import mapply
+from ZPublisher.Publish import (call_object, missing_name, dont_publish_class,
+                                get_module_info, Retry)
+from zope.publisher.browser import setDefaultSkin
+from zope.security.management import newInteraction, endInteraction
+from z3c.soap.interfaces import ISOAPRequest
+from z3c.soap.soap import SOAPResponse
+
+
+def publish(request, module_name, after_list, debug=0,
+            call_object=call_object,
+            missing_name=missing_name,
+            dont_publish_class=dont_publish_class,
+            mapply=mapply,
+            ):
+
+    (bobo_before, bobo_after, object, realm, debug_mode, err_hook,
+     validated_hook, transactions_manager)= get_module_info(module_name)
+
+    parents=None
+    response=None
+
+    try:
+        # TODO pass request here once BaseRequest implements IParticipation
+        newInteraction()
+
+        request.processInputs()
+
+        request_get=request.get
+        response=request.response
+
+        # First check for "cancel" redirect:
+        if request_get('SUBMIT', '').strip().lower()=='cancel':
+            cancel=request_get('CANCEL_ACTION', '')
+            if cancel:
+                raise Redirect(cancel)
+
+        after_list[0]=bobo_after
+        if debug_mode:
+            response.debug_mode=debug_mode
+        if realm and not request.get('REMOTE_USER', None):
+            response.realm=realm
+
+        if bobo_before is not None:
+            bobo_before()
+
+        # Get the path list.
+        # According to RFC1738 a trailing space in the path is valid.
+        path=request_get('PATH_INFO')
+
+        request['PARENTS']=parents=[object]
+
+        if transactions_manager:
+            transactions_manager.begin()
+
+        object=request.traverse(path, validated_hook=validated_hook)
+
+        if transactions_manager:
+            transactions_manager.recordMetaData(object, request)
+
+        result=mapply(object, request.args, request,
+                      call_object, 1,
+                      missing_name,
+                      dont_publish_class,
+                      request, bind=1)
+
+        if result is not response:
+            response.setBody(result)
+
+        if transactions_manager:
+            transactions_manager.commit()
+        endInteraction()
+
+        return response
+    except:
+        # DM: provide nicer error message for FTP
+        sm = None
+        if response is not None:
+            sm = getattr(response, "setMessage", None)
+        if sm is not None:
+            from asyncore import compact_traceback
+            cl, val= sys.exc_info()[:2]
+            sm('%s: %s %s' % (
+                getattr(cl, '__name__', cl), val,
+                debug_mode and compact_traceback()[-1] or ''))
+        if ISOAPRequest.providedBy(request):
+            if transactions_manager:
+                transactions_manager.abort()
+            endInteraction()
+            if response is None:
+                response = SOAPResponse(request.response)
+            response.exception()
+            return response
+        if err_hook is not None:
+            if parents:
+                parents=parents[0]
+            try:
+                try:
+                    return err_hook(parents, request,
+                                    sys.exc_info()[0],
+                                    sys.exc_info()[1],
+                                    sys.exc_info()[2],
+                                    )
+                except Retry:
+                    if not request.supports_retry():
+                        return err_hook(parents, request,
+                                        sys.exc_info()[0],
+                                        sys.exc_info()[1],
+                                        sys.exc_info()[2],
+                                        )
+            finally:
+                if transactions_manager:
+                    transactions_manager.abort()
+                endInteraction()
+
+            # Only reachable if Retry is raised and request supports retry.
+            newrequest=request.retry()
+            request.close()  # Free resources held by the request.
+            # Set the default layer/skin on the newly generated request
+            setDefaultSkin(newrequest)
+            try:
+                return publish(newrequest, module_name, after_list, debug)
+            finally:
+                newrequest.close()
+
+        else:
+            if transactions_manager:
+                transactions_manager.abort()
+            endInteraction()
+            raise
+
+import ZPublisher.Publish
+ZPublisher.Publish.publish = publish


Property changes on: z3c.soap/trunk/z3c/soap/patch.py
___________________________________________________________________
Added: svn:keywords
   + Id

Added: z3c.soap/trunk/z3c/soap/publisher.py
===================================================================
--- z3c.soap/trunk/z3c/soap/publisher.py	                        (rev 0)
+++ z3c.soap/trunk/z3c/soap/publisher.py	2008-11-13 12:18:51 UTC (rev 92902)
@@ -0,0 +1,186 @@
+##############################################################################
+#
+# Copyright (c) 2005 Zope Corporation and Contributors.
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.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.
+#
+##############################################################################
+"""
+SOAP Publisher.
+
+$Id$
+"""
+
+import ZSI
+from zope.app.publication.interfaces import ISOAPRequestFactory
+from zope.publisher.http import HTTPRequest, HTTPResponse
+from z3c.soap.interfaces import ISOAPRequest, ISOAPResponse
+from ZSI import TC, ParsedSoap, ParseException
+from ZSI import SoapWriter, Fault
+from zope.security.proxy import isinstance
+from zope.security.interfaces import IUnauthorized
+from zope.publisher.xmlrpc import premarshal
+from zope.interface import implements
+from StringIO import StringIO
+import traceback
+
+
+class SOAPRequestFactory(object):
+    """
+    This class implements a SOAP request factory that is registered
+    for zope.app.publication.interfaces.ISOAPRequestFactory as a
+    utility. This lets the hook in the z3 publisher delegate to us
+    for SOAP requests.
+    """
+    implements(ISOAPRequestFactory)
+
+    def __call__(self, input, env):
+        return SOAPRequest(input, env)
+
+factory = SOAPRequestFactory()
+
+
+class SOAPRequest(HTTPRequest):
+
+    implements(ISOAPRequest)
+
+##     __slots__ = (
+##         '_target',
+##         '_root',
+##         )
+
+    _target = ''
+    _root = None
+    _args = ()
+
+    def _getPositionalArguments(self):
+        return self._args
+
+    def _createResponse(self):
+        """Create a specific SOAP response object."""
+        return SOAPResponse()
+
+    def _setError(self, error):
+        self._getResponse()._error = error
+
+    def processInputs(self):
+        try:
+            input = self._body_instream.read()
+            parsed = ParsedSoap(input)
+
+            # We do not currently handle actors or mustUnderstand elements.
+            actors = parsed.WhatActorsArePresent()
+            if len(actors):
+                self._setError(ZSI.FaultFromActor(actors[0]))
+                return
+
+            must = parsed.WhatMustIUnderstand()
+            if len(must):
+                uri, localname = must[0]
+                self._setError(ZSI.FaultFromNotUnderstood(uri, localname))
+                return
+
+        except ParseException, e:
+            self._setError(ZSI.FaultFromZSIException(e))
+            return
+
+        except Exception, e:
+            self._setError(ZSI.FaultFromException(e, 1))
+            return
+
+        # Parse the SOAP input.
+        try:
+            docstyle = 0 # cant really tell...
+            resolver = None # XXX
+            root = self._root = parsed.body_root
+            target = self._target = root.localName
+
+            self.setPathSuffix(target.split('.'))
+
+            if docstyle:
+                self._args = (root)
+            else:
+                data = ZSI._child_elements(root)
+                if len(data) == 0:
+                    self._args = ()
+                else:
+                    try:
+                        try:
+                            type = data[0].localName
+                            tc = getattr(resolver, type).typecode
+                        except Exception, e:
+                            tc = TC.Any()
+                        self._args = [tc.parse(e, parsed) for e in data]
+                        self._args = tuple(self._args)
+                    except ZSI.EvaluateException, e:
+                        self._error = ZSI.FaultFromZSIException(e)
+                    return
+
+        except Exception, e:
+            self._setError(ZSI.FaultFromException(e, 0))
+
+
+class SOAPResponse(HTTPResponse):
+
+    implements(ISOAPResponse)
+
+    _error = None
+
+    def setBody(self, body):
+        """Sets the body of the response"""
+        # A SOAP view can return a Fault directly to indicate an error.
+        if isinstance(body, Fault):
+            self._error = body
+
+        if not self._error:
+            try:
+                target = self._request._target
+                body = premarshal(body)
+                output = StringIO()
+                result = body
+
+                if hasattr(result, 'typecode'):
+                    tc = result.typecode
+                else:
+                    tc = TC.Any(aslist=1, pname=target + 'Response')
+                    result = [result]
+
+                SoapWriter(output).serialize(result, tc)
+                output.seek(0)
+
+                if not self._status_set:
+                    self.setStatus(200)
+                self.setHeader('content-type', 'text/xml')
+                self._body = output.read()
+                self._updateContentLength()
+                return
+
+            except Exception, e:
+                self._error = ZSI.FaultFromException(e, 0)
+
+        # Error occurred in input, during parsing or during processing.
+        self.setStatus(500)
+        self.setHeader('content-type', 'text/xml')
+        self.setResult(self._error.AsSOAP())
+        #self._updateContentLength()
+
+    def handleException(self, exc_info):
+        """Handle exceptions that occur during processing."""
+        type, value = exc_info[:2]
+        content = "".join(traceback.format_tb(exc_info[-1]))
+        if IUnauthorized.providedBy(value):
+            self.setStatus(401)
+            self.setBody("")
+            #XXXself._body = ""
+            #self._updateContentLength()
+            return
+        if not isinstance(value, Fault):
+            value = ZSI.FaultFromException(u"%s : %s" % (value, content), 0)
+        self.setStatus(500)
+        self.setBody(value)


Property changes on: z3c.soap/trunk/z3c/soap/publisher.py
___________________________________________________________________
Added: svn:keywords
   + Id

Added: z3c.soap/trunk/z3c/soap/soap.py
===================================================================
--- z3c.soap/trunk/z3c/soap/soap.py	                        (rev 0)
+++ z3c.soap/trunk/z3c/soap/soap.py	2008-11-13 12:18:51 UTC (rev 92902)
@@ -0,0 +1,165 @@
+"""SOAP support module
+
+Based on the XML-RPC Zope support module written by Eric Kidd at UserLand
+software, with much help from Jim Fulton at DC.
+
+This code hooks Zope up to Fredrik Lundh's Python SOAP library.
+"""
+
+import sys
+import types
+from string import replace
+from zExceptions import Unauthorized
+from zope.publisher.xmlrpc import premarshal
+from ZSI import TC, ParsedSoap
+from ZSI import SoapWriter, Fault
+from zope.component import queryUtility
+from z3c.soap.interfaces import IZSIRequestType, IZSIResponseType
+import ZSI
+import logging
+import traceback
+from zope.interface import implements
+from z3c.soap.interfaces import ISOAPResponse
+
+
+class SOAPParser(object):
+
+    def __init__(self, data):
+        self.parsed = ParsedSoap(data)
+        self.root = self.parsed.body_root
+        self.target = self.root.localName
+        self.method = replace(self.target, '.', '/')
+
+    def parse(self):
+        data = ZSI._child_elements(self.root)
+        if len(data) == 0:
+            params = ()
+        else:
+            resolver = queryUtility(IZSIRequestType, name=self.target)
+            if resolver and hasattr(resolver, 'typecode'):
+                tc = resolver.typecode
+                params = [resolver.typecode.parse(self.root, self.parsed)]
+
+                resolver = queryUtility(IZSIResponseType, name=self.target)
+                params.append(resolver)
+            else:
+                tc = TC.Any()
+                params = [tc.parse(e, self.parsed) for e in data]
+            params = tuple(params)
+        return params
+
+
+def parse_input(data):
+    parser = SOAPParser(data)
+    return parser.parse()
+
+
+class SOAPResponse:
+    """Customized Response that handles SOAP-specific details.
+
+    We override setBody to marhsall Python objects into SOAP. We
+    also override exception to convert errors to SOAP faults.
+
+    If these methods stop getting called, make sure that ZPublisher is
+    using the soap.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(ISOAPResponse)
+    _contentType = 'text/xml'
+
+    _soap11 = None
+    _soap12 = None
+    # Because we can't predict what kind of thing we're customizing,
+    # we have to use delegation, rather than inheritence to do the
+    # customization.
+
+    def __init__(self, real):
+        self.__dict__['_real']=real
+
+    def __getattr__(self, name):
+        return getattr(self._real, name)
+
+    def __setattr__(self, name, v):
+        return setattr(self._real, name, v)
+
+    def __delattr__(self, name):
+        return delattr(self._real, name)
+
+    def setBody(self, body, title='', is_error=0, bogus_str_search=None):
+        if isinstance(body, Fault):
+            # Convert Fault object to SOAP response.
+            #body = buildSOAP(args=body, config=Config)
+            body = ZSI.FaultFromException(body, 0)
+            body = body.AsSOAP()
+        else:
+            # Marshall our body as an SOAP response. Strings will be sent
+            # strings, integers as integers, etc. We do *not* convert
+            # everything to a string first.
+            try:
+                target = self._method
+                body = premarshal(body)
+                #output = StringIO()
+                result = body
+                if hasattr(result, 'typecode'):
+                    tc = result.typecode
+                else:
+                    tc = TC.Any(aslist=1, pname=target + 'Response')
+                    result = [result]
+                sw = SoapWriter(nsdict={}, header=True, outputclass=None,
+                        encodingStyle=None)
+                body = sw.serialize(result, tc).body
+            except:
+                self.exception()
+                return
+
+        # Set our body to the message, and fix our MIME type.
+        self._real.setBody(body)
+        self._setHeader()
+        return self
+
+    def exception(self, fatal=0, info=None,
+                  absuri_match=None, tag_search=None):
+        # Fetch our exception info. t is type, v is value and tb is the
+        # traceback object.
+        if type(info) is type(()) and len(info)==3:
+            t, v, tb = info
+        else:
+            t, v, tb = sys.exc_info()
+
+        content = "".join(traceback.format_tb(tb))
+        logger = logging.getLogger('Zope')
+        logger.info('SOAPException: %s' % tb)
+        if t == 'Unauthorized' or t == Unauthorized or (
+           isinstance(t, types.ClassType) and issubclass(t, Unauthorized)):
+            realm=self._real.realm
+            if realm:
+                self._real.setHeader('WWW-Authenticate',
+                                     'basic realm="%s"' % realm, 1)
+                self._real.setStatus(401)
+            return None
+
+        # 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.
+        f=None
+        if not isinstance(v, Fault):
+            f = ZSI.FaultFromException(u"%s : %s" % (v, content), 0)
+        # Do the damage.
+        self.setBody(f)
+        self._real.setStatus(500)
+
+        return tb
+
+    def _setHeader(self):
+        self.setHeader('content-length', len(self._real.body))
+        self._real.setHeader('content-type', self._contentType)
+        if self._soap11:
+            self._real.setHeader('content-type', 'text/xml')
+        if self._soap12:
+            self._real.setHeader('content-type', 'application/soap+xml')
+
+
+response=SOAPResponse


Property changes on: z3c.soap/trunk/z3c/soap/soap.py
___________________________________________________________________
Added: svn:keywords
   + Id

Added: z3c.soap/trunk/z3c/soap/tests/__init__.py
===================================================================
--- z3c.soap/trunk/z3c/soap/tests/__init__.py	                        (rev 0)
+++ z3c.soap/trunk/z3c/soap/tests/__init__.py	2008-11-13 12:18:51 UTC (rev 92902)
@@ -0,0 +1 @@
+# This directory is a Python package.


Property changes on: z3c.soap/trunk/z3c/soap/tests/__init__.py
___________________________________________________________________
Added: svn:keywords
   + Id

Added: z3c.soap/trunk/z3c/soap/tests/mailvalidation.py
===================================================================
--- z3c.soap/trunk/z3c/soap/tests/mailvalidation.py	                        (rev 0)
+++ z3c.soap/trunk/z3c/soap/tests/mailvalidation.py	2008-11-13 12:18:51 UTC (rev 92902)
@@ -0,0 +1,78 @@
+from ZSI import TCcompound, TC
+from ZSI.schema import LocalElementDeclaration, ElementDeclaration
+from ZSI.schema import GED
+
+
+class ns0:
+    targetNamespace = "urn:ws-xwebservices-com:XWebEmailValidation:EmailValidation:v2"
+
+
+class ns1:
+    targetNamespace = "urn:ws-xwebservices-com:XWebEmailValidation:EmailValidation:v2:Messages"
+
+    class ValidateEmailRequest_Dec(TCcompound.ComplexType, ElementDeclaration):
+        literal = "ValidateEmailRequest"
+        schema = "urn:ws-xwebservices-com:XWebEmailValidation:EmailValidation:v2:Messages"
+
+        def __init__(self, **kw):
+            ns = ns1.ValidateEmailRequest_Dec.schema
+            TClist = [TC.String(pname=(ns, "Email"), aname="_Email",
+                                minOccurs=1, maxOccurs=1, nillable=False,
+                                typed=False, encoded=kw.get("encoded"))]
+            kw["pname"] = (u'urn:ws-xwebservices-com:XWebEmailValidation:EmailValidation:v2:Messages', u'ValidateEmailRequest')
+            kw["aname"] = "_ValidateEmailRequest"
+            self.attribute_typecode_dict = {}
+            TCcompound.ComplexType.__init__(self, None, TClist, inorder=0, **kw)
+
+            class Holder:
+                typecode = self
+
+                def __init__(self):
+                    # pyclass
+                    self._Email = None
+                    return
+            Holder.__name__ = "ValidateEmailRequest_Holder"
+            self.pyclass = Holder
+
+
+    class ValidateEmailResponse_Dec(TCcompound.ComplexType, ElementDeclaration):
+        literal = "ValidateEmailResponse"
+        schema = "urn:ws-xwebservices-com:XWebEmailValidation:EmailValidation:v2:Messages"
+
+        def __init__(self, **kw):
+            ns = ns1.ValidateEmailResponse_Dec.schema
+            TClist = [self.__class__.Status_Dec(minOccurs=1, maxOccurs=1,
+                                                nillable=False,
+                                                encoded=kw.get("encoded"))]
+            kw["pname"] = (u'urn:ws-xwebservices-com:XWebEmailValidation:EmailValidation:v2:Messages', u'ValidateEmailResponse')
+            kw["aname"] = "_ValidateEmailResponse"
+            self.attribute_typecode_dict = {}
+            TCcompound.ComplexType.__init__(self, None, TClist, inorder=0, **kw)
+
+            class Holder:
+                typecode = self
+
+                def __init__(self):
+                    # pyclass
+                    self._Status = None
+                    return
+
+            Holder.__name__ = "ValidateEmailResponse_Holder"
+            self.pyclass = Holder
+
+        class Status_Dec(TC.String, LocalElementDeclaration):
+            literal = "Status"
+            schema = "urn:ws-xwebservices-com:XWebEmailValidation:EmailValidation:v2:Messages"
+
+            def __init__(self, **kw):
+                kw["pname"] = "Status"
+                kw["aname"] = "_Status"
+                TC.String.__init__(self, **kw)
+
+                class IHolder(str):
+                    typecode=self
+                self.pyclass = IHolder
+                IHolder.__name__ = "_Status_immutable_holder"
+
+validateEmailIn = GED("urn:ws-xwebservices-com:XWebEmailValidation:EmailValidation:v2:Messages", "ValidateEmailRequest").pyclass
+validateEmailOut = GED("urn:ws-xwebservices-com:XWebEmailValidation:EmailValidation:v2:Messages", "ValidateEmailResponse").pyclass


Property changes on: z3c.soap/trunk/z3c/soap/tests/mailvalidation.py
___________________________________________________________________
Added: svn:keywords
   + Id

Added: z3c.soap/trunk/z3c/soap/tests/soap.zcml
===================================================================
--- z3c.soap/trunk/z3c/soap/tests/soap.zcml	                        (rev 0)
+++ z3c.soap/trunk/z3c/soap/tests/soap.zcml	2008-11-13 12:18:51 UTC (rev 92902)
@@ -0,0 +1,54 @@
+<configure xmlns="http://namespaces.zope.org/zope"
+           xmlns:soap="http://namespaces.zope.org/soap"
+           i18n_domain="zope">
+
+  <include package="z3c.soap" file="meta.zcml"/>
+  <include package="zope.app.security" file="meta.zcml"/>
+ 
+  <soap:view
+      name="test"
+      class="zope.app.component.tests.views.V1"
+      for="zope.app.component.tests.views.IC"
+      permission="zope.Public"
+      />
+
+  <soap:view
+      name="test2"
+      class="zope.app.component.tests.views.V1"
+      for="zope.app.component.tests.views.IC"
+      permission="zope.Public"
+      interface="zope.app.component.tests.views.IV"
+      />
+
+  <soap:view
+      name="test3"
+      class="zope.app.component.tests.views.V1"
+      for="zope.app.component.tests.views.IC"
+      permission="zope.Public"
+      methods="action" />
+
+  <soap:view
+      name="test4"
+      class="zope.app.component.tests.views.V1"
+      for="zope.app.component.tests.views.IC"
+      permission="zope.Public"
+      methods="action"
+      interface="zope.app.component.tests.views.IV" />
+
+  <soap:view
+      name="test5"
+      class="zope.app.component.tests.views.V1"
+      for="zope.app.component.tests.views.IC"
+      permission="zope.Public"
+      methods="action index"
+      interface="zope.app.component.tests.views.IV" />
+ 
+  <soap:view
+      class="zope.app.component.tests.views.V1"
+      for="zope.app.component.tests.views.IC"
+      interface="zope.app.component.tests.views.IV"
+      methods="action"
+      permission="zope.Public"
+      />
+
+</configure>

Added: z3c.soap/trunk/z3c/soap/tests/soap_error.zcml
===================================================================
--- z3c.soap/trunk/z3c/soap/tests/soap_error.zcml	                        (rev 0)
+++ z3c.soap/trunk/z3c/soap/tests/soap_error.zcml	2008-11-13 12:18:51 UTC (rev 92902)
@@ -0,0 +1,13 @@
+<configure xmlns="http://namespaces.zope.org/zope"
+           xmlns:soap="http://namespaces.zope.org/soap"
+           i18n_domain="zope">
+
+  <include package="soap" file="meta.zcml"/>
+
+  <soap:view
+        name="test"
+        factory="zope.component.tests.views.V1"
+        for="zope.component.tests.views.IC"
+        methods="action index" />
+
+</configure>

Added: z3c.soap/trunk/z3c/soap/tests/test_directives.py
===================================================================
--- z3c.soap/trunk/z3c/soap/tests/test_directives.py	                        (rev 0)
+++ z3c.soap/trunk/z3c/soap/tests/test_directives.py	2008-11-13 12:18:51 UTC (rev 92902)
@@ -0,0 +1,83 @@
+##############################################################################
+#
+# Copyright (c) 2005 Zope Corporation and Contributors.
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.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.
+#
+##############################################################################
+"""
+Test 'soap' ZCML Namespace directives.
+
+$Id$
+"""
+
+from zope.configuration import xmlconfig
+from zope.configuration.exceptions import ConfigurationError
+from zope.app.component.tests.views import IC
+from zope.component import getMultiAdapter, queryMultiAdapter
+from zope.app.testing.placelesssetup import PlacelessSetup
+from z3c.soap.interfaces import ISOAPRequest
+from zope.interface import alsoProvides
+from zope.interface import implements
+import unittest
+import z3c.soap.tests
+from zope.publisher.browser import TestRequest
+
+request = TestRequest(ISOAPRequest)
+alsoProvides(request, ISOAPRequest)
+
+
+class Ob(object):
+
+    implements(IC)
+
+ob = Ob()
+
+
+class DirectivesTest(PlacelessSetup, unittest.TestCase):
+
+    def testView(self):
+        self.assertEqual(
+            queryMultiAdapter((ob, request), name='test'), None)
+        xmlconfig.file("soap.zcml", z3c.soap.tests)
+        self.assertEqual(
+            str(queryMultiAdapter((ob, request), name='test').__class__),
+            "<class 'Products.Five.metaclass.V1'>")
+
+    def testInterfaceAndAttributeProtectedView(self):
+        xmlconfig.file("soap.zcml", z3c.soap.tests)
+        v = getMultiAdapter((ob, request), name='test4')
+        self.assertEqual(v.index(), 'V1 here')
+        self.assertEqual(v.action(), 'done')
+
+    def testDuplicatedInterfaceAndAttributeProtectedView(self):
+        xmlconfig.file("soap.zcml", z3c.soap.tests)
+        v = getMultiAdapter((ob, request), name='test5')
+        self.assertEqual(v.index(), 'V1 here')
+        self.assertEqual(v.action(), 'done')
+
+    def testIncompleteProtectedViewNoPermission(self):
+        self.assertRaises(ConfigurationError, xmlconfig.file,
+                          "soap_error.zcml", z3c.soap.tests)
+
+    def test_no_name(self):
+        xmlconfig.file("soap.zcml", z3c.soap.tests)
+        v = getMultiAdapter((ob, request), name='index')
+        self.assertEqual(v(), 'V1 here')
+        v = getMultiAdapter((ob, request), name='action')
+        self.assertEqual(v(), 'done')
+
+
+def test_suite():
+    return unittest.TestSuite((
+        unittest.makeSuite(DirectivesTest),
+        ))
+
+if __name__ == '__main__':
+    unittest.main()


Property changes on: z3c.soap/trunk/z3c/soap/tests/test_directives.py
___________________________________________________________________
Added: svn:keywords
   + Id

Added: z3c.soap/trunk/z3c/soap/tests/test_soappublication.py
===================================================================
--- z3c.soap/trunk/z3c/soap/tests/test_soappublication.py	                        (rev 0)
+++ z3c.soap/trunk/z3c/soap/tests/test_soappublication.py	2008-11-13 12:18:51 UTC (rev 92902)
@@ -0,0 +1,160 @@
+##############################################################################
+#
+# Copyright (c) 2005 Zope Corporation and Contributors.
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.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.
+#
+##############################################################################
+"""
+SOAP Publication Tests
+
+$Id$
+"""
+import unittest
+
+from zope.app.publication.tests.test_zopepublication import \
+     BasePublicationTests
+from zope.app.publication.traversers import TestTraverser
+from zope.app.publication.soap import SOAPPublication
+from zope.interface import Interface, implements
+from zope.proxy import removeAllProxies
+from zope.publisher.interfaces import NotFound
+from z3c.soap.interfaces import ISOAPPresentation, ISOAPRequest
+from z3c.soap.interfaces import ISOAPPublisher
+from z3c.soap.publisher import SOAPRequest
+from zope.app.testing import ztapi
+from StringIO import StringIO
+
+
+class TestRequest(SOAPRequest):
+
+    def __init__(self, body_instream=None, environ=None,
+                 response=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:
+            body_instream = StringIO('')
+
+        super(TestRequest, self).__init__(
+            body_instream, _testEnv, response)
+
+
+class SimpleObject(object):
+
+    def __init__(self, v):
+        self.v = v
+
+
+class SOAPPublicationTests(BasePublicationTests):
+
+    klass = SOAPPublication
+
+    def _createRequest(self, path, publication, **kw):
+        request = TestRequest(PATH_INFO=path, **kw)
+        request.setPublication(publication)
+        return request
+
+    def testTraverseName(self):
+        pub = self.klass(self.db)
+
+        class C(object):
+            x = SimpleObject(1)
+        ob = C()
+        r = self._createRequest('/x', pub)
+        ztapi.provideView(None, ISOAPRequest, ISOAPPublisher,
+                          '', TestTraverser)
+        ob2 = pub.traverseName(r, ob, 'x')
+        self.assertEqual(removeAllProxies(ob2).v, 1)
+
+    def testDenyDirectMethodAccess(self):
+        pub = self.klass(self.db)
+
+        class I(Interface):
+            pass
+
+        class C(object):
+            implements(I)
+
+            def foo(self):
+                return 'bar'
+
+        class V(object):
+
+            def __init__(self, context, request):
+                pass
+            implements(ISOAPPresentation)
+
+        ob = C()
+        r = self._createRequest('/foo', pub)
+
+        ztapi.provideView(I, ISOAPPresentation, Interface, 'view', V)
+        ztapi.setDefaultViewName(I, 'view', type=ISOAPPresentation)
+        self.assertRaises(NotFound, pub.traverseName, r, ob, 'foo')
+
+    def testTraverseNameView(self):
+        pub = self.klass(self.db)
+
+        class I(Interface):
+            pass
+
+        class C(object):
+            implements(I)
+
+        ob = C()
+
+        class V(object):
+
+            def __init__(self, context, request):
+                pass
+            implements(ISOAPPresentation)
+
+
+        # Register the simple traverser so we can traverse without @@
+        from z3c.soap.interfaces import ISOAPPublisher, ISOAPRequest
+        from zope.app.publication.traversers import SimpleComponentTraverser
+        ztapi.provideView(Interface, ISOAPRequest, ISOAPPublisher, '',
+                          SimpleComponentTraverser)
+
+        r = self._createRequest('/@@spam', pub)
+        ztapi.provideView(I, ISOAPRequest, Interface, 'spam', V)
+        ob2 = pub.traverseName(r, ob, '@@spam')
+        self.assertEqual(removeAllProxies(ob2).__class__, V)
+
+        ob2 = pub.traverseName(r, ob, 'spam')
+        self.assertEqual(removeAllProxies(ob2).__class__, V)
+
+    def testTraverseNameServices(self):
+        pub = self.klass(self.db)
+
+        class C(object):
+
+            def getSiteManager(self):
+                return SimpleObject(1)
+        ob = C()
+        r = self._createRequest('/++etc++site', pub)
+        ob2 = pub.traverseName(r, ob, '++etc++site')
+        self.assertEqual(removeAllProxies(ob2).v, 1)
+
+
+def test_suite():
+    return unittest.TestSuite((
+        unittest.makeSuite(SOAPPublicationTests),
+        ))
+
+if __name__ == '__main__':
+    unittest.main()


Property changes on: z3c.soap/trunk/z3c/soap/tests/test_soappublication.py
___________________________________________________________________
Added: svn:keywords
   + Id

Added: z3c.soap/trunk/z3c/soap/tests/test_soaprequest.py
===================================================================
--- z3c.soap/trunk/z3c/soap/tests/test_soaprequest.py	                        (rev 0)
+++ z3c.soap/trunk/z3c/soap/tests/test_soaprequest.py	2008-11-13 12:18:51 UTC (rev 92902)
@@ -0,0 +1,140 @@
+##############################################################################
+#
+# Copyright (c) 2005 Zope Corporation and Contributors.
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.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.
+#
+##############################################################################
+"""
+Test SOAP requests.
+
+$Id$
+"""
+
+import unittest
+from StringIO import StringIO
+from zope.publisher.base import DefaultPublication
+from zope.publisher.http import HTTPCharsets
+from z3c.soap.publisher import SOAPRequest
+
+
+class Publication(DefaultPublication):
+
+    require_docstrings = 0
+
+    def getDefaultTraversal(self, request, ob):
+        if hasattr(ob, 'browserDefault'):
+            return ob.browserDefault(request)
+        return ob, ()
+
+
+class TestSOAPRequest(SOAPRequest, HTTPCharsets):
+    """Make sure that our request also implements IHTTPCharsets, so that we do
+    not need to register any adapters."""
+
+    def __init__(self, *args, **kw):
+        self.request = self
+        SOAPRequest.__init__(self, *args, **kw)
+
+
+rpc_call = u'''<?xml version="1.0"?>
+<SOAP-ENV:Envelope
+ SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"
+ xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/"
+ xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"
+ xmlns:xsd="http://www.w3.org/1999/XMLSchema"
+ xmlns:xsi="http://www.w3.org/1999/XMLSchema-instance">
+ <SOAP-ENV:Body>
+   <m:action xmlns:m="http://www.soapware.org/">
+     <arg1 xsi:type="xsd:int">42</arg1>
+   </m:action>
+ </SOAP-ENV:Body>
+</SOAP-ENV:Envelope>
+'''
+
+
+class SOAPTests(unittest.TestCase):
+    """ """
+
+    _testEnv = {
+        'PATH_INFO': '/folder/item2/view/',
+        'QUERY_STRING': '',
+        'SERVER_URL': 'http://foobar.com',
+        'HTTP_HOST': 'foobar.com',
+        'CONTENT_LENGTH': '0',
+        'REQUEST_METHOD': 'POST',
+        'HTTP_AUTHORIZATION': 'Should be in accessible',
+        'GATEWAY_INTERFACE': 'TestFooInterface/1.0',
+        'HTTP_OFF_THE_WALL': "Spam 'n eggs",
+        'HTTP_ACCEPT_CHARSET': 'ISO-8859-1, UTF-8;q=0.66, UTF-16;q=0.33'}
+
+    def setUp(self):
+        super(SOAPTests, self).setUp()
+
+        class AppRoot(object):
+            pass
+
+        class Folder(object):
+            pass
+
+        class Item(object):
+
+            def __call__(self, a, b):
+                return "%s, %s" % (`a`, `b`)
+
+            def doit(self, a, b):
+                return 'do something %s %s' % (a, b)
+
+        class View(object):
+
+            def action(self, a):
+                return "Parameter[type: %s; value: %s" %(
+                    type(a).__name__, `a`)
+
+        class Item2(object):
+            view = View()
+
+
+        self.app = AppRoot()
+        self.app.folder = Folder()
+        self.app.folder.item = Item()
+        self.app.folder.item2 = Item2()
+
+    def _createRequest(self, extra_env={}, body=""):
+        env = self._testEnv.copy()
+        env.update(extra_env)
+        if len(body):
+            env['CONTENT_LENGTH'] = str(len(body))
+
+        publication = Publication(self.app)
+        instream = StringIO(body)
+        request = TestSOAPRequest(instream, env)
+        request.setPublication(publication)
+        return request
+
+    def testProcessInput(self):
+        req = self._createRequest({}, rpc_call)
+        req.processInputs()
+        self.failUnlessEqual(req._args, (42, ))
+        self.failUnlessEqual(tuple(req._path_suffix), ('action', ))
+
+    def testTraversal(self):
+        req = self._createRequest({}, rpc_call)
+        req.processInputs()
+        action = req.traverse(self.app)
+        self.failUnlessEqual(action(*req._args),
+                             "Parameter[type: int; value: 42")
+
+
+def test_suite():
+    loader = unittest.TestLoader()
+    return loader.loadTestsFromTestCase(SOAPTests)
+
+if __name__=='__main__':
+    unittest.TextTestRunner().run(test_suite())


Property changes on: z3c.soap/trunk/z3c/soap/tests/test_soaprequest.py
___________________________________________________________________
Added: svn:keywords
   + Id



More information about the Checkins mailing list