[Zope3-checkins] SVN: Zope3/trunk/src/zope/ Added functional
doctests and an AppFSSyncLayer
Uwe Oestermeier
uwe_oestermeier at iwm-kmrc.de
Tue Mar 6 05:34:23 EST 2007
Log message for revision 73003:
Added functional doctests and an AppFSSyncLayer
Changed:
U Zope3/trunk/src/zope/app/dtmlpage/fssync/configure.zcml
U Zope3/trunk/src/zope/app/file/fssync/configure.zcml
U Zope3/trunk/src/zope/app/folder/fssync/configure.zcml
U Zope3/trunk/src/zope/app/fssync/browser/__init__.py
U Zope3/trunk/src/zope/app/fssync/browser/configure.zcml
U Zope3/trunk/src/zope/app/fssync/committer.py
U Zope3/trunk/src/zope/app/fssync/configure.zcml
U Zope3/trunk/src/zope/app/fssync/fspickle.py
A Zope3/trunk/src/zope/app/fssync/fspickle.txt
U Zope3/trunk/src/zope/app/fssync/ftesting.zcml
U Zope3/trunk/src/zope/app/fssync/ftests.py
A Zope3/trunk/src/zope/app/fssync/security.txt
U Zope3/trunk/src/zope/app/fssync/syncer.py
U Zope3/trunk/src/zope/app/module/fssync/configure.zcml
U Zope3/trunk/src/zope/app/zptpage/fssync/configure.zcml
U Zope3/trunk/src/zope/dublincore/fssync/configure.zcml
U Zope3/trunk/src/zope/fssync/fssync.py
U Zope3/trunk/src/zope/fssync/server/entryadapter.py
U Zope3/trunk/src/zope/fssync/server/interfaces.py
U Zope3/trunk/src/zope/fssync/server/syncer.py
-=-
Modified: Zope3/trunk/src/zope/app/dtmlpage/fssync/configure.zcml
===================================================================
--- Zope3/trunk/src/zope/app/dtmlpage/fssync/configure.zcml 2007-03-06 10:05:12 UTC (rev 73002)
+++ Zope3/trunk/src/zope/app/dtmlpage/fssync/configure.zcml 2007-03-06 10:34:19 UTC (rev 73003)
@@ -10,4 +10,13 @@
permission="zope.ManageContent"
/>
+ <class
+ class=".adapter.DTMLPageAdapter">
+
+ <require
+ permission="zope.ManageCode"
+ interface="zope.fssync.server.interfaces.IObjectFile" />
+
+ </class>
+
</configure>
Modified: Zope3/trunk/src/zope/app/file/fssync/configure.zcml
===================================================================
--- Zope3/trunk/src/zope/app/file/fssync/configure.zcml 2007-03-06 10:05:12 UTC (rev 73002)
+++ Zope3/trunk/src/zope/app/file/fssync/configure.zcml 2007-03-06 10:34:19 UTC (rev 73003)
@@ -16,5 +16,15 @@
provides="zope.app.fssync.interfaces.IFSSyncFactory"
permission="zope.ManageContent"
/>
+
+ <class
+ class=".adapter.FileAdapter">
+
+ <require
+ permission="zope.ManageContent"
+ interface="zope.fssync.server.interfaces.IObjectFile" />
+
+ </class>
+
</configure>
Modified: Zope3/trunk/src/zope/app/folder/fssync/configure.zcml
===================================================================
--- Zope3/trunk/src/zope/app/folder/fssync/configure.zcml 2007-03-06 10:05:12 UTC (rev 73002)
+++ Zope3/trunk/src/zope/app/folder/fssync/configure.zcml 2007-03-06 10:34:19 UTC (rev 73003)
@@ -9,5 +9,14 @@
provides="zope.app.fssync.interfaces.IFSSyncFactory"
permission="zope.ManageContent"
/>
+
+ <class
+ class=".adapter.FolderAdapter">
+
+ <require
+ permission="zope.ManageContent"
+ interface="zope.fssync.server.interfaces.IContentDirectory" />
+
+ </class>
</configure>
Modified: Zope3/trunk/src/zope/app/fssync/browser/__init__.py
===================================================================
--- Zope3/trunk/src/zope/app/fssync/browser/__init__.py 2007-03-06 10:05:12 UTC (rev 73002)
+++ Zope3/trunk/src/zope/app/fssync/browser/__init__.py 2007-03-06 10:34:19 UTC (rev 73003)
@@ -24,9 +24,10 @@
import transaction
from zope.traversing.api import getName, getParent, getRoot
+from zope.publisher.browser import BrowserView
+
from zope.fssync.snarf import Snarfer, Unsnarfer
from zope.fssync.metadata import Metadata
-from zope.publisher.browser import BrowserView
from zope.app.fssync import syncer
from zope.app.fssync.committer import Committer, Checker
Modified: Zope3/trunk/src/zope/app/fssync/browser/configure.zcml
===================================================================
--- Zope3/trunk/src/zope/app/fssync/browser/configure.zcml 2007-03-06 10:05:12 UTC (rev 73002)
+++ Zope3/trunk/src/zope/app/fssync/browser/configure.zcml 2007-03-06 10:34:19 UTC (rev 73003)
@@ -8,7 +8,7 @@
<page
for="zope.interface.Interface"
name="toFS.snarf"
- permission="zope.ManageServices"
+ permission="zope.ManageContent"
class=".SnarfFile"
attribute="show"
/>
@@ -17,7 +17,7 @@
<page
for="zope.interface.Interface"
name="fromFS.snarf"
- permission="zope.ManageServices"
+ permission="zope.ManageContent"
class=".SnarfCommit"
attribute="run"
/>
@@ -26,7 +26,7 @@
<page
for="zope.interface.Interface"
name="checkin.snarf"
- permission="zope.ManageServices"
+ permission="zope.ManageContent"
class=".SnarfCheckin"
attribute="run"
/>
Modified: Zope3/trunk/src/zope/app/fssync/committer.py
===================================================================
--- Zope3/trunk/src/zope/app/fssync/committer.py 2007-03-06 10:05:12 UTC (rev 73002)
+++ Zope3/trunk/src/zope/app/fssync/committer.py 2007-03-06 10:34:19 UTC (rev 73003)
@@ -25,7 +25,6 @@
from zope.fssync import fsutil
from zope.fssync.metadata import Metadata
from zope.fssync.server.interfaces import IObjectDirectory, IObjectFile
-from zope.proxy import removeAllProxies
from zope.xmlpickle import fromxml
from zope.traversing.api import traverseName, getName
from zope.lifecycleevent import ObjectCreatedEvent, ObjectModifiedEvent
@@ -93,7 +92,6 @@
Invalid object names are reported by raising
``SynchronizationError``.
"""
-
if (os.sep in name or
(os.altsep and os.altsep in name) or
name == os.curdir or
@@ -234,7 +232,6 @@
corrected by a update operation, including invalid object
names.
"""
-
if (os.sep in name or
(os.altsep and os.altsep in name) or
name == os.curdir or
@@ -245,7 +242,7 @@
# This name can't be mapped safely to the filesystem
# or it is a magic value for traverseName (".", "..", "/")
raise SynchronizationError("invalid separator in name %r" % name)
-
+
if not name:
self.synch_dir(container, fspath, context)
else:
@@ -350,6 +347,7 @@
obj = traverseName(container, name)
else:
adapter.setBody(newdata)
+
# Now publish an event, but not for annotations or
# extras. To know which case we have, see if
# getName() works. *** This is a hack. ***
@@ -400,7 +398,7 @@
if iface is IDirectoryFactory:
if factory:
obj = factory(name)
- obj = removeAllProxies(obj)
+ #obj = removeAllProxies(obj)
else:
raise SynchronizationError(
"don't know how to create a directory",
@@ -410,7 +408,7 @@
if factory:
data = read_file(fspath)
obj = factory(name, None, data)
- obj = removeAllProxies(obj)
+ # obj = removeAllProxies(obj)
else:
# The file must contain an xml pickle, or we can't load it:
s = read_file(fspath)
Modified: Zope3/trunk/src/zope/app/fssync/configure.zcml
===================================================================
--- Zope3/trunk/src/zope/app/fssync/configure.zcml 2007-03-06 10:05:12 UTC (rev 73002)
+++ Zope3/trunk/src/zope/app/fssync/configure.zcml 2007-03-06 10:34:19 UTC (rev 73003)
@@ -19,14 +19,35 @@
</class>
- <utility
- component="zope.fssync.server.entryadapter.DefaultFileAdapter"
+ <!-- The zope.fssync DefaultFileAdapter uses zope.xmlpickle which
+ is not location aware. Therefore we must register a location aware
+ zope.app.fssync.fspickle serializer here. -->
+
+ <utility
+ component="zope.app.fssync.syncer.LocationAwareDefaultFileAdapter"
provides="zope.app.fssync.interfaces.IFSSyncFactory"
- permission="zope.ManageContent"
+ permission="zope.ManageSite"
/>
+
+ <class
+ class="zope.app.fssync.syncer.LocationAwareDefaultFileAdapter">
+
+ <require
+ permission="zope.ManageContent"
+ interface="zope.fssync.server.interfaces.IObjectFile" />
+
+ </class>
+
+ <class
+ class="zope.fssync.server.entryadapter.AttrMapping">
+
+ <require
+ permission="zope.ManageContent"
+ interface="zope.fssync.server.interfaces.IAttrMapping" />
-
+ </class>
+
<!-- Include browser package -->
<include package=".browser" />
Modified: Zope3/trunk/src/zope/app/fssync/fspickle.py
===================================================================
--- Zope3/trunk/src/zope/app/fssync/fspickle.py 2007-03-06 10:05:12 UTC (rev 73002)
+++ Zope3/trunk/src/zope/app/fssync/fspickle.py 2007-03-06 10:34:19 UTC (rev 73003)
@@ -184,8 +184,8 @@
return self.parent
else:
return PersistentLoader.load(self, path)
+
-
class DataLocation(TLocation):
"""Sample data container class used in doctests."""
Added: Zope3/trunk/src/zope/app/fssync/fspickle.txt
===================================================================
--- Zope3/trunk/src/zope/app/fssync/fspickle.txt 2007-03-06 10:05:12 UTC (rev 73002)
+++ Zope3/trunk/src/zope/app/fssync/fspickle.txt 2007-03-06 10:34:19 UTC (rev 73003)
@@ -0,0 +1,63 @@
+Pickle Issues
+=============
+
+Pickling large and complex objects can be tricky, since the boundaries of arbitrary objects
+are often complex and difficult to define.
+
+To illustrate possible problems it is sufficient to look at a single folder with a
+local site manager:
+
+>>> root = getRootFolder()
+>>> from zope.app.folder import Folder
+>>> from zope.app.component.site import LocalSiteManager
+>>> folder1 = root[u'folder1'] = Folder()
+>>> sm1 = LocalSiteManager(folder1)
+>>> folder1.setSiteManager(sm1)
+
+>>> from zope.xmlpickle import dumps
+>>> before = len(dumps(folder1))
+>>> before
+81551
+
+Now we add a second folder:
+
+>>> folder2 = root[u'folder2'] = Folder()
+>>> sm2 = LocalSiteManager(folder2)
+>>> folder2.setSiteManager(sm2)
+
+Let's look at the pickle of our first folder again:
+
+>>> after = len(dumps(folder1))
+>>> after
+114880
+
+Bang! The pickle size increased. That means that the pickle of folder1 contains
+additional data probably from folder2 or at least it's parent. How complex and unpredictable
+the situation is shows the following relation:
+
+>>> len(dumps(folder1)) > len(dumps(root))
+True
+
+Let's try the same with a location aware pickler. The location aware pickler saves persistent
+references to locatable objects and thus stops pickling when a pointer leads to an object outside
+the tree of sublocations:
+
+>>> from zope.app.fssync.fspickle import dumps
+>>> before = len(dumps(folder1))
+
+>>> folder3 = root[u'folder3'] = Folder()
+>>> sm = LocalSiteManager(folder3)
+>>> folder3.setSiteManager(sm)
+
+>>> after = len(dumps(folder1))
+>>> after == before
+True
+
+>>> len(dumps(root)) > len(dumps(folder1))
+True
+
+
+To Do
+=====
+
+Write test for pickles with sorted dict items.
Modified: Zope3/trunk/src/zope/app/fssync/ftesting.zcml
===================================================================
--- Zope3/trunk/src/zope/app/fssync/ftesting.zcml 2007-03-06 10:05:12 UTC (rev 73002)
+++ Zope3/trunk/src/zope/app/fssync/ftesting.zcml 2007-03-06 10:34:19 UTC (rev 73003)
@@ -25,7 +25,23 @@
<role id="zope.Anonymous" title="Everybody"
description="All users have this role implicitly" />
<role id="zope.Manager" title="Site Manager" />
+ <role id="zope.Member" title="Member" />
+
+ <!-- Permissions for the readonly example in security.txt -->
+
+ <permission id="zope.fssync.Read" title="Read access" />
+ <permission id="zope.fssync.Write" title="Write access" />
+
+ <class class="zope.app.file.fssync.adapter.FileAdapter">
+
+ <require
+ permission="zope.fssync.Write"
+ interface="zope.fssync.server.interfaces.IWriteObjectFile" />
+
+ </class>
+
+
<!-- Replace the following directive if you don't want public access -->
<grant permission="zope.View"
role="zope.Anonymous" />
@@ -47,7 +63,23 @@
title="Manager"
login="mgr"
password="mgrpw" />
+
+ <!-- Member with manage content permission -->
+
+ <principal
+ id="zope.cm"
+ title="Member"
+ login="cm"
+ password="cmpw" />
+ <!-- Member with view permission -->
+
+ <principal
+ id="zope.rom"
+ title="Member"
+ login="rom"
+ password="rompw" />
+
<!-- Bootstrap principal used to make local grant to the principal above -->
<principal
id="zope.globalmgr"
@@ -56,5 +88,10 @@
password="globalmgrpw" />
<grant role="zope.Manager" principal="zope.globalmgr" />
+ <grant role="zope.Member" principal="zope.cm" />
+ <grant permission="zope.ManageContent" principal="zope.cm" />
+ <grant permission="zope.ManageContent" principal="zope.rom" />
+ <grant permission="zope.fssync.Read" principal="zope.rom" />
+
</configure>
Modified: Zope3/trunk/src/zope/app/fssync/ftests.py
===================================================================
--- Zope3/trunk/src/zope/app/fssync/ftests.py 2007-03-06 10:05:12 UTC (rev 73002)
+++ Zope3/trunk/src/zope/app/fssync/ftests.py 2007-03-06 10:34:19 UTC (rev 73003)
@@ -96,23 +96,31 @@
module.tearDown(test, 'zope.app.fssync.fssync_txt')
shutil.rmtree(checkoutdir)
-
+def cleanUpTree(dir):
+ if os.path.exists(dir):
+ shutil.rmtree(dir)
+ os.mkdir(dir)
+
def test_suite():
globs = {'os': os,
'zope':zope,
'pprint': doctestunit.pprint,
- 'checkoutdir': checkoutdir,
+ 'checkoutdir':checkoutdir,
+ 'cleanUpTree': cleanUpTree,
'PublisherConnection': PublisherConnection,
'TestNetwork': TestNetwork,
'sleep': time.sleep}
suite = unittest.TestSuite()
- test = functional.FunctionalDocFileSuite('fssync.txt',
+
+ for file in 'fspickle.txt', 'fssync.txt', 'security.txt':
+ test = functional.FunctionalDocFileSuite(file,
setUp=setUp, tearDown=tearDown, globs=globs,
optionflags=doctest.NORMALIZE_WHITESPACE+doctest.ELLIPSIS)
- test.layer = AppFSSyncLayer
- suite.addTest(test)
+ test.layer = AppFSSyncLayer
+ suite.addTest(test)
+
return suite
if __name__ == '__main__': unittest.main()
Added: Zope3/trunk/src/zope/app/fssync/security.txt
===================================================================
--- Zope3/trunk/src/zope/app/fssync/security.txt 2007-03-06 10:05:12 UTC (rev 73002)
+++ Zope3/trunk/src/zope/app/fssync/security.txt 2007-03-06 10:34:19 UTC (rev 73003)
@@ -0,0 +1,124 @@
+Security Issues
+===============
+
+The Python API of zope.fssync and zope.app.fssync does not care about security.
+There are neither security checks nor their natural enemies (removeSecurityProxy calls).
+
+The web-based API however has to deal with security issues which mainly depends on the permissions
+to access serialization adapters and their read and write methods.
+
+By default the permissions are set as follows:
+
+ Read and write access to content and annotations is generally governed by the
+ zope.ManageContent permission;
+
+ access to zope.app.module.manager.ModuleManager by zope.ManageCode;
+
+ and access to everything else by zope.ManageSite.
+
+If you need more fine grained distinctions, e.g. differential read and write access, you must
+specify the appropriate permissions for the read and write methods of the registered serialization
+adapters.
+
+Let's start with some objects on the server side:
+
+>>> root = getRootFolder()
+>>> from zope.app.file import File
+>>> serverfile1 = root[u'file1.txt'] = File('A text file', 'plain/text')
+>>> serverfile2 = root[u'file2.txt'] = File('Another text file', 'plain/text')
+
+The root folder has a SiteManager which should only be accessible to
+site managers. This access is governed by the serialization adapters which are
+registered as named utilities. FSSync first looks whether a class based adapter is registered
+as a named utility:
+
+>>> from zope.app.fssync.interfaces import IFSSyncFactory
+>>> zope.component.getUtility(IFSSyncFactory, 'zope.app.component.site.LocalSiteManager')
+Traceback (most recent call last):
+...
+ComponentLookupError: (<...IFSSyncFactory>, 'zope.app.component.site.LocalSiteManager')
+
+Since the LocalSiteManager class has no special serializer FSSync uses the unnamed DefaultAdapter
+which is protected by the ManageSite permission:
+
+>>> factory = zope.component.getUtility(IFSSyncFactory)
+>>> factory.__Security_checker__.get_permissions['__call__']
+'zope.ManageSite'
+
+
+
+Reading with Different Permissions
+----------------------------------
+
+The global manager has all permissions and thus is able to check out all objects:
+
+>>> from zope.fssync.fssync import FSSync
+>>> rooturl = 'http://globalmgr:globalmgrpw@localhost'
+>>> admin = FSSync(network=TestNetwork(), rooturl=rooturl)
+
+Note that the ++etc++site subtree is part of the checkout:
+
+>>> admin.checkout(checkoutdir)
+N .../root/
+U .../root/++etc++site
+N .../root/@@Zope/Annotations/++etc++site/
+U .../root/@@Zope/Annotations/++etc++site/zope.app.dublincore.ZopeDublinCore
+U .../root/file1.txt
+N .../root/@@Zope/Extra/file1.txt/
+U .../root/@@Zope/Extra/file1.txt/contentType
+U .../root/file2.txt
+N .../root/@@Zope/Extra/file2.txt/
+U .../root/@@Zope/Extra/file2.txt/contentType
+N .../@@Zope/Annotations/root/
+U .../@@Zope/Annotations/root/zope.app.dublincore.ZopeDublinCore
+U .../@@Zope/Annotations/root/zope.app.security.AnnotationPrincipalRoleManager
+All done.
+
+>>> cleanUpTree(checkoutdir)
+
+Now we perform the same checkout with the limited permission of a content manager:
+
+>>> rooturl = 'http://cm:cmpw@localhost'
+>>> contentmanager = FSSync(network=TestNetwork(), rooturl=rooturl)
+>>> contentmanager.checkout(checkoutdir)
+N .../root/
+U .../root/file1.txt
+U .../root/file2.txt
+N .../@@Zope/Annotations/root/
+U .../@@Zope/Annotations/root/zope.app.dublincore.ZopeDublinCore
+All done.
+
+>>> cleanUpTree(checkoutdir)
+
+
+Limited Write Permissions
+-------------------------
+
+What if we want to restrict the write access to specific users? One possibility is to introduce
+new permissions, e.g. zope.app.fssync.Read and zope.app.fssync.Write which are used as
+specific permissions to call read and write methods (see ftesting.zcml).
+
+
+>>> rooturl = 'http://rom:rompw@localhost'
+>>> readonly = FSSync(network=TestNetwork(), rooturl=rooturl)
+>>> readonly.checkout(checkoutdir)
+N .../root/
+U .../root/file1.txt
+U .../root/file2.txt
+N .../@@Zope/Annotations/root/
+U .../@@Zope/Annotations/root/zope.app.dublincore.ZopeDublinCore
+All done.
+
+
+>>> localfile1 = os.path.join(checkoutdir, 'root', 'file1.txt')
+>>> fp = open(localfile1, 'w')
+>>> fp.write('A modified text file')
+>>> fp.close()
+
+>>> readonly.commit(localfile1)
+Traceback (most recent call last):
+...
+Error: HTTP error 403 (Forbidden); error document:
+...
+
+
Modified: Zope3/trunk/src/zope/app/fssync/syncer.py
===================================================================
--- Zope3/trunk/src/zope/app/fssync/syncer.py 2007-03-06 10:05:12 UTC (rev 73002)
+++ Zope3/trunk/src/zope/app/fssync/syncer.py 2007-03-06 10:34:19 UTC (rev 73003)
@@ -19,22 +19,39 @@
from zope import interface
from zope import component
+from zope import xmlpickle
from zope.traversing.api import getPath
from zope.annotation.interfaces import IAnnotations
from zope.annotation.attribute import AttributeAnnotations
+from zope.proxy import removeAllProxies
+from zope.security.management import checkPermission
+from zope.security.checker import ProxyFactory
+
from zope.fssync.server.syncer import Syncer
+from zope.fssync.server import entryadapter
from zope.app.fssync.interfaces import IFSSyncFactory
-from interfaces import IFSSyncAnnotations
+import interfaces
+import fspickle
def dottedname(klass):
return "%s.%s" % (klass.__module__, klass.__name__)
+
+class LocationAwareDefaultFileAdapter(entryadapter.DefaultFileAdapter):
+ """A specialization of the DefaultFileAdapter which uses a location aware
+ pickle.
+ """
+
+ def getBody(self):
+ return xmlpickle.toxml(fspickle.dumps(self.context))
+
+
class FSSyncAnnotations(AttributeAnnotations):
"""Default adapter for access to attribute annotations.
Should be registered as trusted adapter.
"""
- interface.implements(IFSSyncAnnotations)
+ interface.implements(interfaces.IFSSyncAnnotations)
def provideSynchronizer(klass, factory):
@@ -42,7 +59,7 @@
name = dottedname(klass)
else:
name = ''
- component.provideUtility(factory, provides=IFSSyncFactory, name=name)
+ component.provideUtility(factory, provides=interfaces.IFSSyncFactory, name=name)
def getObjectId(obj):
@@ -53,15 +70,27 @@
Looks for a named factory first and returns a default adapter
if the dotted class name is not known.
+
+ Checks also for the permission to call the factory in the context of the given object.
+ Removes the security proxy if a call is allowed.
"""
name = dottedname(obj.__class__)
- factory = component.queryUtility(IFSSyncFactory, name=name)
+ factory = component.queryUtility(interfaces.IFSSyncFactory, name=name)
if factory is None:
- factory = component.getUtility(IFSSyncFactory)
- return factory(obj)
+ factory = component.queryUtility(interfaces.IFSSyncFactory)
+ checker = getattr(factory, '__Security_checker__', None)
+ if checker is None:
+ return factory(obj)
+
+ permission = checker.get_permissions['__call__']
+ if checkPermission(permission, obj):
+ return ProxyFactory(factory(removeAllProxies(obj)))
+
+ return None
+
def getAnnotations(obj):
- return IFSSyncAnnotations(obj, None)
+ return interfaces.IFSSyncAnnotations(obj, None)
def toFS(obj, name, location):
Modified: Zope3/trunk/src/zope/app/module/fssync/configure.zcml
===================================================================
--- Zope3/trunk/src/zope/app/module/fssync/configure.zcml 2007-03-06 10:05:12 UTC (rev 73002)
+++ Zope3/trunk/src/zope/app/module/fssync/configure.zcml 2007-03-06 10:34:19 UTC (rev 73003)
@@ -9,4 +9,13 @@
permission="zope.ManageCode"
/>
+ <class
+ class=".adapter.ModuleAdapter">
+
+ <require
+ permission="zope.ManageCode"
+ interface="zope.fssync.server.interfaces.IObjectFile" />
+
+ </class>
+
</configure>
Modified: Zope3/trunk/src/zope/app/zptpage/fssync/configure.zcml
===================================================================
--- Zope3/trunk/src/zope/app/zptpage/fssync/configure.zcml 2007-03-06 10:05:12 UTC (rev 73002)
+++ Zope3/trunk/src/zope/app/zptpage/fssync/configure.zcml 2007-03-06 10:34:19 UTC (rev 73003)
@@ -10,4 +10,13 @@
permission="zope.ManageContent"
/>
+ <class
+ class=".adapter.ZPTPageAdapter">
+
+ <require
+ permission="zope.ManageCode"
+ interface="zope.fssync.server.interfaces.IObjectFile" />
+
+ </class>
+
</configure>
Modified: Zope3/trunk/src/zope/dublincore/fssync/configure.zcml
===================================================================
--- Zope3/trunk/src/zope/dublincore/fssync/configure.zcml 2007-03-06 10:05:12 UTC (rev 73002)
+++ Zope3/trunk/src/zope/dublincore/fssync/configure.zcml 2007-03-06 10:34:19 UTC (rev 73003)
@@ -7,5 +7,15 @@
provides="zope.app.fssync.interfaces.IFSSyncFactory"
permission="zope.ManageContent"
/>
+
+ <class
+ class=".adapter.ZDCAnnotationDataAdapter">
+
+ <require
+ permission="zope.ManageContent"
+ interface="zope.fssync.server.interfaces.IObjectFile" />
+
+ </class>
+
</configure>
Modified: Zope3/trunk/src/zope/fssync/fssync.py
===================================================================
--- Zope3/trunk/src/zope/fssync/fssync.py 2007-03-06 10:05:12 UTC (rev 73002)
+++ Zope3/trunk/src/zope/fssync/fssync.py 2007-03-06 10:34:19 UTC (rev 73003)
@@ -208,11 +208,13 @@
assert self.rooturl
if not path.endswith("/"):
path += "/"
+ path = urllib.quote(path)
path += view
if self.roottype == "https":
conn = httplib.HTTPSConnection(self.host_port)
else:
conn = httplib.HTTPConnection(self.host_port)
+
if datasource is None:
conn.putrequest("GET", path)
else:
Modified: Zope3/trunk/src/zope/fssync/server/entryadapter.py
===================================================================
--- Zope3/trunk/src/zope/fssync/server/entryadapter.py 2007-03-06 10:05:12 UTC (rev 73002)
+++ Zope3/trunk/src/zope/fssync/server/entryadapter.py 2007-03-06 10:34:19 UTC (rev 73003)
@@ -16,19 +16,16 @@
$Id$
"""
-from zope.fssync.server.interfaces import IObjectFile, IContentDirectory
from zope.interface import implements
-from zope.xmlpickle import toxml # dumps
+from zope.xmlpickle import dumps
+from zope.fssync.server import interfaces
-# TODO: This is a bug; we shouldn't depend on these packages at all.
-# Need to restructure.
-from zope.proxy import removeAllProxies
-from zope.app.fssync import fspickle
-
class AttrMapping(object):
- """Convenience object implementing a mapping on selected object attributes
+ """Convenience object implementing a mapping on selected object attributes.
"""
+ implements(interfaces.IAttrMapping)
+
def __init__(self, context, attrs):
self.attrs = attrs
self.context = context
@@ -65,7 +62,7 @@
"""Convenience Base class for ObjectEntry adapter implementations."""
def __init__(self, context):
- self.context = removeAllProxies(context)
+ self.context = context # removeAllProxies(context)
# TODO: for now, remove all proxies.
def extra(self):
@@ -86,17 +83,17 @@
class DefaultFileAdapter(ObjectEntryAdapter):
"""Default File-system representation for objects."""
- implements(IObjectFile)
+ implements(interfaces.IObjectFile)
def getBody(self):
- "See IObjectFile"
+ """See IObjectFile.
- #uo: why was fspickle used here? To keep references to locatable objects?
- s = fspickle.dumps(self.context)
- return toxml(s)
-
- #If we use zope.xmlpickle.dumps we always get the xml elements in a fixed order
- #return dumps(self.context)
+ Uses the zope.xmlpickle which is not very usefull in most circumstances.
+ This pickler does not preserve location and parent information.
+ Use zope.app.fssync.fspickle if you want to pickle standard
+ zope.app objects.
+ """
+ return dumps(self.context)
def setBody(self, body):
"See IObjectFile"
@@ -118,7 +115,7 @@
class DirectoryAdapter(ObjectEntryAdapter):
"""Folder adapter to provide a file-system representation.
"""
- implements(IContentDirectory)
+ implements(interfaces.IContentDirectory)
def contents(self):
result = []
Modified: Zope3/trunk/src/zope/fssync/server/interfaces.py
===================================================================
--- Zope3/trunk/src/zope/fssync/server/interfaces.py 2007-03-06 10:05:12 UTC (rev 73002)
+++ Zope3/trunk/src/zope/fssync/server/interfaces.py 2007-03-06 10:34:19 UTC (rev 73003)
@@ -17,8 +17,15 @@
"""
from zope.interface import Interface
+from zope.interface.common import mapping
+class IAttrMapping(mapping.IReadMapping, mapping.IWriteMapping):
+ """An attribute mapping."""
+
+ def __iter__():
+ """Iterates over all attributes."""
+
class IObjectEntry(Interface):
"""File-system object representation."""
@@ -47,17 +54,22 @@
the dotted name of the object class.
"""
+class IReadObjectFile(Interface):
+ """Read method for file-like objects."""
-class IObjectFile(IObjectEntry):
- """File-system object representation for file-like objects."""
-
def getBody():
"""Return the file body."""
+
+class IWriteObjectFile(Interface):
def setBody(body):
"""Change the file body."""
+class IObjectFile(IObjectEntry, IReadObjectFile, IWriteObjectFile):
+ """File-system object representation for file-like objects."""
+
+
class IObjectDirectory(IObjectEntry):
"""File-system object representation for directory-like objects."""
Modified: Zope3/trunk/src/zope/fssync/server/syncer.py
===================================================================
--- Zope3/trunk/src/zope/fssync/server/syncer.py 2007-03-06 10:05:12 UTC (rev 73002)
+++ Zope3/trunk/src/zope/fssync/server/syncer.py 2007-03-06 10:34:19 UTC (rev 73003)
@@ -66,7 +66,9 @@
# Get the object adapter
adapter = self.getSerializer(ob)
-
+ if adapter is None:
+ return # there is no serializer or we are not allowed to access one
+
entry.clear()
entry['type'] = adapter.typeIdentifier()
entry['factory'] = adapter.factory()
More information about the Zope3-Checkins
mailing list