From 83db27303f41083ecd1cc4394ec7a7913d56b498 Mon Sep 17 00:00:00 2001 From: Christoph Polcin Date: Sun, 5 Jan 2014 20:54:17 +0100 Subject: [PATCH] Respond to all authenticated PROPFIND requests --- radicale/__init__.py | 10 +++-- radicale/xmlutils.py | 105 ++++++++++++++++++++++++------------------- 2 files changed, 67 insertions(+), 48 deletions(-) diff --git a/radicale/__init__.py b/radicale/__init__.py index 9222e9c3..c0d762b0 100644 --- a/radicale/__init__.py +++ b/radicale/__init__.py @@ -283,10 +283,14 @@ class Application(object): read_allowed_items, write_allowed_items = \ self.collect_allowed_items(items, user) + is_authenticated = auth.is_authenticated(user, password) + if ((read_allowed_items or write_allowed_items) - and (not user or auth.is_authenticated(user, password))) or \ + and (not user or is_authenticated)) or \ + (is_authenticated and function == self.propfind) or \ function == self.options or not items: - # Collections found, or OPTIONS request, or no items at all + # Collections found, or authenticated PROPFIND request, + # or OPTIONS request, or no items at all status, headers, answer = function( environ, read_allowed_items, write_allowed_items, content, user) @@ -294,7 +298,7 @@ class Application(object): status, headers, answer = NOT_ALLOWED if ((status, headers, answer) == NOT_ALLOWED and - not auth.is_authenticated(user, password) and + not is_authenticated and config.get("auth", "type") != "None"): # Unknown or unauthorized user log.LOGGER.info("%s refused" % (user or "Anonymous user")) diff --git a/radicale/xmlutils.py b/radicale/xmlutils.py index f0129e3e..f94ed5e6 100644 --- a/radicale/xmlutils.py +++ b/radicale/xmlutils.py @@ -234,8 +234,12 @@ def propfind(path, xml_request, collections, user=None): # Writing answer multistatus = ET.Element(_tag("D", "multistatus")) - for collection in collections: - response = _propfind_response(path, collection, props, user) + if collections: + for collection in collections: + response = _propfind_response(path, collection, props, user) + multistatus.append(response) + else: + response = _propfind_response(path, None, props, user) multistatus.append(response) return _pretty_xml(multistatus) @@ -251,8 +255,11 @@ def _propfind_response(path, item, props, user): response = ET.Element(_tag("D", "response")) href = ET.Element(_tag("D", "href")) - uri = item.url if is_collection else "%s/%s" % (path, item.name) - href.text = _href(uri.replace("//", "/")) + if item: + uri = item.url if is_collection else "%s/%s" % (path, item.name) + href.text = _href(uri.replace("//", "/")) + else: + href.text = _href(path) response.append(href) propstat404 = ET.Element(_tag("D", "propstat")) @@ -268,10 +275,8 @@ def _propfind_response(path, item, props, user): for tag in props: element = ET.Element(tag) is404 = False - if tag == _tag("D", "getetag"): - element.text = item.etag - elif tag in (_tag("D", "principal-URL"), - _tag("D", "current-user-principal")): + if tag in (_tag("D", "principal-URL"), + _tag("D", "current-user-principal")): if user: tag = ET.Element(_tag("D", "href")) tag.text = _href("%s/" % user) @@ -317,45 +322,55 @@ def _propfind_response(path, item, props, user): report_tag.text = report_name supported.append(report_tag) element.append(supported) - elif is_collection: - if tag == _tag("D", "getcontenttype"): - element.text = item.mimetype - elif tag == _tag("D", "resourcetype"): - if item.is_principal: - tag = ET.Element(_tag("D", "principal")) - element.append(tag) - if item.is_leaf(item.path) or ( - not item.exists and item.resource_type): - # 2nd case happens when the collection is not stored yet, - # but the resource type is guessed - if item.resource_type == "addressbook": - tag = ET.Element(_tag("CR", item.resource_type)) - else: - tag = ET.Element(_tag("C", item.resource_type)) - element.append(tag) - tag = ET.Element(_tag("D", "collection")) - element.append(tag) - elif tag == _tag("D", "owner") and item.owner_url: - element.text = item.owner_url - elif tag == _tag("CS", "getctag"): + # item related properties + elif item: + if tag == _tag("D", "getetag"): element.text = item.etag - elif tag == _tag("C", "calendar-timezone"): - element.text = ical.serialize( - item.tag, item.headers, item.timezones) - elif tag == _tag("D", "displayname"): - element.text = item.name - elif tag == _tag("A", "calendar-color"): - element.text = item.color - else: - human_tag = _tag_from_clark(tag) - if human_tag in collection_props: - element.text = collection_props[human_tag] + elif is_collection: + if tag == _tag("D", "getcontenttype"): + element.text = item.mimetype + elif tag == _tag("D", "resourcetype"): + if item.is_principal: + tag = ET.Element(_tag("D", "principal")) + element.append(tag) + if item.is_leaf(item.path) or ( + not item.exists and item.resource_type): + # 2nd case happens when the collection is not stored yet, + # but the resource type is guessed + if item.resource_type == "addressbook": + tag = ET.Element(_tag("CR", item.resource_type)) + else: + tag = ET.Element(_tag("C", item.resource_type)) + element.append(tag) + tag = ET.Element(_tag("D", "collection")) + element.append(tag) + elif tag == _tag("D", "owner") and item.owner_url: + element.text = item.owner_url + elif tag == _tag("CS", "getctag"): + element.text = item.etag + elif tag == _tag("C", "calendar-timezone"): + element.text = ical.serialize( + item.tag, item.headers, item.timezones) + elif tag == _tag("D", "displayname"): + element.text = item.name + elif tag == _tag("A", "calendar-color"): + element.text = item.color else: - is404 = True - # Not for collections - elif tag == _tag("D", "getcontenttype"): - element.text = "%s; component=%s" % ( - item.mimetype, item.tag.lower()) + human_tag = _tag_from_clark(tag) + if human_tag in collection_props: + element.text = collection_props[human_tag] + else: + is404 = True + # Not for collections + elif tag == _tag("D", "getcontenttype"): + element.text = "%s; component=%s" % ( + item.mimetype, item.tag.lower()) + elif tag == _tag("D", "resourcetype"): + # resourcetype must be returned empty for non-collection elements + pass + else: + is404 = True + # Not for items elif tag == _tag("D", "resourcetype"): # resourcetype must be returned empty for non-collection elements pass