Esempio n. 1
0
 def PUT(self, REQUEST, RESPONSE):
     """The PUT method has no inherent meaning for collection
     resources, though collections are not specifically forbidden
     to handle PUT requests. The default response to a PUT request
     for collections is 405 (Method Not Allowed)."""
     self.dav__init(REQUEST, RESPONSE)
     raise MethodNotAllowed('Method not supported for collections.')
Esempio n. 2
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 MKCOL (Collector #2254) (needed for CMF)
        mkcol_handler = getattr(parent, 'MKCOL_handler',
                                parent.manage_addFolder)
        mkcol_handler(name)

        RESPONSE.setStatus(201)
        RESPONSE.setBody('')
        return RESPONSE
Esempio n. 3
0
 def __call__(self):
     if self.request.method != 'POST':
         raise MethodNotAllowed()
     if not IAnnotations(
             self.context)[PDF_SAVE_TOKEN_KEY] == self.get_opaque_id():
         raise Unauthorized
     return super(ReceiveDocumentPDF, self).__call__()
Esempio n. 4
0
 def _handleDelete(self):
     adapter = queryMultiAdapter((aq_inner(self.context), self.request),
                                 ISWORDEditIRI)
     if adapter is None:
         raise MethodNotAllowed(
             "Method DELETE is not supported in this context")
     return adapter()
    def __call__(self):
        if self.request.method != 'POST':
            raise MethodNotAllowed()

        self.model = self.context.model
        self.committee = self.model.committee.oguid.resolve_object()

        return super(ReceiveZipPdf, self).__call__()
Esempio n. 6
0
 def PUT(self, REQUEST, RESPONSE):
     """Replace the GET response entity of an existing resource.
     Because this is often object-dependent, objects which handle
     PUT should override the default PUT implementation with an
     object-specific implementation. By default, PUT requests
     fail with a 405 (Method Not Allowed)."""
     self.dav__init(REQUEST, RESPONSE)
     raise MethodNotAllowed('Method not supported for this resource.')
    def PUT(self, REQUEST=None, RESPONSE=None):
        """WebDAV method to replace self with a new resource. This is also
        used when initialising an object just created from a NullResource.

        This will look up an IRawWriteFile adapter on self and write to it,
        line-by-line, from the request body.
        """
        request = REQUEST is not None and REQUEST or self.REQUEST
        response = RESPONSE is not None and RESPONSE or request.response

        self.dav__init(request, response)
        self.dav__simpleifhandler(request, response, refresh=1)

        infile = request.get('BODYFILE', None)
        if infile is None:
            raise MethodNotAllowed(
                "Cannot complete PUT request: No BODYFILE in request")

        writer = IRawWriteFile(self, None)
        if writer is None:
            raise MethodNotAllowed(
                "Cannot complete PUT request: No IRawWriteFile adapter found")

        contentTypeHeader = request.get_header('content-type', None)

        if contentTypeHeader is not None:
            msg = Message()
            msg['Content-Type'] = contentTypeHeader

            mimeType = msg.get_content_type()
            if mimeType is not None:
                writer.mimeType = mimeType

            charset = msg.get_param('charset')
            if charset is not None:
                writer.encoding = charset

        try:
            for chunk in infile:
                writer.write(chunk)
        finally:
            writer.close()

        modified(self)
        return response
 def MKCOL_handler(self, id, REQUEST=None, RESPONSE=None):
     """Handle "make collection" by delegating to an IDirectoryFactory
     adapter.
     """
     factory = IDirectoryFactory(self, None)
     if factory is None:
         raise MethodNotAllowed(
             "Cannot create collection: No IDirectoryFactory adapter found")
     factory(id)
Esempio n. 9
0
 def TRACE(self, REQUEST, RESPONSE):
     """Return the HTTP message received back to the client as the
     entity-body of a 200 (OK) response. This will often usually
     be intercepted by the web server in use. If not, the TRACE
     request will fail with a 405 (Method Not Allowed), since it
     is not often possible to reproduce the HTTP request verbatim
     from within the Zope environment."""
     self.dav__init(REQUEST, RESPONSE)
     raise MethodNotAllowed('Method not supported for this resource.')
Esempio n. 10
0
 def HEAD(self, REQUEST, RESPONSE):
     """Retrieve resource information without a response body."""
     self.dav__init(REQUEST, RESPONSE)
     # Note that we are willing to acquire the default document
     # here because what we really care about is whether doing
     # a GET on this collection / would yield a 200 response.
     if hasattr(self, 'index_html'):
         if hasattr(self.index_html, 'HEAD'):
             return self.index_html.HEAD(REQUEST, RESPONSE)
         raise MethodNotAllowed('Method not supported for this resource.')
     raise NotFound('The requested resource does not exist.')
Esempio n. 11
0
 def _handleGet(self):
     """ Lookup EditIRI adapter, call it to get a deposit receipt. """
     adapter = queryMultiAdapter((aq_inner(self.context), self.request),
                                 ISWORDEditIRI)
     if adapter is None:
         adapter = queryMultiAdapter((self.context, self.request),
                                     ISWORDListCollection)
     if adapter is None:
         raise MethodNotAllowed("Method GET is not supported for %s" % \
                                self.request['PATH_INFO'])
     return adapter._handleGet()
Esempio n. 12
0
 def __call__(self):
     method = self.request.get('REQUEST_METHOD')
     if method == 'POST':
         return self._handlePost()
     elif method == 'GET':
         return self._handleGet()
     elif method == 'PUT':
         return self._handlePut()
     elif method == 'DELETE':
         return self._handleDelete()
     else:
         raise MethodNotAllowed("Method %s not supported" % method)
Esempio n. 13
0
    def PROPPATCH(self, REQUEST, RESPONSE):
        """Set and/or remove properties defined on the resource."""
        from webdav.davcmds import PropPatch
        self.dav__init(REQUEST, RESPONSE)
        if not hasattr(aq_base(self), 'propertysheets'):
            raise MethodNotAllowed('Method not supported for this resource.')
        # Lock checking
        ifhdr = REQUEST.get_header('If', '')
        if wl_isLocked(self):
            if ifhdr:
                self.dav__simpleifhandler(REQUEST, RESPONSE, 'PROPPATCH')
            else:
                raise Locked('Resource is locked.')

        cmd = PropPatch(REQUEST)
        result = cmd.apply(self)
        RESPONSE.setStatus(207)
        RESPONSE.setHeader('Content-Type', 'text/xml; charset="utf-8"')
        RESPONSE.setBody(result)
        return RESPONSE
Esempio n. 14
0
 def MKCOL(self, REQUEST, RESPONSE):
     """Create a new collection resource. If called on an existing
     resource, MKCOL must fail with 405 (Method Not Allowed)."""
     self.dav__init(REQUEST, RESPONSE)
     raise MethodNotAllowed('The resource already exists.')
Esempio n. 15
0
def PUT(self, REQUEST, RESPONSE):
    """
    Disable HTTP PUT for preventing upload to dmd without authentication
    """
    raise MethodNotAllowed('Method not supported for this resource.')
Esempio n. 16
0
    def PUT(self, REQUEST, RESPONSE):
        """ Create a new non-collection resource, deleting the LockNull
        object from the container before putting the new object in. """

        self.dav__init(REQUEST, RESPONSE)
        name = self.__name__
        parent = self.aq_parent
        parenturl = parent.absolute_url()
        ifhdr = REQUEST.get_header('If', '')

        # Since a Lock null resource is always locked by definition, all
        # operations done by an owner of the lock that affect the resource
        # MUST have the If header in the request
        if not ifhdr:
            raise PreconditionFailed('No If-header')

        # First we need to see if the parent of the locknull is locked, and
        # if the user owns that lock (checked by handling the information in
        # the If header).
        if IWriteLock.providedBy(parent) and parent.wl_isLocked():
            itrue = parent.dav__simpleifhandler(REQUEST,
                                                RESPONSE,
                                                'PUT',
                                                col=1,
                                                url=parenturl,
                                                refresh=1)
            if not itrue:
                raise PreconditionFailed(
                    'Condition failed against resources parent')

        # Now we need to check the If header against our own lock state
        itrue = self.dav__simpleifhandler(REQUEST, RESPONSE, 'PUT', refresh=1)
        if not itrue:
            raise PreconditionFailed(
                'Condition failed against locknull resource')

        # All of the If header tests succeeded, now we need to remove ourselves
        # from our parent.  We need to transfer lock state to the new object.
        locks = self.wl_lockItems()
        parent._delObject(name)

        # Now we need to go through the regular operations of PUT
        body = REQUEST.get('BODY', '')
        typ = REQUEST.get_header('content-type', None)
        if typ is None:
            typ, enc = guess_content_type(name, body)

        factory = getattr(parent, 'PUT_factory', self._default_PUT_factory)
        ob = factory(name, typ, body) or self._default_PUT_factory(
            name, typ, body)

        # Verify that the user can create this type of object
        try:
            parent._verifyObjectPaste(ob.__of__(parent), 0)
        except Unauthorized:
            raise
        except Exception:
            raise Forbidden(sys.exc_info()[1])

        # Put the locks on the new object
        if not IWriteLock.providedBy(ob):
            raise MethodNotAllowed('The target object type cannot be locked')
        for token, lock in locks:
            ob.wl_setLock(token, lock)

        # Delegate actual PUT handling to the new object.
        ob.PUT(REQUEST, RESPONSE)
        parent._setObject(name, ob)

        RESPONSE.setStatus(201)
        RESPONSE.setBody('')
        return RESPONSE
 def MOVE(self, REQUEST, RESPONSE):
     """MOVE request: not allowed
     """
     raise MethodNotAllowed(
         'Cannot move folder data: move the folder instead')
 def COPY(self, REQUEST, RESPONSE):
     """COPY request: not allowed
     """
     raise MethodNotAllowed(
         'Cannot copy folder data: copy the folder instead')
 def DELETE(self, REQUEST, RESPONSE):
     """DELETE request: not allowed
     """
     raise MethodNotAllowed(
         'Cannot delete folder data: delete folder instead')
 def MKCOL(self, REQUEST, RESPONSE):
     """MKCOL request: not allowed
     """
     raise MethodNotAllowed(
         'Cannot create a collection inside a folder data: try at the '
         'folder level instead')
    def PROPFIND(self, REQUEST, RESPONSE):
        """ We don't support webdav, at all!

        """
        from zExceptions import MethodNotAllowed
        raise MethodNotAllowed('Method not supported for this resource.')
Esempio n. 22
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 depth not 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 oflag not 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 Exception:
            raise

        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 Exception:
            raise Forbidden(sys.exc_info()[1])
        try:
            parent._verifyObjectPaste(self)
        except Unauthorized:
            raise
        except Exception:
            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 PreconditionFailed()
                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
Esempio n. 23
0
 def __call__(self):
     method = self.request.get('REQUEST_METHOD')
     if method == 'GET':
         return self._handleGet()
     else:
         raise MethodNotAllowed("Method %s not supported" % method)
Esempio n. 24
0
 def __call__(self):
     method = self.request.get('REQUEST_METHOD')
     call = self.callmap.get(method)
     if call is None:
         raise MethodNotAllowed("Method %s not supported" % method)
     return call()
Esempio n. 25
0
    def MOVE(self, REQUEST, RESPONSE):
        """Move a resource to a new location. Though we may later try to
        make a move appear seamless across namespaces (e.g. from Zope
        to Apache), MOVE is currently only supported within the Zope
        namespace."""
        self.dav__init(REQUEST, RESPONSE)
        self.dav__validate(self, 'DELETE', REQUEST)
        if not hasattr(aq_base(self), 'cb_isMoveable') or \
           not self.cb_isMoveable():
            raise MethodNotAllowed('This object may not be moved.')

        dest = REQUEST.get_header('Destination', '')

        try:
            path = REQUEST.physicalPathFromURL(dest)
        except ValueError:
            raise BadRequest('No destination given')

        flag = REQUEST.get_header('Overwrite', 'F')
        flag = flag.upper()

        name = path.pop()
        parent_path = '/'.join(path)

        try:
            parent = self.restrictedTraverse(path)
        except ValueError:
            raise Conflict('Attempt to move to an unknown namespace.')
        except 'Not Found':
            raise Conflict('The resource %s must exist.' % parent_path)
        except Exception:
            raise

        if hasattr(parent, '__null_resource__'):
            raise Conflict('The resource %s must exist.' % parent_path)
        existing = hasattr(aq_base(parent), name)
        if existing and flag == 'F':
            raise PreconditionFailed('Resource %s exists.' % dest)
        try:
            parent._checkId(name, allow_dup=1)
        except Exception:
            raise Forbidden(sys.exc_info()[1])
        try:
            parent._verifyObjectPaste(self)
        except Unauthorized:
            raise
        except Exception:
            raise Forbidden(sys.exc_info()[1])

        # Now check locks.  Since we're affecting the resource that we're
        # moving as well as the destination, we have to check both.
        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, 'MOVE', url=dest, refresh=1)
                    if not itrue:
                        raise PreconditionFailed
                else:
                    raise Locked('Destination is locked.')
        elif IWriteLock.providedBy(parent) and parent.wl_isLocked():
            # There's no existing object in the destination folder, so
            # we need to check the folders locks since we're changing its
            # member list
            if ifhdr:
                itrue = parent.dav__simpleifhandler(REQUEST, RESPONSE, 'MOVE',
                                                    col=1, url=dest, refresh=1)
                if not itrue:
                    raise PreconditionFailed('Condition failed.')
            else:
                raise Locked('Destination is locked.')
        if wl_isLocked(self):
            # Lastly, we check ourselves
            if ifhdr:
                itrue = self.dav__simpleifhandler(REQUEST, RESPONSE, 'MOVE',
                                                  refresh=1)
                if not itrue:
                    raise PreconditionFailed('Condition failed.')
            else:
                raise Locked('Source is locked and no condition was passed in')

        orig_container = aq_parent(aq_inner(self))
        orig_id = self.getId()

        self._notifyOfCopyTo(parent, op=1)

        notify(ObjectWillBeMovedEvent(self, orig_container, orig_id,
                                      parent, name))

        # try to make ownership explicit so that it gets carried
        # along to the new location if needed.
        self.manage_changeOwnershipType(explicit=1)

        ob = self._getCopy(parent)
        ob._setId(name)

        orig_container._delObject(orig_id, suppress_events=True)

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

        parent._setObject(name, ob, set_owner=0, suppress_events=True)
        ob = parent._getOb(name)

        notify(ObjectMovedEvent(ob, orig_container, orig_id, parent, name))
        notifyContainerModified(orig_container)
        if aq_base(orig_container) is not aq_base(parent):
            notifyContainerModified(parent)

        ob._postCopy(parent, op=1)

        # try to make ownership implicit if possible
        ob.manage_changeOwnershipType(explicit=0)

        RESPONSE.setStatus(existing and 204 or 201)
        if not existing:
            RESPONSE.setHeader('Location', dest)
        RESPONSE.setBody('')
        return RESPONSE
Esempio n. 26
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
        exc_ob = 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"
            exc_ob = HTTPPreconditionFailed()
        except Exception:
            errmsg = "403 Forbidden"
            exc_ob = 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"
                    exc_ob = MethodNotAllowed()
                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"
                exc_ob = ResourceLockedError()
            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"
                    exc_ob = Forbidden()
        except Exception:
            errmsg = "403 Forbidden"
            exc_ob = Forbidden()

        if errmsg:
            if top and ((depth in (0, '0')) or (not iscol)):
                # We don't need to raise multistatus errors
                raise exc_ob
            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()