def getProperties(self, properties):
        """
        Same as _getProperties, but with a cache lookup step in between.
        
        @return a davxml.PropertyContainer
        @see _getProperties
        """

        # check if one of the requested properties is not in the cache
        allCached = True
        for pp in properties:
            if pp.qname() not in self.propertyCache.keys():
                allCached = False
                break

        if not allCached:
            # since we need to make a request anyway, we
            # might as well request frequently needed elements -- but avoid duplicates
            rp = self.cachedProperties + [
                pp for pp in properties if pp not in self.cachedProperties
            ]
            returned = self._getProperties(rp)
        else:
            props = [self.propertyCache[p.qname()] for p in properties]
            returned = davxml.PropertyContainer(*props)

        return returned
Exemple #2
0
    def add(self, what, property):
        """
        Add a response.
        @param what: a status code or a L{Failure} for the given path.
        @param property: the property whose status is being reported.
        """
        if type(what) is int:
            code = what
            error = None
            message = responsecode.RESPONSES[code]
        elif isinstance(what, Failure):
            code = statusForFailure(what)
            error = errorForFailure(what)
            message = messageForFailure(what)
        else:
            raise AssertionError("Unknown data type: %r" % (what, ))

        if len(property.children) > 0:
            # Re-instantiate as empty element.
            property = property.__class__()

        if code > 400:  # Error codes only
            log.err("Error during %s for %s: %s" %
                    (self.method, property, message))

        children = []
        children.append(davxml.PropertyContainer(property))
        children.append(davxml.Status.fromResponseCode(code))
        if error is not None:
            children.append(error)
        if message is not None:
            children.append(davxml.ResponseDescription(message))
        self.propstats.append(davxml.PropertyStatus(*children))
Exemple #3
0
    def test_PROPPATCH_liveprop(self):
        """
        PROPPATCH on a live property
        """
        prop = davxml.GETETag.fromString("some-etag-string")
        patch = davxml.PropertyUpdate(
            davxml.Set(davxml.PropertyContainer(prop)))

        return self._simple_PROPPATCH(patch, prop, responsecode.FORBIDDEN,
                                      "edit of live property")
Exemple #4
0
    def test_PROPPATCH_exists_not(self):
        """
        PROPPATCH remove a non-existant property
        """
        prop = davxml.Timeout(
        )  # Timeout isn't a valid property, so it won't exist.
        patch = davxml.PropertyUpdate(
            davxml.Remove(davxml.PropertyContainer(prop)))

        return self._simple_PROPPATCH(patch, prop, responsecode.OK,
                                      "remove of non-existant property")
Exemple #5
0
def processLockRequest(resource, request):
    """
    Respond to a LOCK request. (RFC 2518, section 8.10)
    
    Relevant notes:
    
    """

    requestStream = request.stream
    depth = getDepth(request.headers)

    #log.error(request.headers.getRawHeaders("X-Litmus")[0])

    # generate DAVDocument from request body
    lockInfo = waitForDeferred(
        deferredGenerator(parseLockRequest)(requestStream))
    yield lockInfo
    lockInfo = lockInfo.getResult()

    assertExclusiveLock(lockInfo)
    assertWriteLock(lockInfo)

    # we currently only allow lock depths of "0"
    assertZeroLockDepth(depth)

    # build the corresponding activelock element
    # e.g. http://www.webdav.org/specs/rfc2518.html#rfc.section.8.10.8
    activeLock = buildActiveLock(lockInfo, depth)

    # extract the lock token
    lt = activeLock.childOfType(davxml.LockToken).childOfType(davxml.HRef)
    # make headers with lock token header
    lth = http_headers.Headers(rawHeaders={"Lock-Token": [lt]})

    ld = davxml.LockDiscovery(activeLock)

    ignored = waitForDeferred(
        deferredGenerator(resource._setLock)(ld, request))
    yield ignored
    ignored = ignored.getResult()

    # debug
    ignored = waitForDeferred(deferredGenerator(resource._getLock)())
    yield ignored
    ignored = ignored.getResult()

    pp = davxml.PropertyContainer(ld)
    yield Response(code=responsecode.OK,
                   headers=lth,
                   stream=stream.MemoryStream(pp.toxml()))
Exemple #6
0
    def test_PROPFIND_basic(self):
        """
        PROPFIND request
        """
        def check_result(response):
            response = IResponse(response)

            if response.code != responsecode.MULTI_STATUS:
                self.fail("Incorrect response code for PROPFIND (%s != %s)" %
                          (response.code, responsecode.MULTI_STATUS))

            content_type = response.headers.getHeader("content-type")
            if content_type not in (http_headers.MimeType("text", "xml"),
                                    http_headers.MimeType(
                                        "application", "xml")):
                self.fail(
                    "Incorrect content-type for PROPFIND response (%r not in %r)"
                    % (content_type,
                       (http_headers.MimeType("text", "xml"),
                        http_headers.MimeType("application", "xml"))))

            return davXMLFromStream(response.stream).addCallback(check_xml)

        def check_xml(doc):
            multistatus = doc.root_element

            if not isinstance(multistatus, davxml.MultiStatus):
                self.fail(
                    "PROPFIND response XML root element is not multistatus: %r"
                    % (multistatus, ))

            for response in multistatus.childrenOfType(
                    davxml.PropertyStatusResponse):
                if response.childOfType(davxml.HRef) == "/":
                    for propstat in response.childrenOfType(
                            davxml.PropertyStatus):
                        status = propstat.childOfType(davxml.Status)
                        properties = propstat.childOfType(
                            davxml.PropertyContainer).children

                        if status.code != responsecode.OK:
                            self.fail(
                                "PROPFIND failed (status %s) to locate live properties: %s"
                                % (status.code, properties))

                        properties_to_find = [
                            p.qname() for p in live_properties
                        ]

                        for property in properties:
                            qname = property.qname()
                            if qname in properties_to_find:
                                properties_to_find.remove(qname)
                            else:
                                self.fail(
                                    "PROPFIND found property we didn't ask for: %r"
                                    % (property, ))

                        if properties_to_find:
                            self.fail(
                                "PROPFIND failed to find properties: %r" %
                                (properties_to_find, ))

                    break

            else:
                self.fail("No response for URI /")

        query = davxml.PropertyFind(davxml.PropertyContainer(*live_properties))

        request = SimpleRequest(self.site, "PROPFIND", "/")

        depth = random.choice(("0", "1", "infinity", None))
        if depth is not None:
            request.headers.setHeader("depth", depth)

        request.stream = MemoryStream(query.toxml())

        return self.send(request, check_result)
Exemple #7
0
    def test_PROPPATCH_basic(self):
        """
        PROPPATCH
        """

        # FIXME:
        # Do PROPFIND to make sure it's still there
        # Test nonexistant resource
        # Test None namespace in property

        def check_patch_response(response):
            response = IResponse(response)

            if response.code != responsecode.MULTI_STATUS:
                self.fail("Incorrect response code for PROPFIND (%s != %s)" %
                          (response.code, responsecode.MULTI_STATUS))

            content_type = response.headers.getHeader("content-type")
            if content_type not in (http_headers.MimeType("text", "xml"),
                                    http_headers.MimeType(
                                        "application", "xml")):
                self.fail(
                    "Incorrect content-type for PROPPATCH response (%r not in %r)"
                    % (content_type,
                       (http_headers.MimeType("text", "xml"),
                        http_headers.MimeType("application", "xml"))))

            return davXMLFromStream(
                response.stream).addCallback(check_patch_xml)

        def check_patch_xml(doc):
            multistatus = doc.root_element

            if not isinstance(multistatus, davxml.MultiStatus):
                self.fail(
                    "PROPFIND response XML root element is not multistatus: %r"
                    % (multistatus, ))

            # Requested a property change one resource, so there should be exactly one response
            response = multistatus.childOfType(davxml.Response)

            # Should have a response description (its contents are arbitrary)
            response.childOfType(davxml.ResponseDescription)

            # Requested property change was on /
            self.failUnless(
                response.childOfType(davxml.HRef) == "/",
                "Incorrect response URI: %s != /" %
                (response.childOfType(davxml.HRef), ))

            # Requested one property change, so there should be exactly one property status
            propstat = response.childOfType(davxml.PropertyStatus)

            # And the contained property should be a SpiffyProperty
            self.failIf(
                propstat.childOfType(
                    davxml.PropertyContainer).childOfType(SpiffyProperty) is
                None, "Not a SpiffyProperty in PROPPATCH property status: %s" %
                (propstat.toxml()))

            if not have_dead_properties:
                raise SkipTest(
                    "No dead property store available for DAVFile.  "
                    "Install xattr (http://undefined.org/python/#xattr) to enable use of dead properties."
                )

            # And the status should be 200
            self.failUnless(
                propstat.childOfType(davxml.Status).code == responsecode.OK,
                "Incorrect status code for PROPPATCH of property %s: %s != %s"
                % (propstat.childOfType(davxml.PropertyContainer).toxml(),
                   propstat.childOfType(davxml.Status).code, responsecode.OK))

        patch = davxml.PropertyUpdate(
            davxml.Set(
                davxml.PropertyContainer(
                    SpiffyProperty.fromString("This is a spiffy resource."))))

        request = SimpleRequest(self.site, "PROPPATCH", "/")
        request.stream = MemoryStream(patch.toxml())
        return self.send(request, check_patch_response)
Exemple #8
0
                            properties_by_status[status] = []
                        properties_by_status[status].append(propertyName(property))
                    else:
                        properties_by_status[responsecode.OK].append(resource_property)
                else:
                    log.err("Can't find property %r for resource %s" % (property, uri))
                    properties_by_status[responsecode.NOT_FOUND].append(propertyName(property))

        propstats = []

        for status in properties_by_status:
            properties = properties_by_status[status]
            if not properties: continue

            xml_status    = davxml.Status.fromResponseCode(status)
            xml_container = davxml.PropertyContainer(*properties)
            xml_propstat  = davxml.PropertyStatus(xml_container, xml_status)

            propstats.append(xml_propstat)

        xml_resource = davxml.HRef(uri)
        xml_response = davxml.PropertyStatusResponse(xml_resource, *propstats)

        xml_responses.append(xml_response)

    #
    # Return response
    #
    yield MultiStatusResponse(xml_responses)

http_PROPFIND = deferredGenerator(http_PROPFIND)