Code Repositories xandikos / debian/0.0.9-2 xandikos / davcommon.py
debian/0.0.9-2

Tree @debian/0.0.9-2 (Download .tar.gz)

davcommon.py @debian/0.0.9-2

49a74d2
a0d19a4
622dd0b
 
 
1f6446f
622dd0b
 
 
 
 
 
 
 
 
 
 
 
 
 
 
49a74d2
622dd0b
fccc3b4
 
d340c53
 
 
 
16e9a96
79a4bd2
 
07e041a
79a4bd2
 
16e9a96
79a4bd2
 
28309fd
d340c53
 
76468e6
16e9a96
28309fd
 
16e9a96
 
d340c53
 
c46d923
622dd0b
 
 
 
d340c53
 
622dd0b
ecfd484
76468e6
 
622dd0b
421e73e
622dd0b
 
 
28309fd
622dd0b
 
429c7e8
622dd0b
2c4f69e
 
db196ca
 
c46d923
38a4291
d340c53
16e9a96
 
c46d923
c565e2e
 
 
 
764f6ee
 
 
 
e45de8b
764f6ee
 
 
c565e2e
 
 
 
 
764f6ee
 
 
 
 
 
 
 
 
 
 
 
# Xandikos
# Copyright (C) 2016-2017 Jelmer Vernooń≥ <jelmer@jelmer.uk>, et al.
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; version 3
# of the License or (at your option) any later version of
# the License.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
# MA  02110-1301, USA.

"""Common functions for DAV implementations."""

from xandikos import webdav

ET = webdav.ET


class SubbedProperty(webdav.Property):
    """Property with sub-components that can be queried."""

    def get_value_ext(self, href, resource, el, environ, requested):
        """Get the value of a data property.

        :param href: Resource href
        :param resource: Resource to get value for
        :param el: Element to fill in
        :param environ: WSGI environ dict
        :param requested: Requested property (including subelements)
        """
        raise NotImplementedError(self.get_value_ext)


def get_properties_with_data(data_property, href, resource, properties,
                             environ, requested):
    properties = dict(properties)
    properties[data_property.name] = data_property
    return webdav.get_properties(
        href, resource, properties, environ, requested)


class MultiGetReporter(webdav.Reporter):
    """Abstract base class for multi-get reporters."""

    name = None

    # A SubbedProperty subclass
    data_property = None

    @webdav.multistatus
    def report(self, environ, body, resources_by_hrefs, properties, base_href,
               resource, depth):
        # TODO(jelmer): Verify that depth == "0"
        # TODO(jelmer): Verify that resource is an the right resource type
        requested = None
        hrefs = []
        for el in body:
            if el.tag in ('{DAV:}prop', '{DAV:}allprop', '{DAV:}propname'):
                requested = el
            elif el.tag == '{DAV:}href':
                hrefs.append(webdav.read_href_element(el))
            else:
                raise webdav.BadRequestError(
                    'Unknown tag %s in report %s' % (el.tag, self.name))
        for (href, resource) in resources_by_hrefs(hrefs):
            if resource is None:
                yield webdav.Status(href, '404 Not Found', propstat=[])
            else:
                propstat = get_properties_with_data(
                    self.data_property, href, resource, properties, environ,
                    requested)
                yield webdav.Status(href, '200 OK', propstat=list(propstat))


# see https://tools.ietf.org/html/rfc4790

class UnknownCollation(Exception):

    def __init__(self, collation):
        super(UnknownCollation, self).__init__(
            "Collation %r is not supported" % collation)
        self.collation = collation


collations = {
    'i;ascii-casemap': lambda a, b: (a.decode('ascii').upper() ==
                                     b.decode('ascii').upper()),
    'i;octet': lambda a, b: a == b,
}


def get_collation(name):
    """Get a collation by name.

    :param name: Collation name
    :raises UnknownCollation: If the collation is not supported
    """
    try:
        return collations[name]
    except KeyError:
        raise UnknownCollation(name)