[Checkins] SVN: z3c.amf/ flash/amf in zope2. Initial import

Jean-Fran�ois Roche jfroche at jfroche.be
Mon Nov 17 18:14:33 EST 2008


Log message for revision 93063:
  flash/amf in zope2. Initial import

Changed:
  A   z3c.amf/
  A   z3c.amf/branches/
  A   z3c.amf/tags/
  A   z3c.amf/trunk/
  A   z3c.amf/trunk/.installed.cfg
  A   z3c.amf/trunk/bootstrap.py
  A   z3c.amf/trunk/buildout.cfg
  A   z3c.amf/trunk/docs/
  A   z3c.amf/trunk/docs/HISTORY.txt
  A   z3c.amf/trunk/setup.cfg
  A   z3c.amf/trunk/setup.py
  A   z3c.amf/trunk/z3c/
  A   z3c.amf/trunk/z3c/__init__.py
  A   z3c.amf/trunk/z3c/amf/
  A   z3c.amf/trunk/z3c/amf/HTTPRequest.py
  A   z3c.amf/trunk/z3c/amf/README.txt
  A   z3c.amf/trunk/z3c/amf/__init__.py
  A   z3c.amf/trunk/z3c/amf/amfgateway.py
  A   z3c.amf/trunk/z3c/amf/browser/
  A   z3c.amf/trunk/z3c/amf/browser/__init__.py
  A   z3c.amf/trunk/z3c/amf/browser/configure.zcml
  A   z3c.amf/trunk/z3c/amf/browser/crossdomain.xml
  A   z3c.amf/trunk/z3c/amf/configure.zcml
  A   z3c.amf/trunk/z3c/amf/ftesting.zcml
  A   z3c.amf/trunk/z3c/amf/ftests.py
  A   z3c.amf/trunk/z3c/amf/interfaces.py
  A   z3c.amf/trunk/z3c/amf/meta.zcml
  A   z3c.amf/trunk/z3c/amf/metaconfigure.py
  A   z3c.amf/trunk/z3c/amf/metadirectives.py
  A   z3c.amf/trunk/z3c/amf/patch.py
  A   z3c.amf/trunk/z3c/amf/permissions.py
  A   z3c.amf/trunk/z3c/amf/tests/
  A   z3c.amf/trunk/z3c/amf/tests/__init__.py
  A   z3c.amf/trunk/z3c/amf/tests/amf.zcml
  A   z3c.amf/trunk/z3c/amf/tests/amf_error.zcml
  A   z3c.amf/trunk/z3c/amf/tests/test_directives.py

-=-
Added: z3c.amf/trunk/.installed.cfg
===================================================================
--- z3c.amf/trunk/.installed.cfg	                        (rev 0)
+++ z3c.amf/trunk/.installed.cfg	2008-11-17 23:14:33 UTC (rev 93063)
@@ -0,0 +1,65 @@
+[buildout]
+installed_develop_eggs = /svn/z3c.amf/develop-eggs/z3c.amf.egg-link
+parts = zope2 instance test
+
+[zope2]
+__buildout_installed__ = /svn/z3c.amf/parts/zope2
+__buildout_signature__ = plone.recipe.zope2install-2.5-py2.4.egg setuptools-0.6c9-py2.4.egg zc.buildout-1.1.1-py2.4.egg
+executable = /svn/z3c.amf/bin/python2.4
+fake-zope-eggs = true
+location = /svn/z3c.amf/parts/zope2
+recipe = plone.recipe.zope2install
+skip-fake-eggs = zope.testing
+url = http://www.zope.org/Products/Zope/2.10.6/Zope-2.10.6-final.tgz
+
+[instance]
+__buildout_installed__ = /svn/z3c.amf/parts/instance
+__buildout_signature__ = plone.recipe.zope2instance-2.6-py2.4.egg zc.recipe.egg-1.1.0-py2.4.egg setuptools-0.6c9-py2.4.egg zc.buildout-1.1.1-py2.4.egg zc.buildout-1.1.1-py2.4.egg
+_b = /svn/z3c.amf/bin
+_d = /svn/z3c.amf/develop-eggs
+_e = /svn/z3c.amf/eggs
+bin-directory = /svn/z3c.amf/bin
+debug-mode = on
+develop-eggs-directory = /svn/z3c.amf/develop-eggs
+eggs = %(__buildout_space_n__)s%(__buildout_space_n__)szope.testing
+	z3c.amf
+eggs-directory = /svn/z3c.amf/eggs
+executable = /svn/z3c.amf/bin/python2.4
+location = /svn/z3c.amf/parts/instance
+recipe = plone.recipe.zope2instance
+scripts = 
+user = admin:admin
+verbose-security = on
+zcml = %(__buildout_space_n__)sz3c.amf-meta
+	z3c.amf
+zope2-location = /svn/z3c.amf/parts/zope2
+
+[test]
+__buildout_installed__ = /svn/z3c.amf/parts/test
+	/svn/z3c.amf/bin/test
+__buildout_signature__ = zc.recipe.testrunner-1.1.0-py2.4.egg zc.recipe.egg-1.1.0-py2.4.egg setuptools-0.6c9-py2.4.egg zope.testing-3.7.1-py2.4.egg zc.buildout-1.1.1-py2.4.egg zc.buildout-1.1.1-py2.4.egg zope.interface-/ZDECtRPNxDRwonKEero+A==
+_b = /svn/z3c.amf/bin
+_d = /svn/z3c.amf/develop-eggs
+_e = /svn/z3c.amf/eggs
+bin-directory = /svn/z3c.amf/bin
+defaults = ['--tests-pattern', '^f?tests$', '-c', '--module=z3c.amf']
+develop-eggs-directory = /svn/z3c.amf/develop-eggs
+eggs = z3c.amf
+eggs-directory = /svn/z3c.amf/eggs
+executable = /svn/z3c.amf/bin/python2.4
+extra-paths = /svn/z3c.amf/parts/zope2/lib/python
+location = /svn/z3c.amf/parts/test
+recipe = zc.recipe.testrunner
+script = /svn/z3c.amf/bin/test
+
+[buildout]
+installed_develop_eggs = /svn/z3c.amf/develop-eggs/z3c.amf.egg-link
+
+[buildout]
+parts = instance test zope2
+
+[buildout]
+parts = test zope2 instance
+
+[buildout]
+parts = zope2 instance test

Added: z3c.amf/trunk/bootstrap.py
===================================================================
--- z3c.amf/trunk/bootstrap.py	                        (rev 0)
+++ z3c.amf/trunk/bootstrap.py	2008-11-17 23:14:33 UTC (rev 93063)
@@ -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.amf/trunk/bootstrap.py
___________________________________________________________________
Added: svn:keywords
   + Id

Added: z3c.amf/trunk/buildout.cfg
===================================================================
--- z3c.amf/trunk/buildout.cfg	                        (rev 0)
+++ z3c.amf/trunk/buildout.cfg	2008-11-17 23:14:33 UTC (rev 93063)
@@ -0,0 +1,40 @@
+[buildout]
+parts =
+    instance
+    test
+
+find-links =
+
+develop =
+    .
+
+eggs =
+
+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.amf
+
+zcml =
+    z3c.amf-meta
+    z3c.amf
+
+[test]
+recipe = zc.recipe.testrunner
+eggs = z3c.amf
+defaults = ['--tests-pattern', '^f?tests$', '-c', '--module=z3c.amf']
+extra-paths = ${zope2:location}/lib/python

Added: z3c.amf/trunk/docs/HISTORY.txt
===================================================================
--- z3c.amf/trunk/docs/HISTORY.txt	                        (rev 0)
+++ z3c.amf/trunk/docs/HISTORY.txt	2008-11-17 23:14:33 UTC (rev 93063)
@@ -0,0 +1,8 @@
+Changelog
+=========
+
+0.1 - (2008-11-17)
+------------------
+
+* Initial release
+


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

Added: z3c.amf/trunk/setup.cfg
===================================================================
--- z3c.amf/trunk/setup.cfg	                        (rev 0)
+++ z3c.amf/trunk/setup.cfg	2008-11-17 23:14:33 UTC (rev 93063)
@@ -0,0 +1,3 @@
+[egg_info]
+tag_build = dev
+tag_svn_revision = true

Added: z3c.amf/trunk/setup.py
===================================================================
--- z3c.amf/trunk/setup.py	                        (rev 0)
+++ z3c.amf/trunk/setup.py	2008-11-17 23:14:33 UTC (rev 93063)
@@ -0,0 +1,41 @@
+from setuptools import setup, find_packages
+import os
+
+version = '0.1'
+
+setup(name='z3c.amf',
+      version=version,
+      description="Zope support for Flash messages (AMF)",
+      long_description=open(os.path.join("z3c", "amf",
+                                         "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",
+        "Programming Language :: Python",
+        "Topic :: Software Development :: Libraries :: Python Modules",
+        ],
+      keywords='Zope2 Zope AMF Flash Flex',
+      author='Jean-Francois Roche',
+      author_email='jfroche at affinitic.be',
+      url='http://svn.zope.org/z3c.amf',
+      license='ZPL 2.1',
+      packages=find_packages(exclude=['ez_setup']),
+      namespace_packages=['z3c'],
+      include_package_data=True,
+      zip_safe=False,
+      install_requires=[
+          'setuptools',
+          'pyamf',
+          'Products.CMFCore',
+          'Products.PluggableAuthService'
+      ],
+      entry_points="""
+      # -*- Entry points: -*-
+      """,
+      )


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

Added: z3c.amf/trunk/z3c/__init__.py
===================================================================
--- z3c.amf/trunk/z3c/__init__.py	                        (rev 0)
+++ z3c.amf/trunk/z3c/__init__.py	2008-11-17 23:14:33 UTC (rev 93063)
@@ -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.amf/trunk/z3c/__init__.py
___________________________________________________________________
Added: svn:keywords
   + Id

Added: z3c.amf/trunk/z3c/amf/HTTPRequest.py
===================================================================
--- z3c.amf/trunk/z3c/amf/HTTPRequest.py	                        (rev 0)
+++ z3c.amf/trunk/z3c/amf/HTTPRequest.py	2008-11-17 23:14:33 UTC (rev 93063)
@@ -0,0 +1,718 @@
+# -*- coding: utf-8 -*-
+###############################################################################
+#
+# 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
+#
+##############################################################################
+"""
+$Id$
+"""
+
+import re
+from cgi import FieldStorage, escape
+from ZPublisher.HTTPRequest import *
+from ZPublisher.Converters import get_converter
+from copy import deepcopy
+from ZPublisher.TaintedString import TaintedString
+from zope.interface import directlyProvides
+from z3c.amf.interfaces import IAMFRequest
+
+xmlrpc=None # Placeholder for module that we'll import if we have to.
+amfgateway=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:
+        # Hm, maybe it's an XML-RPC
+        if (fs.headers.has_key('content-type') and
+            'text/xml' in fs.headers['content-type'] and
+            method == 'POST'):
+            # 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
+        elif (fs.headers.has_key('content-type') and
+            'application/x-amf' in fs.headers['content-type']):
+            global amfgateway
+            directlyProvides(self, IAMFRequest)
+            if amfgateway is None: import amfgateway
+            aparser = amfgateway.AMFParser(fs.value)
+            aparser.parse()
+            meth = aparser.method
+            self.args = aparser.args
+            response = amfgateway.AMFResponse(response)
+            response._amfVersion = aparser.amfVersion
+            response._clientType = aparser.clientType
+            response._method = meth
+            response._name = aparser.name
+            auth = aparser.auth
+            if auth:
+                import base64
+                response._auth = 1
+                authString = "%s:%s" % (auth.get('userid'),
+                                        auth.get('password'))
+                self._auth = "Basic %s" % base64.encodestring(authString)
+                self._auth = self._auth.replace('\n','')
+            other['RESPONSE'] = self.response = response
+            other['REQUEST_METHOD'] = method
+            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(default_encoding))
+                        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("z3c.amf: modified ZPublisher.HTTPRequest.processInputs")
+


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

Added: z3c.amf/trunk/z3c/amf/README.txt
===================================================================
--- z3c.amf/trunk/z3c/amf/README.txt	                        (rev 0)
+++ z3c.amf/trunk/z3c/amf/README.txt	2008-11-17 23:14:33 UTC (rev 93063)
@@ -0,0 +1,246 @@
+AMF/Flash Support in Zope 2
+===========================
+
+Introduction
+------------
+
+This package allows you to query Zope 2 from a flash using Flex with
+Actionscript 2 or Actionscript 3 throught AMF0 or AMF3.
+
+We are just providing here the Zope layer. The lower layer has been done
+using the PyAMF package (see http://pyamf.org).
+
+Let's write a simple AMF view that echoes various types of input:
+
+  >>> from Products.Five import BrowserView
+  >>> from datetime import datetime
+  >>> import elementtree.ElementTree as etree
+  >>> class EchoView(BrowserView):
+  ...
+  ...   def echoString(self, value):
+  ...       return "%s" % value
+  ...
+  ...   def echoProtectedString(self, value):
+  ...       return "%s" % value
+  ...
+  ...   def echoList(self, value):
+  ...       return list(value)
+  ...
+  ...   def echoDict(self, value):
+  ...       return dict(value)
+  ...
+  ...   def echoVoid(self, value):
+  ...       pass
+  ...
+  ...   def echoTuple(self, value):
+  ...       return tuple(value)
+  ...
+  ...   def echoDate(self):
+  ...       return datetime(2008, 11, 17, 11, 11)
+  ...
+  ...   def echoXML(self, value):
+  ...       root = etree.Element("html")
+  ...       body = etree.SubElement(root, 'body')
+  ...       body.text = value
+  ...       return root
+
+Now we'll register it as a Flash view. For now we'll just register the
+view for folder objects and call it on the default folder of the user:
+
+  >>> from zope.configuration import xmlconfig
+  >>> ignored = xmlconfig.string("""
+  ... <configure
+  ...     xmlns="http://namespaces.zope.org/zope"
+  ...     xmlns:browser="http://namespaces.zope.org/browser"
+  ...     xmlns:flash="http://namespaces.zope.org/flash"
+  ...     >
+  ...
+  ...   <include package="z3c.amf" file="meta.zcml" />
+  ...   <include package="Products.Five" file="meta.zcml" />
+  ...   <include package="z3c.amf" />
+  ...
+  ...   <flash:view
+  ...       for="OFS.interfaces.IFolder"
+  ...       methods="echoString echoList echoDict echoVoid echoTuple
+  ...                echoDate echoXML"
+  ...       class="z3c.amf.README.EchoView"
+  ...       permission="zope.Public"
+  ...       />
+  ...
+  ...   <flash:view
+  ...       for="OFS.interfaces.IFolder"
+  ...       methods="echoProtectedString"
+  ...       class="z3c.amf.README.EchoView"
+  ...       permission="zope2.FlashAccess"
+  ...       />
+  ...
+  ... </configure>
+  ... """)
+
+We create some helper functions.
+For Requests:
+
+  >>> def createAMFRequest(target, body, username=None, password=None):
+  ...   envelope = remoting.Envelope(pyamf.AMF0, pyamf.ClientTypes.Flash9)
+  ...   if username is not None and password is not None:
+  ...       envelope.headers['Credentials'] = dict(userid=unicode(username),
+  ...                                              password=unicode(password))
+  ...   request = remoting.Request(target, [body], envelope)
+  ...   envelope[u'/1'] = request
+  ...   amfRequest = remoting.encode(envelope)
+  ...   amfRequest.seek(0)
+  ...   return amfRequest.read()
+
+For Responses:
+
+  >>> import pyamf
+  >>> from pyamf import remoting
+  >>> def printAMFResponse(response):
+  ...   context = pyamf.amf0.Context
+  ...   requests = remoting.decode(response.body, context())
+  ...   for name, value in requests.items():
+  ...       print (name, value, type(value.body))
+
+Basic Types
+-----------
+
+String
+
+  >>> amfRequest = createAMFRequest(target='echoString', body='Hello World!')
+  >>> amfRequest
+  '\x00\x03\x00\x00\x00\x01\x00\nechoString\x00\x02/1\x00\x00\x00\x00\n\x00\x00\x00\x01\x02\x00\x0cHello World!'
+  >>> response = http(r"""
+  ... POST /test_folder_1_ HTTP/1.0
+  ... Content-Length: 102
+  ... Content-Type: application/x-amf
+  ...
+  ... %s""" % amfRequest)
+  >>> printAMFResponse(response)
+  (u'/1', <Response status=/onResult>Hello World!</Response>, <type 'unicode'>)
+
+List
+
+  >>> amfRequest = createAMFRequest(target='echoList', body=[u'Hé', u'Ho'])
+  >>> response = http(r"""
+  ... POST /test_folder_1_ HTTP/1.0
+  ... Content-Length: 102
+  ... Content-Type: application/x-amf
+  ...
+  ... %s""" % amfRequest)
+  >>> printAMFResponse(response)
+  (u'/1', <Response status=/onResult>[u'H\xc3\xa9', u'Ho']</Response>,
+   <type 'list'>)
+
+Dictionary
+
+  >>> amfRequest = createAMFRequest(target='echoDict',
+  ...                               body={'fruit': 'orange'})
+  >>> response = http(r"""
+  ... POST /test_folder_1_ HTTP/1.0
+  ... Content-Length: 102
+  ... Content-Type: application/x-amf
+  ...
+  ... %s""" % amfRequest)
+  >>> printAMFResponse(response)
+  (u'/1', <Response status=/onResult>{u'fruit': u'orange'}</Response>,
+   <class 'pyamf.ASObject'>)
+
+Without return
+
+  >>> amfRequest = createAMFRequest(target='echoVoid', body='Hello World!')
+  >>> response = http(r"""
+  ... POST /test_folder_1_ HTTP/1.0
+  ... Content-Length: 102
+  ... Content-Type: application/x-amf
+  ...
+  ... %s""" % amfRequest)
+  >>> printAMFResponse(response)
+  (u'/1', <Response status=/onResult>None</Response>, <type 'NoneType'>)
+
+Tuple
+
+  >>> amfRequest = createAMFRequest(target='echoTuple', body=['foo', 'bar'])
+  >>> response = http(r"""
+  ... POST /test_folder_1_ HTTP/1.0
+  ... Content-Length: 102
+  ... Content-Type: application/x-amf
+  ...
+  ... %s""" % amfRequest)
+  >>> printAMFResponse(response)
+  (u'/1', <Response status=/onResult>[u'foo', u'bar']</Response>,
+   <type 'list'>)
+
+Datetime
+
+  >>> amfRequest = createAMFRequest(target='echoDate', body=None)
+  >>> response = http(r"""
+  ... POST /test_folder_1_ HTTP/1.0
+  ... Content-Length: 102
+  ... Content-Type: application/x-amf
+  ...
+  ... %s""" % amfRequest)
+  >>> printAMFResponse(response)
+  (u'/1', <Response status=/onResult>2008-11-17 11:11:00</Response>,
+   <type 'datetime.datetime'>)
+
+XML
+
+  >>> amfRequest = createAMFRequest(target='echoXML', body='It works!')
+  >>> response = http(r"""
+  ... POST /test_folder_1_ HTTP/1.0
+  ... Content-Length: 102
+  ... Content-Type: application/x-amf
+  ...
+  ... %s""" % amfRequest)
+  >>> printAMFResponse(response)
+  (u'/1', <Response status=/onResult><Element html at ...></Response>,
+   <type 'instance'>)
+
+Errors
+------
+
+
+  >>> amfRequest = createAMFRequest(target='echoUnknown', body=['foo', 'bar'])
+  >>> response = http(r"""
+  ... POST /test_folder_1_ HTTP/1.0
+  ... Content-Length: 102
+  ... Content-Type: application/x-amf
+  ...
+  ... %s""" % amfRequest)
+  >>> printAMFResponse(response)
+  (u'/1', <Response status=/onStatus><ErrorFault level=error code=NotFound type=Resource not found...
+  ...
+
+
+User authentication
+-------------------
+
+Try to access our protected view without providing login/pass in flash:
+
+  >>> amfRequest = createAMFRequest(target='echoProtectedString',
+  ...                               body='It works!')
+  >>> response = http(r"""
+  ... POST /test_folder_1_ HTTP/1.0
+  ... Content-Length: 102
+  ... Content-Type: application/x-amf
+  ...
+  ... %s""" % amfRequest)
+  >>> printAMFResponse(response)
+  (u'/1', <Response status=/onStatus><ErrorFault level=error code=zExceptions.unauthorized.Unauthorized type=Not authorized></Response>,
+   <class 'pyamf.remoting.ErrorFault'>)
+
+
+Now try to access with login/pass:
+
+  >>> from Testing.ZopeTestCase import user_name, user_password
+  >>> amfRequest = createAMFRequest(target='echoProtectedString',
+  ...                               body="Hello World!", username=user_name,
+  ...                               password=user_password)
+  >>> response = http(r"""
+  ... POST /test_folder_1_ HTTP/1.0
+  ... Content-Length: 200
+  ... Content-Type: application/x-amf
+  ...
+  ... %s""" % amfRequest)
+  >>> printAMFResponse(response)
+  (u'/1', <Response status=/onResult>Hello World!</Response>, <type 'unicode'>)


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

Added: z3c.amf/trunk/z3c/amf/__init__.py
===================================================================
--- z3c.amf/trunk/z3c/amf/__init__.py	                        (rev 0)
+++ z3c.amf/trunk/z3c/amf/__init__.py	2008-11-17 23:14:33 UTC (rev 93063)
@@ -0,0 +1,3 @@
+import HTTPRequest
+import patch
+from permissions import *


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

Added: z3c.amf/trunk/z3c/amf/amfgateway.py
===================================================================
--- z3c.amf/trunk/z3c/amf/amfgateway.py	                        (rev 0)
+++ z3c.amf/trunk/z3c/amf/amfgateway.py	2008-11-17 23:14:33 UTC (rev 93063)
@@ -0,0 +1,131 @@
+# -*- coding: utf-8 -*-
+##############################################################################
+#
+# 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
+#
+##############################################################################
+"""
+$Id$
+"""
+
+import logging
+import sys
+import traceback
+import types
+
+from z3c.amf.interfaces import IAMFResponse
+from zExceptions import Unauthorized, NotFound
+from zope.interface import implements
+
+import pyamf
+from pyamf import remoting
+from pyamf.remoting import amf0
+
+
+class AMFParser(object):
+    """
+    Parse the request
+    """
+
+    def __init__(self, data):
+        context = pyamf.get_context(pyamf.AMF0)
+        self.requests = remoting.decode(data, context)
+        self.auth = None
+
+    def parse(self):
+        name, request = self.requests.items()[0]
+        if self.requests.headers:
+            self.auth = self.requests.headers.get(u'Credentials')
+        self.method = request.target
+        params = request.body
+        if params[0] is None:
+            self.args = tuple()
+        else:
+            self.args = tuple(params)
+        self.amfVersion = self.requests.amfVersion
+        self.clientType = self.requests.clientType
+        self.name = name
+
+
+def parse_input(data):
+    parser = AMFParser(data)
+    return parser.parse()
+
+
+class AMFResponse:
+    """Customized Response that handles AMF-specific details.
+
+    We override setBody to marhsall Python objects into AMF. We
+    also override exception to convert errors to AMF faults.
+    """
+    implements(IAMFResponse)
+    _contentType = remoting.CONTENT_TYPE
+
+    # 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):
+        responseBody = remoting.Envelope(self._amfVersion,
+                                         self._clientType)
+        context = pyamf.get_context(pyamf.AMF0)
+        proc = amf0.RequestProcessor(self)
+        if isinstance(body, remoting.BaseFault):
+            amfResponse = remoting.Response(body,
+                                            status=remoting.STATUS_ERROR)
+        else:
+            amfResponse = remoting.Response(body)
+        responseBody[self._name] = amfResponse
+        body = remoting.encode(responseBody, context)
+        body.seek(0)
+        self._real.setBody(body.read())
+        self._setHeader()
+        return self
+
+    def exception(self, fatal=0, info=None,
+                  absuri_match=None, tag_search=None):
+        if isinstance(info, tuple) 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('AMF Exception: %s' % content)
+        f=None
+        self._real.setStatus(200)
+        if t == 'Unauthorized' or t == Unauthorized or (
+           isinstance(t, types.ClassType) and issubclass(t, Unauthorized)):
+            # 401
+            f = remoting.ErrorFault(code=str(t), type='Not authorized')
+        elif isinstance(v, NotFound): # 404
+            f = remoting.ErrorFault(code='NotFound',
+                                    type='Resource not found',
+                                    description=str(v))
+        elif not isinstance(v, pyamf.BaseError): # 500
+            f = remoting.ErrorFault(code=str(t), type=str(v), description=content)
+        self.setBody(f)
+        return tb
+
+    def _setHeader(self):
+        self.setHeader('content-length', len(self._real.body))
+        self._real.setHeader('content-type', self._contentType)


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


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

Added: z3c.amf/trunk/z3c/amf/browser/configure.zcml
===================================================================
--- z3c.amf/trunk/z3c/amf/browser/configure.zcml	                        (rev 0)
+++ z3c.amf/trunk/z3c/amf/browser/configure.zcml	2008-11-17 23:14:33 UTC (rev 93063)
@@ -0,0 +1,12 @@
+<configure xmlns="http://namespaces.zope.org/zope"
+           xmlns:browser="http://namespaces.zope.org/browser"
+           i18n_domain="z3c.amf">
+
+  <browser:page
+    for="*"
+    name="crossdomain.xml"
+    permission="zope.Public"
+    template="crossdomain.xml"/>
+
+</configure>
+

Added: z3c.amf/trunk/z3c/amf/browser/crossdomain.xml
===================================================================
--- z3c.amf/trunk/z3c/amf/browser/crossdomain.xml	                        (rev 0)
+++ z3c.amf/trunk/z3c/amf/browser/crossdomain.xml	2008-11-17 23:14:33 UTC (rev 93063)
@@ -0,0 +1,5 @@
+<!DOCTYPE cross-domain-policy
+  SYSTEM "http://www.macromedia.com/xml/dtds/cross-domain-policy.dtd">
+<cross-domain-policy>
+        <allow-access-from domain="*" />
+</cross-domain-policy>

Added: z3c.amf/trunk/z3c/amf/configure.zcml
===================================================================
--- z3c.amf/trunk/z3c/amf/configure.zcml	                        (rev 0)
+++ z3c.amf/trunk/z3c/amf/configure.zcml	2008-11-17 23:14:33 UTC (rev 93063)
@@ -0,0 +1,10 @@
+<configure xmlns="http://namespaces.zope.org/zope"
+           xmlns:browser="http://namespaces.zope.org/browser"
+           i18n_domain="z3c.amf">
+
+  <permission
+      id="zope2.FlashAccess"
+      title="Flash Access"/>
+
+</configure>
+

Added: z3c.amf/trunk/z3c/amf/ftesting.zcml
===================================================================
--- z3c.amf/trunk/z3c/amf/ftesting.zcml	                        (rev 0)
+++ z3c.amf/trunk/z3c/amf/ftesting.zcml	2008-11-17 23:14:33 UTC (rev 93063)
@@ -0,0 +1,9 @@
+<configure xmlns="http://namespaces.zope.org/zope"
+           i18n_domain="z3c.amf">
+
+     <include package="Products.Five"/>
+     <include package="z3c.amf" file="meta.zcml" />
+
+
+</configure>
+

Added: z3c.amf/trunk/z3c/amf/ftests.py
===================================================================
--- z3c.amf/trunk/z3c/amf/ftests.py	                        (rev 0)
+++ z3c.amf/trunk/z3c/amf/ftests.py	2008-11-17 23:14:33 UTC (rev 93063)
@@ -0,0 +1,107 @@
+##############################################################################
+#
+# 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 AMF.
+
+$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.amf.interfaces import IAMFRequest
+
+
+# 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.amf.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,
+                        IAMFRequest,
+                        zope.interface,
+                        'contents',
+                        None,
+                        )
+    ztapi.provideView(IFolder,
+                        IAMFRequest,
+                        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_amf_functional_layer = ZCMLLayer(filename,
+                                     __name__,
+                                     'z3c.amf_functional_layer')
+
+
+def test_suite():
+    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_amf_functional_layer
+    return ftest
+
+if __name__ == '__main__':
+    import unittest
+    unittest.main(defaultTest='test_suite')


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

Added: z3c.amf/trunk/z3c/amf/interfaces.py
===================================================================
--- z3c.amf/trunk/z3c/amf/interfaces.py	                        (rev 0)
+++ z3c.amf/trunk/z3c/amf/interfaces.py	2008-11-17 23:14:33 UTC (rev 93063)
@@ -0,0 +1,22 @@
+# -*- coding: utf-8 -*-
+"""
+z3c.amf
+
+Licensed under the <+ LICENSE +> license, see LICENCE.txt for more details.
+Copyright by Affinitic sprl
+
+$Id$
+"""
+from zope.interface import Interface
+
+
+class IAMFResponse(Interface):
+    """
+    Marker interface
+    """
+
+
+class IAMFRequest(Interface):
+    """
+    Marker interface
+    """


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

Added: z3c.amf/trunk/z3c/amf/meta.zcml
===================================================================
--- z3c.amf/trunk/z3c/amf/meta.zcml	                        (rev 0)
+++ z3c.amf/trunk/z3c/amf/meta.zcml	2008-11-17 23:14:33 UTC (rev 93063)
@@ -0,0 +1,12 @@
+<configure xmlns="http://namespaces.zope.org/zope"
+           xmlns:meta="http://namespaces.zope.org/meta"
+           i18n_domain="z3c.amf">
+
+  <meta:directive
+       namespace="http://namespaces.zope.org/flash"
+       name="view"
+       schema=".metadirectives.IViewDirective"
+       handler=".metaconfigure.view" />
+
+</configure>
+

Added: z3c.amf/trunk/z3c/amf/metaconfigure.py
===================================================================
--- z3c.amf/trunk/z3c/amf/metaconfigure.py	                        (rev 0)
+++ z3c.amf/trunk/z3c/amf/metaconfigure.py	2008-11-17 23:14:33 UTC (rev 93063)
@@ -0,0 +1,137 @@
+"""
+AMF configuration code
+
+$Id$
+"""
+
+from zope.interface import Interface
+from zope.security.checker import CheckerPublic
+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 z3c.amf.interfaces import IAMFRequest
+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:
+        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, IAMFRequest),
+            callable = handler,
+            args = ('registerAdapter',
+                    new_class, (for_, IAMFRequest),
+                    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:
+        for name in require:
+            cdict.update({'__page_attribute__': name,
+                          '__name__': name})
+            new_class = makeClass(class_.__name__,
+                                  (class_, ViewMixinForAttributes),
+                                  cdict)
+
+            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, IAMFRequest),
+                callable = handler,
+                args = ('registerAdapter',
+                        new_class,
+                        (for_, IAMFRequest), 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.amf/trunk/z3c/amf/metaconfigure.py
___________________________________________________________________
Added: svn:keywords
   + Id

Added: z3c.amf/trunk/z3c/amf/metadirectives.py
===================================================================
--- z3c.amf/trunk/z3c/amf/metadirectives.py	                        (rev 0)
+++ z3c.amf/trunk/z3c/amf/metadirectives.py	2008-11-17 23:14:33 UTC (rev 93063)
@@ -0,0 +1,70 @@
+"""
+AMF 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 AMF methods."""
+
+    for_ = zope.configuration.fields.GlobalObject(
+        title=u"Published Object Type",
+        description=u"""The types of objects to be published via AMF
+
+        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.amf/trunk/z3c/amf/metadirectives.py
___________________________________________________________________
Added: svn:keywords
   + Id

Added: z3c.amf/trunk/z3c/amf/patch.py
===================================================================
--- z3c.amf/trunk/z3c/amf/patch.py	                        (rev 0)
+++ z3c.amf/trunk/z3c/amf/patch.py	2008-11-17 23:14:33 UTC (rev 93063)
@@ -0,0 +1,203 @@
+# -*- coding: utf-8 -*-
+##############################################################################
+#
+# 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
+#
+##############################################################################
+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.amf.interfaces import IAMFRequest
+from z3c.amf.amfgateway import AMFResponse
+import pyamf
+
+
+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 IAMFRequest.providedBy(request):
+            if transactions_manager:
+                transactions_manager.abort()
+            endInteraction()
+            if response is None:
+                response = AMFResponse(request.response)
+                response._amfVersion = pyamf.AMF0
+                response._clientType = pyamf.AMF0
+                response._name = '/1'
+            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
+
+from Products.PluggableAuthService.plugins.CookieAuthHelper import CookieAuthHelper
+from urllib import quote
+
+
+def unauthorized(self):
+        req = self.REQUEST
+        resp = req['RESPONSE']
+
+        # If we set the auth cookie before, delete it now.
+        if self.cookie_name in resp.cookies:
+            del resp.cookies[self.cookie_name]
+
+        # Redirect if desired.
+        url = self.getLoginURL()
+        if IAMFRequest.providedBy(req):
+            #no need to redirect if it's an amf request
+            return 0
+
+        if url is not None:
+            came_from = req.get('came_from', None)
+
+            if came_from is None:
+                came_from = req.get('URL', '')
+                query = req.get('QUERY_STRING')
+                if query:
+                    if not query.startswith('?'):
+                        query = '?' + query
+                    came_from = came_from + query
+            else:
+                # If came_from contains a value it means the user
+                # must be coming through here a second time
+                # Reasons could be typos when providing credentials
+                # or a redirect loop (see below)
+                req_url = req.get('URL', '')
+
+                if req_url and req_url == url:
+                    # Oops... The login_form cannot be reached by the user -
+                    # it might be protected itself due to misconfiguration -
+                    # the only sane thing to do is to give up because we are
+                    # in an endless redirect loop.
+                    return 0
+
+            url = url + '?came_from=%s' % quote(came_from)
+            resp.redirect(url, lock=1)
+            return 1
+
+        # Could not challenge.
+        return 0
+
+CookieAuthHelper.unauthorized = unauthorized


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

Added: z3c.amf/trunk/z3c/amf/permissions.py
===================================================================
--- z3c.amf/trunk/z3c/amf/permissions.py	                        (rev 0)
+++ z3c.amf/trunk/z3c/amf/permissions.py	2008-11-17 23:14:33 UTC (rev 93063)
@@ -0,0 +1,23 @@
+# -*- coding: utf-8 -*-
+###############################################################################
+#
+# 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
+#
+##############################################################################
+"""
+$Id$
+"""
+from AccessControl import ModuleSecurityInfo
+from Products.CMFCore.permissions import setDefaultRoles
+
+security = ModuleSecurityInfo('z3c.amf.permissions')
+security.declarePublic('Flash Access')
+AMFAccess = 'Flash Access'
+setDefaultRoles(AMFAccess, ('Authenticated', ))


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


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

Added: z3c.amf/trunk/z3c/amf/tests/amf.zcml
===================================================================
--- z3c.amf/trunk/z3c/amf/tests/amf.zcml	                        (rev 0)
+++ z3c.amf/trunk/z3c/amf/tests/amf.zcml	2008-11-17 23:14:33 UTC (rev 93063)
@@ -0,0 +1,53 @@
+<configure xmlns="http://namespaces.zope.org/zope"
+           xmlns:flash="http://namespaces.zope.org/flash"
+           i18n_domain="zope">
+
+  <include package="z3c.amf" file="meta.zcml"/>
+  <include package="zope.app.security" file="meta.zcml"/>
+  <flash:view
+      name="test"
+      class="zope.app.component.tests.views.V1"
+      for="zope.app.component.tests.views.IC"
+      permission="zope.Public"
+      />
+
+  <flash: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"
+      />
+
+  <flash:view
+      name="test3"
+      class="zope.app.component.tests.views.V1"
+      for="zope.app.component.tests.views.IC"
+      permission="zope.Public"
+      methods="action" />
+
+  <flash: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" />
+
+  <flash: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" />
+ 
+  <flash: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.amf/trunk/z3c/amf/tests/amf_error.zcml
===================================================================
--- z3c.amf/trunk/z3c/amf/tests/amf_error.zcml	                        (rev 0)
+++ z3c.amf/trunk/z3c/amf/tests/amf_error.zcml	2008-11-17 23:14:33 UTC (rev 93063)
@@ -0,0 +1,14 @@
+<configure xmlns="http://namespaces.zope.org/zope"
+           xmlns:flash="http://namespaces.zope.org/flash"
+           i18n_domain="zope">
+
+  <include package="z3c.amf" file="meta.zcml"/>
+  <include package="zope.app.security" file="meta.zcml"/>
+
+  <flash:view
+        name="test"
+        factory="zope.component.tests.views.V1"
+        for="zope.component.tests.views.IC"
+        methods="action index" />
+
+</configure>

Added: z3c.amf/trunk/z3c/amf/tests/test_directives.py
===================================================================
--- z3c.amf/trunk/z3c/amf/tests/test_directives.py	                        (rev 0)
+++ z3c.amf/trunk/z3c/amf/tests/test_directives.py	2008-11-17 23:14:33 UTC (rev 93063)
@@ -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 'amf' 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.amf.interfaces import IAMFRequest
+from zope.interface import alsoProvides
+from zope.interface import implements
+import unittest
+import z3c.amf.tests
+from zope.publisher.browser import TestRequest
+
+request = TestRequest()
+alsoProvides(request, IAMFRequest)
+
+
+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("amf.zcml", z3c.amf.tests)
+        self.assertEqual(
+            str(queryMultiAdapter((ob, request), name='test').__class__),
+            "<class 'Products.Five.metaclass.V1'>")
+
+    def testInterfaceAndAttributeProtectedView(self):
+        xmlconfig.file("amf.zcml", z3c.amf.tests)
+        v = getMultiAdapter((ob, request), name='test4')
+        self.assertEqual(v.index(), 'V1 here')
+        self.assertEqual(v.action(), 'done')
+
+    def testDuplicatedInterfaceAndAttributeProtectedView(self):
+        xmlconfig.file("amf.zcml", z3c.amf.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,
+                          "amf_error.zcml", z3c.amf.tests)
+
+    def test_no_name(self):
+        xmlconfig.file("amf.zcml", z3c.amf.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.amf/trunk/z3c/amf/tests/test_directives.py
___________________________________________________________________
Added: svn:keywords
   + Id



More information about the Checkins mailing list