Ejemplo n.º 1
0
    def test_encodeXMLName(self):
        # No namespace
        self.assertEquals(encodeXMLName(None, "name"), "name")
        self.assertEquals(encodeXMLName(""  , "name"), "name")

        # Normal case
        self.assertEquals(encodeXMLName("namespace", "name"), "{namespace}name")
Ejemplo n.º 2
0
    def test_encodeXMLName(self):
        # No namespace
        self.assertEquals(encodeXMLName(None, "name"), "name")
        self.assertEquals(encodeXMLName("", "name"), "name")

        # Normal case
        self.assertEquals(encodeXMLName("namespace", "name"), "{namespace}name")
Ejemplo n.º 3
0
        def gotProperties(qnames):
            accessDeniedValue = object()

            def gotError(f, name):
                f.trap(HTTPError)
                code = f.value.response.code
                if code == responsecode.NOT_FOUND:
                    log.error("Property %s was returned by listProperties() "
                              "but does not exist for resource %s."
                              % (name, self.resource))
                    return (name, None)
                if code == responsecode.UNAUTHORIZED:
                    return (name, accessDeniedValue)
                return f

            whenAllProperties = gatherResults([
                maybeDeferred(self.resource.readProperty, qn, request)
                .addCallback(lambda p, iqn=qn: (p.sname(), p.toxml())
                             if p is not None else (encodeXMLName(*iqn), None))
                .addErrback(gotError, encodeXMLName(*qn))
                for qn in sorted(qnames)
            ])

            @whenAllProperties.addCallback
            def gotValues(items):
                for even, [name, value] in zip(cycle(["odd", "even"]), items):
                    if value is None:
                        value = tags.i("(no value)")
                    elif value is accessDeniedValue:
                        value = tags.i("(access forbidden)")
                    yield tag.clone().fillSlots(
                        even=even, name=name, value=value,
                    )
            return whenAllProperties
Ejemplo n.º 4
0
    def get(self, qname, uid=None):
        """
        Retrieve the value of a property stored as an extended attribute on the
        wrapped path.

        @param qname: The property to retrieve as a two-tuple of namespace URI
            and local name.

        @param uid: The per-user identifier for per user properties.

        @raise HTTPError: If there is no value associated with the given
            property.

        @return: A L{WebDAVDocument} representing the value associated with the
            given property.
        """
        
        try:
            data = self.attrs.get(self._encode(qname, uid))
        except KeyError:
            raise HTTPError(StatusResponse(
                responsecode.NOT_FOUND,
                "No such property: %s" % (encodeXMLName(*qname),)
            ))
        except IOError, e:
            if e.errno in _ATTR_MISSING or e.errno == errno.ENOENT:
                raise HTTPError(StatusResponse(
                    responsecode.NOT_FOUND,
                    "No such property: %s" % (encodeXMLName(*qname),)
                ))
            else:
                raise HTTPError(StatusResponse(
                    statusForFailure(Failure()),
                    "Unable to read property: %s" % (encodeXMLName(*qname),)
                ))
Ejemplo n.º 5
0
 def __init__(self, qname):
     HTTPError.__init__(self,
         StatusResponse(
             responsecode.NOT_FOUND,
             "No such property: %s" % encodeXMLName(*qname)
         )
     )
Ejemplo n.º 6
0
 def __init__(self, qname):
     HTTPError.__init__(
         self,
         StatusResponse(
             responsecode.NOT_FOUND,
             "No such property: %s" % encodeXMLName(*qname)
         )
     )
Ejemplo n.º 7
0
    def setProperty(self, child, property, uid, delete=False):
        propertyCache, key, childCache, token = self.childCache(child)

        if delete:
            qname = property
            qnameuid = qname + (uid, )
            if qnameuid in childCache:
                del childCache[qnameuid]
        else:
            qname = property.qname()
            qnameuid = qname + (uid, )
            childCache[qnameuid] = property

        client = self.memcacheClient()

        if client is not None:
            retries = 10
            while retries:
                try:
                    if client.set(key,
                                  childCache,
                                  time=self.cacheTimeout,
                                  token=token):
                        # Success
                        break

                except TokenMismatchError:
                    # The value in memcache has changed since we last
                    # fetched it
                    self.log.debug(
                        "memcacheprops setProperty TokenMismatchError; retrying..."
                    )

                finally:
                    # Re-fetch the properties for this child
                    loaded = self._loadCache(
                        childNames=(child.fp.basename(), ))
                    propertyCache.update(loaded.iteritems())

                retries -= 1

                propertyCache, key, childCache, token = self.childCache(child)

                if delete:
                    if qnameuid in childCache:
                        del childCache[qnameuid]
                else:
                    childCache[qnameuid] = property

            else:
                self.log.error(
                    "memcacheprops setProperty had too many failures")
                delattr(self, "_propertyCache")
                raise MemcacheError(
                    "Unable to %s property %s%s on %s" %
                    ("delete" if delete else "set", uid if uid else "",
                     encodeXMLName(*qname), child))
Ejemplo n.º 8
0
    def setProperty(self, child, property, uid, delete=False):
        propertyCache, key, childCache, token = self.childCache(child)

        if delete:
            qname = property
            qnameuid = qname + (uid,)
            if qnameuid in childCache:
                del childCache[qnameuid]
        else:
            qname = property.qname()
            qnameuid = qname + (uid,)
            childCache[qnameuid] = property

        client = self.memcacheClient()

        if client is not None:
            retries = 10
            while retries:
                try:
                    if client.set(
                        key, childCache, time=self.cacheTimeout,
                        token=token
                    ):
                        # Success
                        break

                except TokenMismatchError:
                    # The value in memcache has changed since we last
                    # fetched it
                    self.log.debug("memcacheprops setProperty TokenMismatchError; retrying...")

                finally:
                    # Re-fetch the properties for this child
                    loaded = self._loadCache(childNames=(child.fp.basename(),))
                    propertyCache.update(loaded.iteritems())

                retries -= 1

                propertyCache, key, childCache, token = self.childCache(child)

                if delete:
                    if qnameuid in childCache:
                        del childCache[qnameuid]
                else:
                    childCache[qnameuid] = property

            else:
                self.log.error("memcacheprops setProperty had too many failures")
                delattr(self, "_propertyCache")
                raise MemcacheError("Unable to %s property %s%s on %s" % (
                    "delete" if delete else "set",
                    uid if uid else "",
                    encodeXMLName(*qname),
                    child
                ))
Ejemplo n.º 9
0
    def get(self, qname):
        try:
            property = self._dict[qname]
        except KeyError:
            raise HTTPError(
                StatusResponse(
                    responsecode.NOT_FOUND,
                    "No such property: %s" % (encodeXMLName(*qname), )))

        doc = element.WebDAVDocument.fromString(property)
        return doc.root_element
Ejemplo n.º 10
0
    def get(self, qname):
        try:
            property = self._dict[qname]
        except KeyError:
            raise HTTPError(StatusResponse(
                responsecode.NOT_FOUND,
                "No such property: %s" % (encodeXMLName(*qname),)
            ))

        doc = element.WebDAVDocument.fromString(property)
        return doc.root_element
Ejemplo n.º 11
0
        def gotProperties(qnames):
            accessDeniedValue = object()

            def gotError(f, name):
                f.trap(HTTPError)
                code = f.value.response.code
                if code == responsecode.NOT_FOUND:
                    log.error(
                        "Property {p} was returned by listProperties() "
                        "but does not exist for resource {r}.",
                        p=name,
                        r=self.resource)
                    return (name, None)
                if code == responsecode.UNAUTHORIZED:
                    return (name, accessDeniedValue)
                return f

            whenAllProperties = gatherResults([
                maybeDeferred(
                    self.resource.readProperty, qn, request).addCallback(
                        lambda p, iqn=qn: (p.sname(), p.toxml()) if p is
                        not None else (encodeXMLName(*iqn), None)).addErrback(
                            gotError, encodeXMLName(*qn))
                for qn in sorted(qnames)
            ])

            @whenAllProperties.addCallback
            def gotValues(items):
                for even, [name, value] in zip(cycle(["odd", "even"]), items):
                    if value is None:
                        value = tags.i("(no value)")
                    elif value is accessDeniedValue:
                        value = tags.i("(access forbidden)")
                    yield tag.clone().fillSlots(
                        even=even,
                        name=name,
                        value=value,
                    )

            return whenAllProperties
Ejemplo n.º 12
0
    def _encodeKey(self, effective, compressNamespace=True):

        qname, uid = effective
        if compressNamespace:
            namespace = self._namespaceCompress.get(qname.namespace,
                                                    qname.namespace)
        else:
            namespace = qname.namespace
        result = urllib.quote(encodeXMLName(namespace, qname.name), safe="{}:")
        if uid and uid != self._defaultUser:
            result = uid + result
        r = self.deadPropertyXattrPrefix + result
        return r
Ejemplo n.º 13
0
    def _encodeKey(self, effective, compressNamespace=True):

        qname, uid = effective
        if compressNamespace:
            namespace = self._namespaceCompress.get(qname.namespace,
                                                    qname.namespace)
        else:
            namespace = qname.namespace
        result = urllib.quote(encodeXMLName(namespace, qname.name), safe="{}:")
        if uid and uid != self._defaultUser:
            result = uid + result
        r = self.deadPropertyXattrPrefix + result
        return r
Ejemplo n.º 14
0
    def get(self, qname, uid=None):
        """
        Retrieve the value of a property stored as an extended attribute on the
        wrapped path.

        @param qname: The property to retrieve as a two-tuple of namespace URI
            and local name.

        @param uid: The per-user identifier for per user properties.

        @raise HTTPError: If there is no value associated with the given
            property.

        @return: A L{WebDAVDocument} representing the value associated with the
            given property.
        """

        try:
            data = self.attrs.get(self._encode(qname, uid))
        except KeyError:
            raise HTTPError(
                StatusResponse(
                    responsecode.NOT_FOUND,
                    "No such property: %s" % (encodeXMLName(*qname), )))
        except IOError, e:
            if e.errno in _ATTR_MISSING or e.errno == errno.ENOENT:
                raise HTTPError(
                    StatusResponse(
                        responsecode.NOT_FOUND,
                        "No such property: %s" % (encodeXMLName(*qname), )))
            else:
                raise HTTPError(
                    StatusResponse(
                        statusForFailure(Failure()),
                        "Unable to read property: %s" %
                        (encodeXMLName(*qname), )))
Ejemplo n.º 15
0
        def get(self, qname, uid=None, cache=True):
            if cache:
                propertyCache = self.propertyCache()
                qnameuid = qname + (uid, )
                if qnameuid in propertyCache:
                    return propertyCache[qnameuid]
                else:
                    raise HTTPError(
                        StatusResponse(
                            responsecode.NOT_FOUND, "No such property: %s%s" %
                            (uid if uid else "", encodeXMLName(*qname))))

            self.log.debug("Read for %s%s on %s" %
                           (("{%s}:" % (uid, )) if uid else "", qname,
                            self.childPropertyStore.resource.fp.path))
            return self.childPropertyStore.get(qname, uid=uid)
Ejemplo n.º 16
0
        def get(self, qname, uid=None, cache=True):
            if cache:
                propertyCache = self.propertyCache()
                qnameuid = qname + (uid,)
                if qnameuid in propertyCache:
                    return propertyCache[qnameuid]
                else:
                    raise HTTPError(StatusResponse(
                        responsecode.NOT_FOUND,
                        "No such property: %s%s" % (uid if uid else "", encodeXMLName(*qname))
                    ))

            self.log_debug("Read for %s%s on %s" % (
                ("{%s}:" % (uid,)) if uid else "",
                qname,
                self.childPropertyStore.resource.fp.path
            ))
            return self.childPropertyStore.get(qname, uid=uid)
Ejemplo n.º 17
0
 def get(self, qname, uid=None):
     raise HTTPError(
         StatusResponse(responsecode.NOT_FOUND,
                        "No such property: %s" % (encodeXMLName(*qname), )))
Ejemplo n.º 18
0
 def _encode(clazz, name, uid=None):
     result = urllib.quote(encodeXMLName(*name), safe='{}:')
     if uid:
         result = uid + result
     r = clazz.deadPropertyXattrPrefix + result
     return r
Ejemplo n.º 19
0
class xattrPropertyStore(object):
    """

    This implementation uses Bob Ippolito's xattr package, available from::

        http://undefined.org/python/#xattr

    Note that the Bob's xattr package is specific to Linux and Darwin, at least
    presently.
    """
    #
    # Dead properties are stored as extended attributes on disk.  In order to
    # avoid conflicts with other attributes, prefix dead property names.
    #
    deadPropertyXattrPrefix = "WebDAV:"

    # Linux seems to require that attribute names use a "user." prefix.
    # FIXME: Is is a system-wide thing, or a per-filesystem thing?
    #   If the latter, how to we detect the file system?
    if sys.platform == "linux2":
        deadPropertyXattrPrefix = "user."

    def _encode(clazz, name, uid=None):
        result = urllib.quote(encodeXMLName(*name), safe='{}:')
        if uid:
            result = uid + result
        r = clazz.deadPropertyXattrPrefix + result
        return r

    def _decode(clazz, name):
        name = urllib.unquote(name[len(clazz.deadPropertyXattrPrefix):])

        index1 = name.find("{")
        index2 = name.find("}")

        if (index1 is -1 or index2 is -1 or not len(name) > index2):
            raise ValueError("Invalid encoded name: %r" % (name, ))
        if index1 == 0:
            uid = None
        else:
            uid = name[:index1]
        propnamespace = name[index1 + 1:index2]
        propname = name[index2 + 1:]

        return (propnamespace, propname, uid)

    _encode = classmethod(_encode)
    _decode = classmethod(_decode)

    def __init__(self, resource):
        self.resource = resource
        self.attrs = xattr.xattr(self.resource.fp.path)

    def get(self, qname, uid=None):
        """
        Retrieve the value of a property stored as an extended attribute on the
        wrapped path.

        @param qname: The property to retrieve as a two-tuple of namespace URI
            and local name.

        @param uid: The per-user identifier for per user properties.

        @raise HTTPError: If there is no value associated with the given
            property.

        @return: A L{WebDAVDocument} representing the value associated with the
            given property.
        """

        try:
            data = self.attrs.get(self._encode(qname, uid))
        except KeyError:
            raise HTTPError(
                StatusResponse(
                    responsecode.NOT_FOUND,
                    "No such property: %s" % (encodeXMLName(*qname), )))
        except IOError, e:
            if e.errno in _ATTR_MISSING or e.errno == errno.ENOENT:
                raise HTTPError(
                    StatusResponse(
                        responsecode.NOT_FOUND,
                        "No such property: %s" % (encodeXMLName(*qname), )))
            else:
                raise HTTPError(
                    StatusResponse(
                        statusForFailure(Failure()),
                        "Unable to read property: %s" %
                        (encodeXMLName(*qname), )))

        #
        # Unserialize XML data from an xattr.  The storage format has changed
        # over time:
        #
        #  1- Started with XML
        #  2- Started compressing the XML due to limits on xattr size
        #  3- Switched to pickle which is faster, still compressing
        #  4- Back to compressed XML for interoperability, size
        #
        # We only write the current format, but we also read the old
        # ones for compatibility.
        #
        legacy = False

        try:
            data = decompress(data)
        except zlib.error:
            legacy = True

        try:
            doc = WebDAVDocument.fromString(data)
        except ValueError:
            try:
                doc = unpickle(data)
            except UnpicklingError:
                format = "Invalid property value stored on server: %s %s"
                msg = format % (encodeXMLName(*qname), data)
                err(None, msg)
                raise HTTPError(
                    StatusResponse(responsecode.INTERNAL_SERVER_ERROR, msg))
            else:
                legacy = True

        if legacy:
            self.set(doc.root_element)

        return doc.root_element
Ejemplo n.º 20
0
            StatusResponse(responsecode.BAD_REQUEST,
                           "REPORT request body may not be empty"))

    #
    # Parse request
    #
    namespace = doc.root_element.namespace
    name = doc.root_element.name

    if namespace:
        if namespace == davxml.dav_namespace:
            request.submethod = "DAV:" + name
        elif namespace == caldavxml.caldav_namespace:
            request.submethod = "CalDAV:" + name
        else:
            request.submethod = encodeXMLName(namespace, name)
    else:
        request.submethod = name

    def to_method(namespace, name):
        if namespace:
            s = "_".join((namespace, name))
        else:
            s = name

        ok = string.ascii_letters + string.digits + "_"
        out = []
        for c in s:
            if c in ok:
                out.append(c)
            else:
Ejemplo n.º 21
0
 def _encode(clazz, name, uid=None):
     result = urllib.quote(encodeXMLName(*name), safe='{}:')
     if uid:
         result = uid + result
     r = clazz.deadPropertyXattrPrefix + result
     return r
Ejemplo n.º 22
0
 def toString(self):
     return encodeXMLName(self.namespace, self.name)
Ejemplo n.º 23
0
            "REPORT request body may not be empty"
        ))

    #
    # Parse request
    #
    namespace = doc.root_element.namespace
    name = doc.root_element.name

    if namespace:
        if namespace == davxml.dav_namespace:
            request.submethod = "DAV:" + name
        elif namespace == caldavxml.caldav_namespace:
            request.submethod = "CalDAV:" + name
        else:
            request.submethod = encodeXMLName(namespace, name)
    else:
        request.submethod = name


    def to_method(namespace, name):
        if namespace:
            s = "_".join((namespace, name))
        else:
            s = name

        ok = string.ascii_letters + string.digits + "_"
        out = []
        for c in s:
            if c in ok:
                out.append(c)
Ejemplo n.º 24
0
    if doc is None:
        raise HTTPError(StatusResponse(responsecode.BAD_REQUEST, "REPORT request body may not be empty"))

    #
    # Parse request
    #
    namespace = doc.root_element.namespace
    name = doc.root_element.name

    if namespace:
        if namespace == davxml.dav_namespace:
            request.submethod = "DAV:" + name
        elif namespace == caldavxml.caldav_namespace:
            request.submethod = "CalDAV:" + name
        else:
            request.submethod = encodeXMLName(namespace, name)
    else:
        request.submethod = name

    def to_method(namespace, name):
        if namespace:
            s = "_".join((namespace, name))
        else:
            s = name

        ok = string.ascii_letters + string.digits + "_"
        out = []
        for c in s:
            if c in ok:
                out.append(c)
            else:
Ejemplo n.º 25
0
 def toString(self):
     return encodeXMLName(self.namespace, self.name)
 def __repr__(self):
     return "%s = %s" % (encodeXMLName(self.ns, self.name), self.value)
Ejemplo n.º 27
0
 def get(self, qname, uid=None):
     raise HTTPError(StatusResponse(
         responsecode.NOT_FOUND,
         "No such property: %s" % (encodeXMLName(*qname),)
     ))
Ejemplo n.º 28
0
    def to_method(s):
        out = []
        for c in s:
            if c in ok:
                out.append(c)
            else:
                out.append("_")
        return "report_" + "".join(out)

    if namespace:
        method_name = to_method("_".join((namespace, name)))

        if namespace == davxml.dav_namespace:
            request.submethod = "DAV:" + name
        else:
            request.submethod = encodeXMLName(namespace, name)
    else:
        method_name = to_method(name)

        request.submethod = name

    try:
        method = getattr(self, method_name)
        
        # Also double-check via supported-reports property
        reports = self.supportedReports()
        test = lookupElement((namespace, name))
        if not test:
            raise AttributeError()
        test = davxml.Report(test())
        if test not in reports:
 def __repr__(self):
     return "%s = %s" % (encodeXMLName(self.ns, self.name), self.value)
Ejemplo n.º 30
0
            "REPORT request body may not be empty"
        ))

    #
    # Parse request
    #
    namespace = doc.root_element.namespace
    name = doc.root_element.name

    if namespace:
        if namespace == davxml.dav_namespace:
            request.submethod = "DAV:" + name
        elif namespace == caldavxml.caldav_namespace:
            request.submethod = "CalDAV:" + name
        else:
            request.submethod = encodeXMLName(namespace, name)
    else:
        request.submethod = name


    def to_method(namespace, name):
        if namespace:
            s = "_".join((namespace, name))
        else:
            s = name

        ok = string.ascii_letters + string.digits + "_"
        out = []
        for c in s:
            if c in ok:
                out.append(c)
Ejemplo n.º 31
0
def action_readProperty(rootResource, directory, store, resource, qname):
    property = (yield resource.readProperty(qname, None))
    print("%r on %s:" % (encodeXMLName(*qname), resource))
    print("")
    print(property.toxml())
Ejemplo n.º 32
0
    def to_method(s):
        out = []
        for c in s:
            if c in ok:
                out.append(c)
            else:
                out.append("_")
        return "report_" + "".join(out)

    if namespace:
        method_name = to_method("_".join((namespace, name)))

        if namespace == davxml.dav_namespace:
            request.submethod = "DAV:" + name
        else:
            request.submethod = encodeXMLName(namespace, name)
    else:
        method_name = to_method(name)

        request.submethod = name

    try:
        method = getattr(self, method_name)

        # Also double-check via supported-reports property
        reports = self.supportedReports()
        test = lookupElement((namespace, name))
        if not test:
            raise AttributeError()
        test = davxml.Report(test())
        if test not in reports:
Ejemplo n.º 33
0
def action_readProperty(resource, qname):
    property = (yield resource.readProperty(qname, None))
    print "%r on %s:" % (encodeXMLName(*qname), resource)
    print ""
    print property.toxml()