Déplacement pour eggification.
[Plinn.git] / Folder.py
diff --git a/Folder.py b/Folder.py
deleted file mode 100644 (file)
index 8ed3cc3..0000000
--- a/Folder.py
+++ /dev/null
@@ -1,557 +0,0 @@
-# -*- coding: utf-8 -*-
-#######################################################################################
-#   Plinn - http://plinn.org                                                          #
-#   Copyright (C) 2005-2014  Benoît Pin <benoit.pin@ensmp.fr>                         #
-#                                                                                     #
-#   This program is free software; you can redistribute it and/or                     #
-#   modify it under the terms of the GNU General Public License                       #
-#   as published by the Free Software Foundation; either version 2                    #
-#   of the License, or (at your option) any later version.                            #
-#                                                                                     #
-#   This program is distributed in the hope that it will be useful,                   #
-#   but WITHOUT ANY WARRANTY; without even the implied warranty of                    #
-#   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the                     #
-#   GNU General Public License for more details.                                      #
-#                                                                                     #
-#   You should have received a copy of the GNU General Public License                 #
-#   along with this program; if not, write to the Free Software                       #
-#   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.   #
-#######################################################################################
-""" Plinn portal folder implementation
-
-
-
-"""
-
-from OFS.CopySupport import CopyError, eNoData, _cb_decode, eInvalid, eNotFound,\
-                            eNotSupported, sanity_check, cookie_path
-from App.Dialogs import MessageDialog
-from zExceptions import BadRequest
-from zExceptions import Unauthorized
-import sys
-import warnings
-from cgi import escape
-from urllib import unquote
-from OFS import Moniker
-from ZODB.POSException import ConflictError
-import OFS.subscribers
-from zope.event import notify
-from zope.lifecycleevent import ObjectCopiedEvent
-try :
-    from zope.app.container.contained import notifyContainerModified
-    from zope.app.container.contained import ObjectMovedEvent
-except ImportError :
-    ## Zope-2.13 compat
-    from zope.container.contained import notifyContainerModified
-    from zope.container.contained import ObjectMovedEvent
-from OFS.event import ObjectClonedEvent
-from OFS.event import ObjectWillBeMovedEvent
-from zope.component.factory import Factory
-from Acquisition import aq_base, aq_inner, aq_parent
-
-from types import StringType, NoneType
-from Products.CMFCore.permissions import ListFolderContents, View, ViewManagementScreens,\
-                                         ManageProperties, AddPortalFolders, AddPortalContent,\
-                                         ManagePortal, ModifyPortalContent
-from permissions import DeletePortalContents, DeleteObjects, DeleteOwnedObjects, SetLocalRoles, CheckMemberPermission
-from Products.CMFCore.utils import _checkPermission, getToolByName
-from Products.CMFCore.utils import getUtilityByInterfaceName
-from Products.CMFCore.CMFCatalogAware import CMFCatalogAware
-from Products.CMFCore.PortalFolder import PortalFolder, ContentFilter
-from Products.CMFCore.interfaces import IDublinCore
-from Products.CMFDefault.DublinCore import DefaultDublinCoreImpl
-
-from zope.interface import implements
-from Products.CMFCore.interfaces import IContentish
-
-from utils import _checkMemberPermission
-from utils import Message as _
-from utils import makeValidId
-from Globals import InitializeClass
-from AccessControl import ClassSecurityInfo
-from ZServer import LARGE_FILE_THRESHOLD
-from webdav.interfaces import IWriteLock
-from webdav.common import Locked
-from webdav.common import PreconditionFailed
-from zope.contenttype import guess_content_type
-
-
-class PlinnFolder(CMFCatalogAware, PortalFolder, DefaultDublinCoreImpl) :
-    """ Plinn Folder """
-    
-    implements(IContentish)
-
-    security = ClassSecurityInfo()
-    
-    manage_options = PortalFolder.manage_options
-
-    ## change security for inherited methods
-    security.declareProtected(AddPortalContent, 'manage_pasteObjects')
-
-    def __init__( self, id, title='' ) :
-        PortalFolder.__init__(self, id)
-        DefaultDublinCoreImpl.__init__(self, title = title)
-            
-    security.declarePublic('allowedContentTypes')
-    def allowedContentTypes(self):
-        """
-        List type info objects for types which can be added in this folder.
-        Types can be filtered using the localContentTypes attribute.
-        """
-        allowedTypes = PortalFolder.allowedContentTypes(self)
-        if hasattr(self, 'localContentTypes'):
-            allowedTypes = [t for t in allowedTypes if t.title in self.localContentTypes]
-        return allowedTypes
-
-    security.declareProtected(View, 'objectIdCanBeDeleted')
-    def objectIdCanBeDeleted(self, id) :
-        """ Check permissions and ownership and return True
-            if current user can delete object id.
-        """
-        if _checkPermission(DeleteObjects, self) : # std zope perm
-            return True
-
-        elif _checkPermission(DeletePortalContents, self):
-            mtool = getToolByName(self, 'portal_membership')
-            authMember = mtool.getAuthenticatedMember()
-            ob = getattr(self, id)
-            if authMember.allowed(ob, object_roles=['Owner'] ) and \
-               _checkPermission(DeleteOwnedObjects, ob) : return True
-
-        else :
-            return False
-
-
-    security.declareProtected(DeletePortalContents, 'manage_delObjects')
-    def manage_delObjects(self, ids=[], REQUEST=None):
-        """Delete subordinate objects.
-           A member can delete his owned contents (if he has the 'Delete Portal Contents' permission)
-           without 'Delete objects' permission in this folder.
-           Return skipped object ids.
-        """
-        notOwned = []
-        if _checkPermission(DeleteObjects, self) : # std zope perm
-            PortalFolder.manage_delObjects(self, ids=ids, REQUEST=REQUEST)
-        else :
-            mtool = getToolByName(self, 'portal_membership')
-            authMember = mtool.getAuthenticatedMember()
-            owned = []
-            if type(ids) == StringType :
-                ids = [ids]
-            for id in ids :
-                ob = self._getOb(id)
-                if authMember.allowed(ob, object_roles=['Owner'] ) and \
-                   _checkPermission(DeleteOwnedObjects, ob) : owned.append(id)
-                else : notOwned.append(id)
-            if owned :
-                PortalFolder.manage_delObjects(self, ids=owned, REQUEST=REQUEST)
-
-        if REQUEST is not None:
-            return self.manage_main(
-                self, REQUEST,
-                manage_tabs_message='Object(s) deleted.',
-                update_menu=1)
-        return notOwned
-
-
-    security.declareProtected(AddPortalContent, 'manage_renameObjects')
-    def manage_renameObjects(self, ids=[], new_ids=[], REQUEST=None) :
-        """ Rename subordinate objects
-            A member can rename his owned contents if he has the 'Modify Portal Content' permission.
-            Returns skippend object ids.
-        """
-        if len(ids) != len(new_ids):
-            raise BadRequest(_('Please rename each listed object.'))
-        
-        if _checkPermission(ViewManagementScreens, self) : # std zope perm
-            return super(PlinnFolder, self).manage_renameObjects(ids, new_ids, REQUEST)
-            
-        mtool = getToolByName(self, 'portal_membership')
-        authMember = mtool.getAuthenticatedMember()
-        skiped = []
-        for id, new_id in zip(ids, new_ids) :
-            if id == new_id : continue
-            
-            ob = self._getOb(id)
-            if authMember.allowed(ob, object_roles=['Owner'] ) and \
-               _checkPermission(ModifyPortalContent, ob) :
-                self.manage_renameObject(id, new_id)
-            else :
-                skiped.append(id)
-        
-        if REQUEST is not None :
-            return self.manage_main(self, REQUEST, update_menu=1)
-
-        return skiped
-
-
-    security.declareProtected(ListFolderContents, 'listFolderContents')
-    def listFolderContents( self, contentFilter=None ):
-        """ List viewable contentish and folderish sub-objects.
-        """
-        items = self.contentItems(filter=contentFilter)
-        l = []
-        for id, obj in items:
-            if _checkPermission(View, obj) :
-                l.append(obj)
-
-        return l
-
-
-    security.declareProtected(ListFolderContents, 'listNearestFolderContents')
-    def listNearestFolderContents(self, contentFilter=None, userid=None, sorted=False) :
-        """ Return folder contents and traverse
-        recursively unaccessfull sub folders to find
-        accessible contents.
-        """
-
-        filt = {}
-        if contentFilter :
-            filt = contentFilter.copy()
-        ctool = getToolByName(self, 'portal_catalog')
-        mtool = getToolByName(self, 'portal_membership')
-
-        if userid and _checkPermission(CheckMemberPermission, getToolByName(self, 'portal_url').getPortalObject()) :
-            checkFunc = lambda perm, ob : _checkMemberPermission(userid, View, ob)
-            filt['allowedRolesAndUsers'] = ctool._listAllowedRolesAndUsers( mtool.getMemberById(userid) )
-        else :
-            checkFunc = _checkPermission
-            filt['allowedRolesAndUsers'] = ctool._listAllowedRolesAndUsers( mtool.getAuthenticatedMember() )
-        
-        
-        # copy from CMFCore.PortalFolder.PortalFolder._filteredItems
-        pt = filt.get('portal_type', [])
-        if type(pt) is type(''):
-            pt = [pt]
-        types_tool = getToolByName(self, 'portal_types')
-        allowed_types = types_tool.listContentTypes()
-        if not pt:
-            pt = allowed_types
-        else:
-            pt = [t for t in pt if t in allowed_types]
-        if not pt:
-            # After filtering, no types remain, so nothing should be
-            # returned.
-            return []
-        filt['portal_type'] = pt
-        #---
-
-        query = ContentFilter(**filt)
-        nearestObjects = []
-        
-        for o in self.objectValues() :
-            if query(o) :
-                if checkFunc(View, o):
-                    nearestObjects.append(o)
-                elif getattr(o.aq_self,'isAnObjectManager', False):
-                    nearestObjects.extend(_getDeepObjects(self, ctool, o, filter=filt))
-                
-        if sorted and len(nearestObjects) > 0 :
-            key, reverse = self.getDefaultSorting()
-            if key != 'position' :
-                indexCallable = callable(getattr(nearestObjects[0], key))
-                if indexCallable :
-                    sortfunc = lambda a, b : cmp(getattr(a, key)(), getattr(b, key)())
-                else :                       
-                    sortfunc = lambda a, b : cmp(getattr(a, key), getattr(b, key))
-                nearestObjects.sort(cmp=sortfunc, reverse=reverse)
-        
-        return nearestObjects
-    
-    security.declareProtected(ListFolderContents, 'listCatalogedContents')
-    def listCatalogedContents(self, contentFilter={}):
-        """ query catalog and returns brains of contents.
-            Requires ExtendedPathIndex
-        """
-        ctool = getUtilityByInterfaceName('Products.CMFCore.interfaces.ICatalogTool')
-        contentFilter['path'] = {'query':'/'.join(self.getPhysicalPath()),
-                                'depth':1}
-        if not contentFilter.has_key('sort_on') :
-            contentFilter['sort_index'] = 'position'
-        return ctool(**contentFilter)    
-
-    security.declarePublic('synContentValues')
-    def synContentValues(self):
-        # value for syndication
-        return self.listNearestFolderContents()
-
-    security.declareProtected(View, 'SearchableText')
-    def SearchableText(self) :
-        """ for full text indexation
-        """
-        return '%s %s' % (self.title, self.description)
-
-    security.declareProtected(AddPortalFolders, 'manage_addPlinnFolder')
-    def manage_addPlinnFolder(self, id, title='', REQUEST=None):
-        """Add a new PortalFolder object with id *id*.
-        """
-        ob=PlinnFolder(id, title)
-        # from CMFCore.PortalFolder.PortalFolder :-)
-        self._setObject(id, ob)
-        if REQUEST is not None:
-            return self.folder_contents( # XXX: ick!
-                self, REQUEST, portal_status_message="Folder added")
-    
-    
-    security.declareProtected(AddPortalContent, 'put_upload')
-    def put_upload(self, REQUEST, RESPONSE):
-        """ Upload a content thru webdav put method.
-            The default behavior (NullRessource.PUT + PortalFolder.PUT_factory)
-            disallow files names with '_' at the begining.
-        """
-
-        self.dav__init(REQUEST, RESPONSE)
-        fileName = unquote(REQUEST.getHeader('X-File-Name', ''))
-        validId = makeValidId(self, fileName, allow_dup=True)
-
-        ifhdr = REQUEST.get_header('If', '')
-        if self.wl_isLocked():
-            if ifhdr:
-                self.dav__simpleifhandler(REQUEST, RESPONSE, col=1)
-            else:
-                raise Locked
-        elif ifhdr:
-            raise PreconditionFailed
-
-        if int(REQUEST.get('CONTENT_LENGTH') or 0) > LARGE_FILE_THRESHOLD:
-            file = REQUEST['BODYFILE']
-            body = file.read(LARGE_FILE_THRESHOLD)
-            file.seek(0)
-        else:
-            body = REQUEST.get('BODY', '')
-
-        typ=REQUEST.get_header('content-type', None)
-        if typ is None:
-            typ, enc=guess_content_type(validId, body)
-
-        if self.checkIdAvailable(validId) :
-            try :
-                ob = self.PUT_factory(validId, typ, body)
-                self._setObject(validId, ob)
-                ob = self._getOb(validId)
-            except ValueError : # maybe "Disallowed subobject type". Fallback to file type.
-                validId = self.invokeFactory('File', validId)
-                ob = self._getOb(validId)
-            if IDublinCore.providedBy(ob) :
-                ob.editMetadata(title=fileName,
-                                format=typ)
-            httpRespCode = 201
-        else :
-            httpRespCode = 200
-            ob = self._getOb(validId)
-
-        # We call _verifyObjectPaste with verify_src=0, to see if the
-        # user can create this type of object (and we don't need to
-        # check the clipboard.
-        try:
-            self._verifyObjectPaste(ob.__of__(self), 0)
-        except CopyError:
-             sMsg = 'Unable to create object of class %s in %s: %s' % \
-                    (ob.__class__, repr(self), sys.exc_info()[1],)
-             raise Unauthorized, sMsg
-
-        ob.PUT(REQUEST, RESPONSE)
-        ob.orig_name = fileName
-        
-        # get method from ob created / refreshed
-        ti = ob.getTypeInfo()
-        method_id = ti.queryMethodID('jsupload_snippet')
-        meth = getattr(ob, method_id) if method_id else None
-        if not meth :
-            # get method from container that receive uploaded content
-            ti = self.getTypeInfo()
-            method_id = ti.queryMethodID('jsupload_snippet')
-            meth = getattr(self, method_id) if method_id else lambda ob : 'Not implemented'
-
-        RESPONSE.setStatus(httpRespCode)
-        RESPONSE.setHeader('Content-Type', 'text/xml;;charset=utf-8')
-        return '<fragment>%s</fragment>' % meth(ob).strip()
-
-    
-#   ## overload to maintain ownership if authenticated user has 'Manage portal' permission
-#   def manage_pasteObjects(self, cb_copy_data=None, REQUEST=None):
-#       """Paste previously copied objects into the current object.
-#
-#       If calling manage_pasteObjects from python code, pass the result of a
-#       previous call to manage_cutObjects or manage_copyObjects as the first
-#       argument.
-#
-#       Also sends IObjectCopiedEvent and IObjectClonedEvent
-#       or IObjectWillBeMovedEvent and IObjectMovedEvent.
-#       """
-#       if cb_copy_data is not None:
-#           cp = cb_copy_data
-#       elif REQUEST is not None and REQUEST.has_key('__cp'):
-#           cp = REQUEST['__cp']
-#       else:
-#           cp = None
-#       if cp is None:
-#           raise CopyError, eNoData
-#
-#       try:
-#           op, mdatas = _cb_decode(cp)
-#       except:
-#           raise CopyError, eInvalid
-#
-#       oblist = []
-#       app = self.getPhysicalRoot()
-#       for mdata in mdatas:
-#           m = Moniker.loadMoniker(mdata)
-#           try:
-#               ob = m.bind(app)
-#           except ConflictError:
-#               raise
-#           except:
-#               raise CopyError, eNotFound
-#           self._verifyObjectPaste(ob, validate_src=op+1)
-#           oblist.append(ob)
-#
-#       result = []
-#       if op == 0:
-#           # Copy operation
-#           mtool = getToolByName(self, 'portal_membership')
-#           utool = getToolByName(self, 'portal_url')
-#           portal = utool.getPortalObject()
-#           userIsPortalManager = mtool.checkPermission(ManagePortal, portal)
-#
-#           for ob in oblist:
-#               orig_id = ob.getId()
-#               if not ob.cb_isCopyable():
-#                   raise CopyError, eNotSupported % escape(orig_id)
-#
-#               try:
-#                   ob._notifyOfCopyTo(self, op=0)
-#               except ConflictError:
-#                   raise
-#               except:
-#                   raise CopyError, MessageDialog(
-#                       title="Copy Error",
-#                       message=sys.exc_info()[1],
-#                       action='manage_main')
-#
-#               id = self._get_id(orig_id)
-#               result.append({'id': orig_id, 'new_id': id})
-#
-#               orig_ob = ob
-#               ob = ob._getCopy(self)
-#               ob._setId(id)
-#               notify(ObjectCopiedEvent(ob, orig_ob))
-#               
-#               if not userIsPortalManager :
-#                   self._setObject(id, ob, suppress_events=True)
-#               else :
-#                   self._setObject(id, ob, suppress_events=True, set_owner=0)
-#               ob = self._getOb(id)
-#               ob.wl_clearLocks()
-#
-#               ob._postCopy(self, op=0)
-#
-#               OFS.subscribers.compatibilityCall('manage_afterClone', ob, ob)
-#
-#               notify(ObjectClonedEvent(ob))
-#
-#           if REQUEST is not None:
-#               return self.manage_main(self, REQUEST, update_menu=1,
-#                                       cb_dataValid=1)
-#
-#       elif op == 1:
-#           # Move operation
-#           for ob in oblist:
-#               orig_id = ob.getId()
-#               if not ob.cb_isMoveable():
-#                   raise CopyError, eNotSupported % escape(orig_id)
-#
-#               try:
-#                   ob._notifyOfCopyTo(self, op=1)
-#               except ConflictError:
-#                   raise
-#               except:
-#                   raise CopyError, MessageDialog(
-#                       title="Move Error",
-#                       message=sys.exc_info()[1],
-#                       action='manage_main')
-#
-#               if not sanity_check(self, ob):
-#                   raise CopyError, "This object cannot be pasted into itself"
-#
-#               orig_container = aq_parent(aq_inner(ob))
-#               if aq_base(orig_container) is aq_base(self):
-#                   id = orig_id
-#               else:
-#                   id = self._get_id(orig_id)
-#               result.append({'id': orig_id, 'new_id': id})
-#
-#               notify(ObjectWillBeMovedEvent(ob, orig_container, orig_id,
-#                                             self, id))
-#
-#               # try to make ownership explicit so that it gets carried
-#               # along to the new location if needed.
-#               ob.manage_changeOwnershipType(explicit=1)
-#
-#               try:
-#                   orig_container._delObject(orig_id, suppress_events=True)
-#               except TypeError:
-#                   orig_container._delObject(orig_id)
-#                   warnings.warn(
-#                       "%s._delObject without suppress_events is discouraged."
-#                       % orig_container.__class__.__name__,
-#                       DeprecationWarning)
-#               ob = aq_base(ob)
-#               ob._setId(id)
-#
-#               try:
-#                   self._setObject(id, ob, set_owner=0, suppress_events=True)
-#               except TypeError:
-#                   self._setObject(id, ob, set_owner=0)
-#                   warnings.warn(
-#                       "%s._setObject without suppress_events is discouraged."
-#                       % self.__class__.__name__, DeprecationWarning)
-#               ob = self._getOb(id)
-#
-#               notify(ObjectMovedEvent(ob, orig_container, orig_id, self, id))
-#               notifyContainerModified(orig_container)
-#               if aq_base(orig_container) is not aq_base(self):
-#                   notifyContainerModified(self)
-#
-#               ob._postCopy(self, op=1)
-#               # try to make ownership implicit if possible
-#               ob.manage_changeOwnershipType(explicit=0)
-#
-#           if REQUEST is not None:
-#               REQUEST['RESPONSE'].setCookie('__cp', 'deleted',
-#                                   path='%s' % cookie_path(REQUEST),
-#                                   expires='Wed, 31-Dec-97 23:59:59 GMT')
-#               REQUEST['__cp'] = None
-#               return self.manage_main(self, REQUEST, update_menu=1,
-#                                       cb_dataValid=0)
-#
-#       return result
-
-        
-InitializeClass(PlinnFolder)
-PlinnFolderFactory = Factory(PlinnFolder)
-
-def _getDeepObjects(self, ctool, o, filter={}):
-    res = ctool.unrestrictedSearchResults(path = '/'.join(o.getPhysicalPath()), **filter)
-    
-    if not res :
-        return []
-    else :
-        deepObjects = []
-        res = list(res)
-        res.sort(lambda a, b: cmp(a.getPath(), b.getPath()))
-        previousPath = res[0].getPath()
-
-        deepObjects.append(res[0].getObject())
-        for b in res[1:] :
-            currentPath = b.getPath()
-            if currentPath.startswith(previousPath) and len(currentPath) > len(previousPath):
-                continue
-            else :
-                deepObjects.append(b.getObject())
-                previousPath = currentPath
-
-        return deepObjects
-
-
-manage_addPlinnFolder = PlinnFolder.manage_addPlinnFolder.im_func