Пример #1
0
    def MKCOL(self, REQUEST, RESPONSE):
        """Create a new collection resource."""
        self.dav__init(REQUEST, RESPONSE)
        if REQUEST.get('BODY', ''):
            raise UnsupportedMediaType, 'Unknown request body.'

        name=self.__name__
        parent = self.__parent__

        if hasattr(aq_base(parent), name):
            raise MethodNotAllowed, 'The name %s is in use.' % name
        if not isDavCollection(parent):
            raise Forbidden, 'Cannot create collection at this location.'

        ifhdr = REQUEST.get_header('If', '')
        if IWriteLock.providedBy(parent) and parent.wl_isLocked():
            if ifhdr:
                parent.dav__simpleifhandler(REQUEST, RESPONSE, col=1)
            else:
                raise Locked
        elif ifhdr:
            # There was an If header, but the parent is not locked
            raise PreconditionFailed

        # Add hook for webdav/FTP MKCOL (Collector #2254) (needed for CMF)
#       parent.manage_addFolder(name)
        mkcol_handler = getattr(parent,'MKCOL_handler' ,parent.manage_addFolder)
        mkcol_handler(name)

        RESPONSE.setStatus(201)
        RESPONSE.setBody('')
        return RESPONSE
Пример #2
0
    def apply(self, obj, token, sm, url=None, result=None, top=1):
        if result is None:
            result = StringIO()
            url = urlfix(url, 'DELETE')
            url = urlbase(url)
        iscol = isDavCollection(obj)
        errmsg = None
        parent = aq_parent(obj)

        islockable = IWriteLock.providedBy(obj)
        if parent and (not sm.checkPermission(delete_objects, parent)):
            # User doesn't have permission to delete this object
            errmsg = "403 Forbidden"
        elif islockable and obj.wl_isLocked():
            if token and obj.wl_hasLock(token):
                # Object is locked, and the token matches (no error)
                errmsg = ""
            else:
                errmsg = "423 Locked"

        if errmsg:
            if top and (not iscol):
                if errmsg == "403 Forbidden":
                    raise Forbidden()
                if errmsg == "423 Locked":
                    raise Locked()
            elif not result.getvalue():
                # We haven't had any errors yet, so our result is empty
                # and we need to set up the XML header
                result.write('<?xml version="1.0" encoding="utf-8" ?>\n' \
                             '<d:multistatus xmlns:d="DAV:">\n')
            result.write('<d:response>\n <d:href>%s</d:href>\n' % url)
            result.write(' <d:status>HTTP/1.1 %s</d:status>\n' % errmsg)
            result.write('</d:response>\n')

        if iscol:
            for ob in obj.objectValues():
                dflag = hasattr(ob,'_p_changed') and (ob._p_changed == None)
                if hasattr(ob, '__dav_resource__'):
                    uri = urljoin(url, absattr(ob.getId()))
                    self.apply(ob, token, sm, uri, result, top=0)
                    if dflag:
                        ob._p_deactivate()
        if not top:
            return result
        if result.getvalue():
            # One or more subitems can't be delted, so close the multistatus
            # element
            result.write('</d:multistatus>\n')
        return result.getvalue()
Пример #3
0
    def COPY(self, REQUEST, RESPONSE):
        """Create a duplicate of the source resource whose state
        and behavior match that of the source resource as closely
        as possible. Though we may later try to make a copy appear
        seamless across namespaces (e.g. from Zope to Apache), COPY
        is currently only supported within the Zope namespace."""
        self.dav__init(REQUEST, RESPONSE)
        if not hasattr(aq_base(self), 'cb_isCopyable') or \
           not self.cb_isCopyable():
            raise MethodNotAllowed, 'This object may not be copied.'

        depth=REQUEST.get_header('Depth', 'infinity')
        if not depth in ('0', 'infinity'):
            raise BadRequest, 'Invalid Depth header.'

        dest=REQUEST.get_header('Destination', '')
        while dest and dest[-1]=='/':
            dest=dest[:-1]
        if not dest:
            raise BadRequest, 'Invalid Destination header.'

        try: path = REQUEST.physicalPathFromURL(dest)
        except ValueError:
            raise BadRequest, 'Invalid Destination header'

        name = path.pop()

        oflag=REQUEST.get_header('Overwrite', 'F').upper()
        if not oflag in ('T', 'F'):
            raise BadRequest, 'Invalid Overwrite header.'

        try: parent=self.restrictedTraverse(path)
        except ValueError:
            raise Conflict, 'Attempt to copy to an unknown namespace.'
        except NotFound:
            raise Conflict, 'Object ancestors must already exist.'
        except:
            t, v, tb=sys.exc_info()
            raise t, v
        if hasattr(parent, '__null_resource__'):
            raise Conflict, 'Object ancestors must already exist.'
        existing=hasattr(aq_base(parent), name)
        if existing and oflag=='F':
            raise PreconditionFailed, 'Destination resource exists.'
        try:
            parent._checkId(name, allow_dup=1)
        except:
            raise Forbidden, sys.exc_info()[1]
        try:
            parent._verifyObjectPaste(self)
        except Unauthorized:
            raise
        except:
            raise Forbidden, sys.exc_info()[1]

        # Now check locks.  The If header on a copy only cares about the
        # lock on the destination, so we need to check out the destinations
        # lock status.
        ifhdr = REQUEST.get_header('If', '')
        if existing:
            # The destination itself exists, so we need to check its locks
            destob = aq_base(parent)._getOb(name)
            if IWriteLock.providedBy(destob) and destob.wl_isLocked():
                if ifhdr:
                    itrue = destob.dav__simpleifhandler(
                        REQUEST, RESPONSE, 'COPY', refresh=1)
                    if not itrue:
                        raise PreconditonFailed
                else:
                    raise Locked, 'Destination is locked.'
        elif IWriteLock.providedBy(parent) and parent.wl_isLocked():
            if ifhdr:
                parent.dav__simpleifhandler(REQUEST, RESPONSE, 'COPY',
                                            refresh=1)
            else:
                raise Locked, 'Destination is locked.'

        self._notifyOfCopyTo(parent, op=0)
        ob = self._getCopy(parent)
        ob._setId(name)

        if depth=='0' and isDavCollection(ob):
            for id in ob.objectIds():
                ob._delObject(id)

        notify(ObjectCopiedEvent(ob, self))

        if existing:
            object=getattr(parent, name)
            self.dav__validate(object, 'DELETE', REQUEST)
            parent._delObject(name)

        parent._setObject(name, ob)
        ob = parent._getOb(name)
        ob._postCopy(parent, op=0)

        compatibilityCall('manage_afterClone', ob, ob)

        notify(ObjectClonedEvent(ob))

        # We remove any locks from the copied object because webdav clients
        # don't track the lock status and the lock token for copied resources
        ob.wl_clearLocks()
        RESPONSE.setStatus(existing and 204 or 201)
        if not existing:
            RESPONSE.setHeader('Location', dest)
        RESPONSE.setBody('')
        return RESPONSE
Пример #4
0
 def dav__resourcetype(self):
     vself=self.v_self()
     if isDavCollection(vself):
         return '<n:collection/>'
     return ''
Пример #5
0
 def dav__resourcetype(self):
     vself=self.v_self()
     if (isDavCollection(vself) or
         getattr(aq_base(vself), 'isAnObjectManager', None)):
         return '<n:collection/>'
     return ''
Пример #6
0
    def COPY(self, REQUEST, RESPONSE):
        """Create a duplicate of the source resource whose state
        and behavior match that of the source resource as closely
        as possible. Though we may later try to make a copy appear
        seamless across namespaces (e.g. from Zope to Apache), COPY
        is currently only supported within the Zope namespace."""
        self.dav__init(REQUEST, RESPONSE)
        if not hasattr(aq_base(self), 'cb_isCopyable') or \
           not self.cb_isCopyable():
            raise MethodNotAllowed, 'This object may not be copied.'

        depth = REQUEST.get_header('Depth', 'infinity')
        if not depth in ('0', 'infinity'):
            raise BadRequest, 'Invalid Depth header.'

        dest = REQUEST.get_header('Destination', '')
        while dest and dest[-1] == '/':
            dest = dest[:-1]
        if not dest:
            raise BadRequest, 'Invalid Destination header.'

        try:
            path = REQUEST.physicalPathFromURL(dest)
        except ValueError:
            raise BadRequest, 'Invalid Destination header'

        name = path.pop()

        oflag = REQUEST.get_header('Overwrite', 'F').upper()
        if not oflag in ('T', 'F'):
            raise BadRequest, 'Invalid Overwrite header.'

        try:
            parent = self.restrictedTraverse(path)
        except ValueError:
            raise Conflict, 'Attempt to copy to an unknown namespace.'
        except NotFound:
            raise Conflict, 'Object ancestors must already exist.'
        except:
            t, v, tb = sys.exc_info()
            raise t, v
        if hasattr(parent, '__null_resource__'):
            raise Conflict, 'Object ancestors must already exist.'
        existing = hasattr(aq_base(parent), name)
        if existing and oflag == 'F':
            raise PreconditionFailed, 'Destination resource exists.'
        try:
            parent._checkId(name, allow_dup=1)
        except:
            raise Forbidden, sys.exc_info()[1]
        try:
            parent._verifyObjectPaste(self)
        except Unauthorized:
            raise
        except:
            raise Forbidden, sys.exc_info()[1]

        # Now check locks.  The If header on a copy only cares about the
        # lock on the destination, so we need to check out the destinations
        # lock status.
        ifhdr = REQUEST.get_header('If', '')
        if existing:
            # The destination itself exists, so we need to check its locks
            destob = aq_base(parent)._getOb(name)
            if IWriteLock.providedBy(destob) and destob.wl_isLocked():
                if ifhdr:
                    itrue = destob.dav__simpleifhandler(REQUEST,
                                                        RESPONSE,
                                                        'COPY',
                                                        refresh=1)
                    if not itrue:
                        raise PreconditonFailed
                else:
                    raise Locked, 'Destination is locked.'
        elif IWriteLock.providedBy(parent) and parent.wl_isLocked():
            if ifhdr:
                parent.dav__simpleifhandler(REQUEST,
                                            RESPONSE,
                                            'COPY',
                                            refresh=1)
            else:
                raise Locked, 'Destination is locked.'

        self._notifyOfCopyTo(parent, op=0)
        ob = self._getCopy(parent)
        ob._setId(name)

        if depth == '0' and isDavCollection(ob):
            for id in ob.objectIds():
                ob._delObject(id)

        notify(ObjectCopiedEvent(ob, self))

        if existing:
            object = getattr(parent, name)
            self.dav__validate(object, 'DELETE', REQUEST)
            parent._delObject(name)

        parent._setObject(name, ob)
        ob = parent._getOb(name)
        ob._postCopy(parent, op=0)

        compatibilityCall('manage_afterClone', ob, ob)

        notify(ObjectClonedEvent(ob))

        # We remove any locks from the copied object because webdav clients
        # don't track the lock status and the lock token for copied resources
        ob.wl_clearLocks()
        RESPONSE.setStatus(existing and 204 or 201)
        if not existing:
            RESPONSE.setHeader('Location', dest)
        RESPONSE.setBody('')
        return RESPONSE
Пример #7
0
 def dav__resourcetype(self):
     vself = self.v_self()
     if isDavCollection(vself):
         return '<n:collection/>'
     return ''
Пример #8
0
    def apply(self, obj, token, url=None, result=None, top=1):
        if result is None:
            result = StringIO()
            url = urlfix(url, 'UNLOCK')
            url = urlbase(url)
        iscol = isDavCollection(obj)
        if iscol and url[-1] != '/':
            url = url + '/'
        errmsg = None

        islockable = IWriteLock.providedBy(obj)

        if islockable:
            if obj.wl_hasLock(token):
                method = getattr(obj, 'wl_delLock')
                vld = getSecurityManager().validate(None,obj,
                                                    'wl_delLock',method)
                if vld:
                    obj.wl_delLock(token)
                else:
                    errmsg = "403 Forbidden"
            else:
                errmsg = '400 Bad Request'
        else:
            # Only set an error message if the command is being applied
            # to a top level object.  Otherwise, we're descending a tree
            # which may contain many objects that don't implement locking,
            # so we just want to avoid them
            if top:
                errmsg = "405 Method Not Allowed"

        if errmsg:
            if top and (not iscol):
                # We don't need to raise multistatus errors
                if errmsg[:3] == '403':
                    raise Forbidden
                else:
                    raise PreconditionFailed
            elif not result.getvalue():
                # We haven't had any errors yet, so our result is empty
                # and we need to set up the XML header
                result.write('<?xml version="1.0" encoding="utf-8" ?>\n' \
                             '<d:multistatus xmlns:d="DAV:">\n')
            result.write('<d:response>\n <d:href>%s</d:href>\n' % url)
            result.write(' <d:status>HTTP/1.1 %s</d:status>\n' % errmsg)
            result.write('</d:response>\n')

        if iscol:
            for ob in obj.objectValues():
                if hasattr(ob, '__dav_resource__') and \
                        IWriteLock.providedBy(ob):
                    uri = urljoin(url, absattr(ob.getId()))
                    self.apply(ob, token, uri, result, top=0)
        if not top:
            return result
        if result.getvalue():
            # One or more subitems probably failed, so close the multistatus
            # element and clear out all succesful unlocks
            result.write('</d:multistatus>')
            transaction.abort()
        return result.getvalue()
Пример #9
0
    def apply(self, obj, creator=None, depth='infinity', token=None,
              result=None, url=None, top=1):
        """ Apply, built for recursion (so that we may lock subitems
        of a collection if requested """

        if result is None:
            result = StringIO()
            url = urlfix(self.request['URL'], 'LOCK')
            url = urlbase(url)
        iscol = isDavCollection(obj)
        if iscol and url[-1] != '/':
            url = url + '/'
        errmsg = None
        lock = None

        try:
            lock = LockItem(creator, self.owner, depth, self.timeout,
                            self.type, self.scope, token)
            if token is None:
                token = lock.getLockToken()

        except ValueError:
            errmsg = "412 Precondition Failed"
        except:
            errmsg = "403 Forbidden"

        try:
            if not IWriteLock.providedBy(obj):
                if top:
                    # This is the top level object in the apply, so we
                    # do want an error
                    errmsg = "405 Method Not Allowed"
                else:
                    # We're in an infinity request and a subobject does
                    # not support locking, so we'll just pass
                    pass
            elif obj.wl_isLocked():
                errmsg = "423 Locked"
            else:
                method = getattr(obj, 'wl_setLock')
                vld = getSecurityManager().validate(None, obj, 'wl_setLock',
                                                    method)
                if vld and token and (lock is not None):
                    obj.wl_setLock(token, lock)
                else:
                    errmsg = "403 Forbidden"
        except:
            errmsg = "403 Forbidden"

        if errmsg:
            if top and ((depth in (0, '0')) or (not iscol)):
                # We don't need to raise multistatus errors
                raise errmsg[4:]
            elif not result.getvalue():
                # We haven't had any errors yet, so our result is empty
                # and we need to set up the XML header
                result.write('<?xml version="1.0" encoding="utf-8" ?>\n' \
                             '<d:multistatus xmlns:d="DAV:">\n')
            result.write('<d:response>\n <d:href>%s</d:href>\n' % url)
            result.write(' <d:status>HTTP/1.1 %s</d:status>\n' % errmsg)
            result.write('</d:response>\n')

        if depth == 'infinity' and iscol:
            for ob in obj.objectValues():
                if hasattr(obj, '__dav_resource__'):
                    uri = urljoin(url, absattr(ob.getId()))
                    self.apply(ob, creator, depth, token, result,
                               uri, top=0)
        if not top:
            return token, result
        if result.getvalue():
            # One or more subitems probably failed, so close the multistatus
            # element and clear out all succesful locks
            result.write('</d:multistatus>')
            transaction.abort() # This *SHOULD* clear all succesful locks
        return token, result.getvalue()
Пример #10
0
 def apply(self, obj):
     url=urlfix(self.request['URL'], 'PROPPATCH')
     if isDavCollection(obj):
         url=url+'/'
     result=StringIO()
     errors=[]
     result.write('<?xml version="1.0" encoding="utf-8"?>\n' \
                  '<d:multistatus xmlns:d="DAV:">\n' \
                  '<d:response>\n' \
                  '<d:href>%s</d:href>\n' % quote(url))
     propsets=obj.propertysheets
     for value in self.values:
         status='200 OK'
         if len(value) > 2:
             name, ns, val, md=value
             propset=propsets.get(ns, None)
             if propset is None:
                 propsets.manage_addPropertySheet('', ns)
                 propset=propsets.get(ns)
             if propset.hasProperty(name):
                 try:
                     propset._updateProperty(name, val, meta=md)
                 except:
                     errors.append(str(sys.exc_info()[1]))
                     status='409 Conflict'
             else:
                 try:
                     propset._setProperty(name, val, meta=md)
                 except:
                     errors.append(str(sys.exc_info()[1]))
                     status='409 Conflict'
         else:
             name, ns=value
             propset=propsets.get(ns, None)
             if propset is None or not propset.hasProperty(name):
                 # removing a non-existing property is not an error!
                 # according to RFC 2518
                 status='200 OK'
             else:
                 try:
                     propset._delProperty(name)
                 except:
                     errors.append('%s cannot be deleted.' % name)
                     status='409 Conflict'
         result.write('<d:propstat xmlns:n="%s">\n' \
                      '  <d:prop>\n' \
                      '  <n:%s/>\n' \
                      '  </d:prop>\n' \
                      '  <d:status>HTTP/1.1 %s</d:status>\n' \
                      '</d:propstat>\n' % (ns, name, status))
     errmsg='\n'.join(errors) or 'The operation succeded.'
     result.write('<d:responsedescription>\n' \
                  '%s\n' \
                  '</d:responsedescription>\n' \
                  '</d:response>\n' \
                  '</d:multistatus>' % errmsg)
     result=result.getvalue()
     if not errors:
         return result
     # This is lame, but I cant find a way to keep ZPublisher
     # from sticking a traceback into my xml response :(
     transaction.abort()
     result=result.replace( '200 OK', '424 Failed Dependency')
     return result
Пример #11
0
    def apply(self, obj, url=None, depth=0, result=None, top=1):
        if result is None:
            result=StringIO()
            depth=self.depth
            url=urlfix(self.request['URL'], 'PROPFIND')
            url=urlbase(url)
            result.write('<?xml version="1.0" encoding="utf-8"?>\n' \
                         '<d:multistatus xmlns:d="DAV:">\n')
        iscol=isDavCollection(obj)
        if iscol and url[-1] != '/': url=url+'/'
        result.write('<d:response>\n<d:href>%s</d:href>\n' % safe_quote(url))
        if hasattr(aq_base(obj), 'propertysheets'):
            propsets=obj.propertysheets.values()
            obsheets=obj.propertysheets
        else:
            davprops=DAVProps(obj)
            propsets=(davprops,)
            obsheets={'DAV:': davprops}
        if self.allprop:
            stats=[]
            for ps in propsets:
                if hasattr(aq_base(ps), 'dav__allprop'):
                    stats.append(ps.dav__allprop())
            stats=''.join(stats) or '<d:status>200 OK</d:status>\n'
            result.write(stats)
        elif self.propname:
            stats=[]
            for ps in propsets:
                if hasattr(aq_base(ps), 'dav__propnames'):
                    stats.append(ps.dav__propnames())
            stats=''.join(stats) or '<d:status>200 OK</d:status>\n'
            result.write(stats)
        elif self.propnames:
            rdict={}
            for name, ns in self.propnames:
                ps=obsheets.get(ns, None)
                if ps is not None and hasattr(aq_base(ps), 'dav__propstat'):
                    stat=ps.dav__propstat(name, rdict)
                else:
                    prop='<n:%s xmlns:n="%s"/>' % (name, ns)
                    code='404 Not Found'
                    if not rdict.has_key(code):
                        rdict[code]=[prop]
                    else:
                        rdict[code].append(prop)
            keys=rdict.keys()
            keys.sort()
            for key in keys:
                result.write('<d:propstat>\n' \
                             '  <d:prop>\n' \
                             )
                map(result.write, rdict[key])
                result.write('  </d:prop>\n' \
                             '  <d:status>HTTP/1.1 %s</d:status>\n' \
                             '</d:propstat>\n' % key
                             )
        else:
            raise BadRequest, 'Invalid request'
        result.write('</d:response>\n')
        if depth in ('1', 'infinity') and iscol:
            for ob in obj.listDAVObjects():
                if hasattr(ob,"meta_type"):
                    if ob.meta_type=="Broken Because Product is Gone":
                        continue
                dflag=hasattr(ob, '_p_changed') and (ob._p_changed == None)
                if hasattr(ob, '__locknull_resource__'):
                    # Do nothing, a null resource shouldn't show up to DAV
                    if dflag:
                        ob._p_deactivate()
                elif hasattr(ob, '__dav_resource__'):
                    uri = urljoin(url, absattr(ob.getId()))
                    depth = depth=='infinity' and depth or 0
                    self.apply(ob, uri, depth, result, top=0)
                    if dflag:
                        ob._p_deactivate()
        if not top:
            return result
        result.write('</d:multistatus>')

        return result.getvalue()
Пример #12
0
    def apply(self, obj, token, url=None, result=None, top=1):
        if result is None:
            result = StringIO()
            url = urlfix(url, 'UNLOCK')
            url = urlbase(url)
        iscol = isDavCollection(obj)
        if iscol and url[-1] != '/':
            url = url + '/'
        errmsg = None

        islockable = IWriteLock.providedBy(obj)

        if islockable:
            if obj.wl_hasLock(token):
                method = getattr(obj, 'wl_delLock')
                vld = getSecurityManager().validate(None,obj,
                                                    'wl_delLock',method)
                if vld:
                    obj.wl_delLock(token)
                else:
                    errmsg = "403 Forbidden"
            else:
                errmsg = '400 Bad Request'
        else:
            # Only set an error message if the command is being applied
            # to a top level object.  Otherwise, we're descending a tree
            # which may contain many objects that don't implement locking,
            # so we just want to avoid them
            if top:
                errmsg = "405 Method Not Allowed"

        if errmsg:
            if top and (not iscol):
                # We don't need to raise multistatus errors
                if errmsg[:3] == '403':
                    raise Forbidden
                else:
                    raise PreconditionFailed
            elif not result.getvalue():
                # We haven't had any errors yet, so our result is empty
                # and we need to set up the XML header
                result.write('<?xml version="1.0" encoding="utf-8" ?>\n' \
                             '<d:multistatus xmlns:d="DAV:">\n')
            result.write('<d:response>\n <d:href>%s</d:href>\n' % url)
            result.write(' <d:status>HTTP/1.1 %s</d:status>\n' % errmsg)
            result.write('</d:response>\n')

        if iscol:
            for ob in obj.objectValues():
                if hasattr(ob, '__dav_resource__') and \
                        IWriteLock.providedBy(ob):
                    uri = urljoin(url, absattr(ob.getId()))
                    self.apply(ob, token, uri, result, top=0)
        if not top:
            return result
        if result.getvalue():
            # One or more subitems probably failed, so close the multistatus
            # element and clear out all succesful unlocks
            result.write('</d:multistatus>')
            transaction.abort()
        return result.getvalue()
Пример #13
0
    def apply(self, obj, creator=None, depth='infinity', token=None,
              result=None, url=None, top=1):
        """ Apply, built for recursion (so that we may lock subitems
        of a collection if requested """

        if result is None:
            result = StringIO()
            url = urlfix(self.request['URL'], 'LOCK')
            url = urlbase(url)
        iscol = isDavCollection(obj)
        if iscol and url[-1] != '/':
            url = url + '/'
        errmsg = None
        lock = None

        try:
            lock = LockItem(creator, self.owner, depth, self.timeout,
                            self.type, self.scope, token)
            if token is None:
                token = lock.getLockToken()

        except ValueError:
            errmsg = "412 Precondition Failed"
        except:
            errmsg = "403 Forbidden"

        try:
            if not IWriteLock.providedBy(obj):
                if top:
                    # This is the top level object in the apply, so we
                    # do want an error
                    errmsg = "405 Method Not Allowed"
                else:
                    # We're in an infinity request and a subobject does
                    # not support locking, so we'll just pass
                    pass
            elif obj.wl_isLocked():
                errmsg = "423 Locked"
            else:
                method = getattr(obj, 'wl_setLock')
                vld = getSecurityManager().validate(None, obj, 'wl_setLock',
                                                    method)
                if vld and token and (lock is not None):
                    obj.wl_setLock(token, lock)
                else:
                    errmsg = "403 Forbidden"
        except:
            errmsg = "403 Forbidden"

        if errmsg:
            if top and ((depth in (0, '0')) or (not iscol)):
                # We don't need to raise multistatus errors
                raise errmsg[4:]
            elif not result.getvalue():
                # We haven't had any errors yet, so our result is empty
                # and we need to set up the XML header
                result.write('<?xml version="1.0" encoding="utf-8" ?>\n' \
                             '<d:multistatus xmlns:d="DAV:">\n')
            result.write('<d:response>\n <d:href>%s</d:href>\n' % url)
            result.write(' <d:status>HTTP/1.1 %s</d:status>\n' % errmsg)
            result.write('</d:response>\n')

        if depth == 'infinity' and iscol:
            for ob in obj.objectValues():
                if hasattr(obj, '__dav_resource__'):
                    uri = urljoin(url, absattr(ob.getId()))
                    self.apply(ob, creator, depth, token, result,
                               uri, top=0)
        if not top:
            return token, result
        if result.getvalue():
            # One or more subitems probably failed, so close the multistatus
            # element and clear out all succesful locks
            result.write('</d:multistatus>')
            transaction.abort() # This *SHOULD* clear all succesful locks
        return token, result.getvalue()
Пример #14
0
 def apply(self, obj):
     url=urlfix(self.request['URL'], 'PROPPATCH')
     if isDavCollection(obj):
         url=url+'/'
     result=StringIO()
     errors=[]
     result.write('<?xml version="1.0" encoding="utf-8"?>\n' \
                  '<d:multistatus xmlns:d="DAV:">\n' \
                  '<d:response>\n' \
                  '<d:href>%s</d:href>\n' % quote(url))
     propsets=obj.propertysheets
     for value in self.values:
         status='200 OK'
         if len(value) > 2:
             name, ns, val, md=value
             propset=propsets.get(ns, None)
             if propset is None:
                 propsets.manage_addPropertySheet('', ns)
                 propset=propsets.get(ns)
             if propset.hasProperty(name):
                 try:
                     propset._updateProperty(name, val, meta=md)
                 except:
                     errors.append(str(sys.exc_info()[1]))
                     status='409 Conflict'
             else:
                 try:
                     propset._setProperty(name, val, meta=md)
                 except:
                     errors.append(str(sys.exc_info()[1]))
                     status='409 Conflict'
         else:
             name, ns=value
             propset=propsets.get(ns, None)
             if propset is None or not propset.hasProperty(name):
                 # removing a non-existing property is not an error!
                 # according to RFC 2518
                 status='200 OK'
             else:
                 try:
                     propset._delProperty(name)
                 except:
                     errors.append('%s cannot be deleted.' % name)
                     status='409 Conflict'
         result.write('<d:propstat xmlns:n="%s">\n' \
                      '  <d:prop>\n' \
                      '  <n:%s/>\n' \
                      '  </d:prop>\n' \
                      '  <d:status>HTTP/1.1 %s</d:status>\n' \
                      '</d:propstat>\n' % (ns, name, status))
     errmsg='\n'.join(errors) or 'The operation succeded.'
     result.write('<d:responsedescription>\n' \
                  '%s\n' \
                  '</d:responsedescription>\n' \
                  '</d:response>\n' \
                  '</d:multistatus>' % errmsg)
     result=result.getvalue()
     if not errors:
         return result
     # This is lame, but I cant find a way to keep ZPublisher
     # from sticking a traceback into my xml response :(
     transaction.abort()
     result=result.replace( '200 OK', '424 Failed Dependency')
     return result
Пример #15
0
    def apply(self, obj, url=None, depth=0, result=None, top=1):
        if result is None:
            result=StringIO()
            depth=self.depth
            url=urlfix(self.request['URL'], 'PROPFIND')
            url=urlbase(url)
            result.write('<?xml version="1.0" encoding="utf-8"?>\n' \
                         '<d:multistatus xmlns:d="DAV:">\n')
        iscol=isDavCollection(obj)
        if iscol and url[-1] != '/': url=url+'/'
        result.write('<d:response>\n<d:href>%s</d:href>\n' % safe_quote(url))
        if hasattr(aq_base(obj), 'propertysheets'):
            propsets=obj.propertysheets.values()
            obsheets=obj.propertysheets
        else:
            davprops=DAVProps(obj)
            propsets=(davprops,)
            obsheets={'DAV:': davprops}
        if self.allprop:
            stats=[]
            for ps in propsets:
                if hasattr(aq_base(ps), 'dav__allprop'):
                    stats.append(ps.dav__allprop())
            stats=''.join(stats) or '<d:status>200 OK</d:status>\n'
            result.write(stats)
        elif self.propname:
            stats=[]
            for ps in propsets:
                if hasattr(aq_base(ps), 'dav__propnames'):
                    stats.append(ps.dav__propnames())
            stats=''.join(stats) or '<d:status>200 OK</d:status>\n'
            result.write(stats)
        elif self.propnames:
            rdict={}
            for name, ns in self.propnames:
                ps=obsheets.get(ns, None)
                if ps is not None and hasattr(aq_base(ps), 'dav__propstat'):
                    stat=ps.dav__propstat(name, rdict)
                else:
                    prop='<n:%s xmlns:n="%s"/>' % (name, ns)
                    code='404 Not Found'
                    if not rdict.has_key(code):
                        rdict[code]=[prop]
                    else:
                        rdict[code].append(prop)
            keys=rdict.keys()
            keys.sort()
            for key in keys:
                result.write('<d:propstat>\n' \
                             '  <d:prop>\n' \
                             )
                map(result.write, rdict[key])
                result.write('  </d:prop>\n' \
                             '  <d:status>HTTP/1.1 %s</d:status>\n' \
                             '</d:propstat>\n' % key
                             )
        else:
            raise BadRequest, 'Invalid request'
        result.write('</d:response>\n')
        if depth in ('1', 'infinity') and iscol:
            for ob in obj.listDAVObjects():
                if hasattr(ob,"meta_type"):
                    if ob.meta_type=="Broken Because Product is Gone":
                        continue
                dflag=hasattr(ob, '_p_changed') and (ob._p_changed == None)
                if hasattr(ob, '__locknull_resource__'):
                    # Do nothing, a null resource shouldn't show up to DAV
                    if dflag:
                        ob._p_deactivate()
                elif hasattr(ob, '__dav_resource__'):
                    uri = urljoin(url, absattr(ob.getId()))
                    depth = depth=='infinity' and depth or 0
                    self.apply(ob, uri, depth, result, top=0)
                    if dflag:
                        ob._p_deactivate()
        if not top:
            return result
        result.write('</d:multistatus>')

        return result.getvalue()