From 72f3af9ab9e89164276d64357e534487ac664965 Mon Sep 17 00:00:00 2001 From: Guillaume Ayoub Date: Fri, 17 Dec 2010 17:19:39 +0100 Subject: [PATCH 01/12] Fix bug caused by commit:673da6a9 --- radicale/xmlutils.py | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/radicale/xmlutils.py b/radicale/xmlutils.py index b49666c7..7ff759b0 100644 --- a/radicale/xmlutils.py +++ b/radicale/xmlutils.py @@ -97,22 +97,22 @@ def propfind(path, xml_request, calendar, depth, request): multistatus = ET.Element(_tag("D", "multistatus")) if depth == "0": - elements = [calendar] + items = [calendar] elif depth == "1": - elements = [calendar] + calendar.events + calendar.todos + items = [calendar] + calendar.events + calendar.todos else: # depth is infinity or not specified # we limit ourselves to depth == 1 - elements = [calendar] + calendar.events + calendar.todos + items = [calendar] + calendar.events + calendar.todos - for element in elements: - is_calendar = isinstance(element, ical.Calendar) + for item in items: + is_calendar = isinstance(item, ical.Calendar) response = ET.Element(_tag("D", "response")) multistatus.append(response) href = ET.Element(_tag("D", "href")) - href.text = path if is_calendar else "%s/%s" % (path, element.name) + href.text = path if is_calendar else "%s/%s" % (path, item.name) response.append(href) propstat = ET.Element(_tag("D", "propstat")) @@ -138,7 +138,7 @@ def propfind(path, xml_request, calendar, depth, request): elif tag == _tag("D", "getcontenttype"): element.text = "text/calendar" elif tag == _tag("D", "getetag"): - element.text = element.etag + element.text = item.etag elif tag == _tag("D", "displayname"): element.text = calendar.name elif tag == _tag("D", "supported-report-set"): From 091d89889d152ec2b3013a2b24f7548b53a9f30c Mon Sep 17 00:00:00 2001 From: Guillaume Ayoub Date: Mon, 20 Dec 2010 15:49:48 +0100 Subject: [PATCH 02/12] Fix get requests for whole calendar --- radicale/__init__.py | 4 +++- radicale/xmlutils.py | 3 ++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/radicale/__init__.py b/radicale/__init__.py index 2fc3f804..64b58335 100644 --- a/radicale/__init__.py +++ b/radicale/__init__.py @@ -154,7 +154,8 @@ class CalendarHTTPHandler(server.BaseHTTPRequestHandler): def do_GET(self): """Manage GET request.""" self.do_HEAD() - self.wfile.write(self._answer) + if self._answer: + self.wfile.write(self._answer) @check_rights def do_HEAD(self): @@ -170,6 +171,7 @@ class CalendarHTTPHandler(server.BaseHTTPRequestHandler): headers=self._calendar.headers, items=items) etag = item.etag else: + self._answer = None self.send_response(client.GONE) return else: diff --git a/radicale/xmlutils.py b/radicale/xmlutils.py index 7ff759b0..ddf0a7f1 100644 --- a/radicale/xmlutils.py +++ b/radicale/xmlutils.py @@ -52,7 +52,8 @@ def _response(code): def name_from_path(path): """Return Radicale item name from ``path``.""" - return path.split("/")[-1] + path_parts = path.strip("/").split("/") + return path_parts[-1] if len(path_parts) > 2 else None def delete(path, calendar): From c39ac102e8b581aedfe18e04fcb4cb5fc5a374a9 Mon Sep 17 00:00:00 2001 From: Guillaume Ayoub Date: Wed, 29 Dec 2010 16:47:07 +0100 Subject: [PATCH 03/12] Remove a done/rejected TODO --- radicale/xmlutils.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/radicale/xmlutils.py b/radicale/xmlutils.py index ddf0a7f1..25f72e5a 100644 --- a/radicale/xmlutils.py +++ b/radicale/xmlutils.py @@ -27,8 +27,6 @@ in them for XML requests (all but PUT). """ -# TODO: Manage depth and calendars/collections - import xml.etree.ElementTree as ET from radicale import client, config, ical From 9d508efcd4f6900bdf952c92f309fa09c67256dd Mon Sep 17 00:00:00 2001 From: Guillaume Ayoub Date: Wed, 29 Dec 2010 18:58:54 +0100 Subject: [PATCH 04/12] Update NEWS and TODO files --- NEWS | 9 +++++++++ TODO | 13 ++++++++++--- 2 files changed, 19 insertions(+), 3 deletions(-) diff --git a/NEWS b/NEWS index ea78e6d2..fa927ff1 100644 --- a/NEWS +++ b/NEWS @@ -6,6 +6,15 @@ NEWS ------ +0.5 - *Not released yet* +======================== + +* Calendar depth +* MacOS and Windows support +* HEAD requests management +* htpasswd user from calendar path + + 0.4 - Hot Days Back =================== diff --git a/TODO b/TODO index e9f57b34..f394b8ab 100644 --- a/TODO +++ b/TODO @@ -9,9 +9,16 @@ 0.5 === -* Calendar collections -* Group calendars -* [IN PROGRESS] Windows and MacOS tested support +* iCal and iPhone support + + +0.6 +=== + +* [IN PROGRESS] Group calendars +* [IN PROGRESS] LDAP and databases auth support +* CalDAV rights +* Read-only access for foreign users 1.0 From dcabf4249e755276526f643336599df77f194db8 Mon Sep 17 00:00:00 2001 From: Guillaume Ayoub Date: Wed, 29 Dec 2010 19:10:56 +0100 Subject: [PATCH 05/12] Adding the calendar-home-set property management --- radicale/xmlutils.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/radicale/xmlutils.py b/radicale/xmlutils.py index 25f72e5a..35071a3b 100644 --- a/radicale/xmlutils.py +++ b/radicale/xmlutils.py @@ -151,6 +151,12 @@ def propfind(path, xml_request, calendar, depth, request): element.text = "%s://%s%s" % ( request.server.PROTOCOL, request.headers["Host"], request.path) + elif tag == _tag("C", "calendar-home-set"): + tag = ET.Element(_tag("D", "href")) + tag.text = "%s://%s%s" % ( + request.server.PROTOCOL, request.headers["Host"], + request.path) + element.append(tag) prop.append(element) From 039e868e5f36d02e032d919d2fb58d7ddf332a6e Mon Sep 17 00:00:00 2001 From: Guillaume Ayoub Date: Fri, 7 Jan 2011 15:25:05 +0100 Subject: [PATCH 06/12] iPhone support, thank you Andrew --- radicale/__init__.py | 2 +- radicale/xmlutils.py | 80 +++++++++++++++++++++----------------------- 2 files changed, 39 insertions(+), 43 deletions(-) diff --git a/radicale/__init__.py b/radicale/__init__.py index 64b58335..b842b6a5 100644 --- a/radicale/__init__.py +++ b/radicale/__init__.py @@ -216,7 +216,7 @@ class CalendarHTTPHandler(server.BaseHTTPRequestHandler): xml_request = self.rfile.read(int(self.headers["Content-Length"])) self._answer = xmlutils.propfind( self.path, xml_request, self._calendar, - self.headers.get("depth", "infinity"), self) + self.headers.get("depth", "infinity")) self.send_response(client.MULTI_STATUS) self.send_header("DAV", "1, calendar-access") diff --git a/radicale/xmlutils.py b/radicale/xmlutils.py index 35071a3b..11cb1756 100644 --- a/radicale/xmlutils.py +++ b/radicale/xmlutils.py @@ -79,7 +79,7 @@ def delete(path, calendar): return ET.tostring(multistatus, config.get("encoding", "request")) -def propfind(path, xml_request, calendar, depth, request): +def propfind(path, xml_request, calendar, depth): """Read and answer PROPFIND requests. Read rfc4918-9.1 for info. @@ -97,10 +97,8 @@ def propfind(path, xml_request, calendar, depth, request): if depth == "0": items = [calendar] - elif depth == "1": - items = [calendar] + calendar.events + calendar.todos else: - # depth is infinity or not specified + # depth is 1, infinity or not specified # we limit ourselves to depth == 1 items = [calendar] + calendar.events + calendar.todos @@ -111,7 +109,7 @@ def propfind(path, xml_request, calendar, depth, request): multistatus.append(response) href = ET.Element(_tag("D", "href")) - href.text = path if is_calendar else "%s/%s" % (path, item.name) + href.text = path if is_calendar else path + item.name response.append(href) propstat = ET.Element(_tag("D", "propstat")) @@ -122,42 +120,45 @@ def propfind(path, xml_request, calendar, depth, request): for tag in props: element = ET.Element(tag) - if tag == _tag("D", "resourcetype"): - if is_calendar: - tag = ET.Element(_tag("C", "calendar")) - element.append(tag) - tag = ET.Element(_tag("D", "collection")) - element.append(tag) - else: - tag = ET.Element(_tag("C", "comp")) - tag.set("name", element.tag) - element.append(tag) + if tag == _tag("D", "resourcetype") and is_calendar: + tag = ET.Element(_tag("C", "calendar")) + element.append(tag) + tag = ET.Element(_tag("D", "collection")) + element.append(tag) elif tag == _tag("D", "owner"): element.text = calendar.owner elif tag == _tag("D", "getcontenttype"): element.text = "text/calendar" + elif tag == _tag("CS", "getctag") and is_calendar: + element.text = item.etag elif tag == _tag("D", "getetag"): element.text = item.etag - elif tag == _tag("D", "displayname"): + elif tag == _tag("D", "displayname") and is_calendar: element.text = calendar.name - elif tag == _tag("D", "supported-report-set"): - supported_report = ET.Element(_tag("D", "supported-report")) - report_set = ET.Element(_tag("D", "report")) - report_set.append(ET.Element(_tag("C", "calendar-multiget"))) - supported_report.append(report_set) - element.append(supported_report) elif tag == _tag("D", "principal-URL"): # TODO: use a real principal URL, read rfc3744-4.2 for info - element.text = "%s://%s%s" % ( - request.server.PROTOCOL, request.headers["Host"], - request.path) + tag = ET.Element(_tag("D", "href")) + tag.text = path + element.append(tag) + elif tag == _tag("D", "principal-collection-set"): + tag = ET.Element(_tag("D", "href")) + tag.text = path + element.append(tag) elif tag == _tag("C", "calendar-home-set"): tag = ET.Element(_tag("D", "href")) - tag.text = "%s://%s%s" % ( - request.server.PROTOCOL, request.headers["Host"], - request.path) + tag.text = path element.append(tag) - + elif tag == _tag("C", "supported-calendar-component-set"): + comp = ET.Element(_tag("C", "comp")) + comp.set("name", "VTODO") + element.append(comp) + comp = ET.Element(_tag("C", "comp")) + comp.set("name", "VEVENT") + element.append(comp) + elif tag == _tag("D", "current-user-privilege-set"): + privilege = ET.Element(_tag("D", "privilege")) + privilege.append(ET.Element(_tag("D", "all"))) + element.append(privilege) prop.append(element) status = ET.Element(_tag("D", "status")) @@ -227,19 +228,14 @@ def report(path, xml_request, calendar): prop = ET.Element(_tag("D", "prop")) propstat.append(prop) - if _tag("D", "getetag") in props: - element = ET.Element(_tag("D", "getetag")) - element.text = item.etag - prop.append(element) - - if _tag("C", "calendar-data") in props: - element = ET.Element(_tag("C", "calendar-data")) - if isinstance(item, ical.Event): - element.text = ical.serialize( - calendar.headers, calendar.timezones + [item]) - elif isinstance(item, ical.Todo): - element.text = ical.serialize( - calendar.headers, calendar.timezones + [item]) + for tag in props: + element = ET.Element(tag) + if tag == _tag("D", "getetag"): + element.text = item.etag + elif tag == _tag("C", "calendar-data"): + if isinstance(item, (ical.Event, ical.Todo)): + element.text = ical.serialize( + calendar.headers, calendar.timezones + [item]) prop.append(element) status = ET.Element(_tag("D", "status")) From d11d4cc8c19a9cd41b950ef86fb87862fa1f9cbe Mon Sep 17 00:00:00 2001 From: Guillaume Ayoub Date: Sun, 9 Jan 2011 17:41:42 +0100 Subject: [PATCH 07/12] Pylint, remove fixed todos --- radicale/__init__.py | 1 + radicale/acl/htpasswd.py | 2 +- radicale/config.py | 2 -- radicale/ical.py | 1 - radicale/xmlutils.py | 2 +- 5 files changed, 3 insertions(+), 5 deletions(-) diff --git a/radicale/__init__.py b/radicale/__init__.py index b842b6a5..ebcfe161 100644 --- a/radicale/__init__.py +++ b/radicale/__init__.py @@ -90,6 +90,7 @@ class HTTPServer(server.HTTPServer): class HTTPSServer(HTTPServer): """HTTPS server.""" PROTOCOL = "https" + def __init__(self, address, handler): """Create server by wrapping HTTP socket in an SSL socket.""" # Fails with Python 2.5, import if needed diff --git a/radicale/acl/htpasswd.py b/radicale/acl/htpasswd.py index bb2f26bc..f6413516 100644 --- a/radicale/acl/htpasswd.py +++ b/radicale/acl/htpasswd.py @@ -49,7 +49,7 @@ def _sha1(hash_value, password): """Check if ``hash_value`` and ``password`` match using sha1 method.""" hash_value = hash_value.replace("{SHA}", "").encode("ascii") password = password.encode(config.get("encoding", "stock")) - sha1 = hashlib.sha1() + sha1 = hashlib.sha1() # pylint: disable=E1101 sha1.update(password) return sha1.digest() == base64.b64decode(hash_value) diff --git a/radicale/config.py b/radicale/config.py index 1cf9dd67..8c372807 100644 --- a/radicale/config.py +++ b/radicale/config.py @@ -25,8 +25,6 @@ Give a configparser-like interface to read and write configuration. """ -# TODO: Use abstract filenames for other platforms - import os import sys # Manage Python2/3 different modules diff --git a/radicale/ical.py b/radicale/ical.py index cff038f8..b1567411 100644 --- a/radicale/ical.py +++ b/radicale/ical.py @@ -135,7 +135,6 @@ class Calendar(object): def __init__(self, path): """Initialize the calendar with ``cal`` and ``user`` parameters.""" - # TODO: Use properties from the calendar configuration self.encoding = "utf-8" self.owner = path.split("/")[0] self.path = os.path.join(FOLDER, path.replace("/", os.path.sep)) diff --git a/radicale/xmlutils.py b/radicale/xmlutils.py index 11cb1756..d300e0ed 100644 --- a/radicale/xmlutils.py +++ b/radicale/xmlutils.py @@ -150,7 +150,7 @@ def propfind(path, xml_request, calendar, depth): element.append(tag) elif tag == _tag("C", "supported-calendar-component-set"): comp = ET.Element(_tag("C", "comp")) - comp.set("name", "VTODO") + comp.set("name", "VTODO") # pylint: disable=W0511 element.append(comp) comp = ET.Element(_tag("C", "comp")) comp.set("name", "VEVENT") From 04938243a8f855448e64eb38d958f2343bf0f91d Mon Sep 17 00:00:00 2001 From: Guillaume Ayoub Date: Sun, 9 Jan 2011 17:46:22 +0100 Subject: [PATCH 08/12] Update copyright year --- radicale.py | 2 +- radicale/__init__.py | 2 +- radicale/acl/__init__.py | 2 +- radicale/acl/fake.py | 2 +- radicale/acl/htpasswd.py | 2 +- radicale/config.py | 2 +- radicale/ical.py | 2 +- radicale/xmlutils.py | 2 +- setup.py | 2 +- 9 files changed, 9 insertions(+), 9 deletions(-) diff --git a/radicale.py b/radicale.py index e7d490c2..704bcd63 100755 --- a/radicale.py +++ b/radicale.py @@ -2,7 +2,7 @@ # -*- coding: utf-8 -*- # # This file is part of Radicale Server - Calendar Server -# Copyright © 2008-2010 Guillaume Ayoub +# Copyright © 2008-2011 Guillaume Ayoub # Copyright © 2008 Nicolas Kandel # Copyright © 2008 Pascal Halter # diff --git a/radicale/__init__.py b/radicale/__init__.py index ebcfe161..c23a98cb 100644 --- a/radicale/__init__.py +++ b/radicale/__init__.py @@ -1,7 +1,7 @@ # -*- coding: utf-8 -*- # # This file is part of Radicale Server - Calendar Server -# Copyright © 2008-2010 Guillaume Ayoub +# Copyright © 2008-2011 Guillaume Ayoub # Copyright © 2008 Nicolas Kandel # Copyright © 2008 Pascal Halter # diff --git a/radicale/acl/__init__.py b/radicale/acl/__init__.py index 349b1dd0..d33e8788 100644 --- a/radicale/acl/__init__.py +++ b/radicale/acl/__init__.py @@ -1,7 +1,7 @@ # -*- coding: utf-8 -*- # # This file is part of Radicale Server - Calendar Server -# Copyright © 2008-2010 Guillaume Ayoub +# Copyright © 2008-2011 Guillaume Ayoub # Copyright © 2008 Nicolas Kandel # Copyright © 2008 Pascal Halter # diff --git a/radicale/acl/fake.py b/radicale/acl/fake.py index 145f3d12..9ddd2246 100644 --- a/radicale/acl/fake.py +++ b/radicale/acl/fake.py @@ -1,7 +1,7 @@ # -*- coding: utf-8 -*- # # This file is part of Radicale Server - Calendar Server -# Copyright © 2008-2010 Guillaume Ayoub +# Copyright © 2008-2011 Guillaume Ayoub # Copyright © 2008 Nicolas Kandel # Copyright © 2008 Pascal Halter # diff --git a/radicale/acl/htpasswd.py b/radicale/acl/htpasswd.py index f6413516..250ec901 100644 --- a/radicale/acl/htpasswd.py +++ b/radicale/acl/htpasswd.py @@ -1,7 +1,7 @@ # -*- coding: utf-8 -*- # # This file is part of Radicale Server - Calendar Server -# Copyright © 2008-2010 Guillaume Ayoub +# Copyright © 2008-2011 Guillaume Ayoub # Copyright © 2008 Nicolas Kandel # Copyright © 2008 Pascal Halter # diff --git a/radicale/config.py b/radicale/config.py index 8c372807..63929aec 100644 --- a/radicale/config.py +++ b/radicale/config.py @@ -1,7 +1,7 @@ # -*- coding: utf-8 -*- # # This file is part of Radicale Server - Calendar Server -# Copyright © 2008-2010 Guillaume Ayoub +# Copyright © 2008-2011 Guillaume Ayoub # Copyright © 2008 Nicolas Kandel # Copyright © 2008 Pascal Halter # diff --git a/radicale/ical.py b/radicale/ical.py index b1567411..f8d51e4a 100644 --- a/radicale/ical.py +++ b/radicale/ical.py @@ -1,7 +1,7 @@ # -*- coding: utf-8 -*- # # This file is part of Radicale Server - Calendar Server -# Copyright © 2008-2010 Guillaume Ayoub +# Copyright © 2008-2011 Guillaume Ayoub # Copyright © 2008 Nicolas Kandel # Copyright © 2008 Pascal Halter # diff --git a/radicale/xmlutils.py b/radicale/xmlutils.py index d300e0ed..ed986f1d 100644 --- a/radicale/xmlutils.py +++ b/radicale/xmlutils.py @@ -1,7 +1,7 @@ # -*- coding: utf-8 -*- # # This file is part of Radicale Server - Calendar Server -# Copyright © 2008-2010 Guillaume Ayoub +# Copyright © 2008-2011 Guillaume Ayoub # Copyright © 2008 Nicolas Kandel # Copyright © 2008 Pascal Halter # diff --git a/setup.py b/setup.py index 70553b1e..2d9b09cf 100755 --- a/setup.py +++ b/setup.py @@ -2,7 +2,7 @@ # -*- coding: utf-8 -*- # # This file is part of Radicale Server - Calendar Server -# Copyright © 2009-2010 Guillaume Ayoub +# Copyright © 2009-2011 Guillaume Ayoub # # This library is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by From 9874129bbba7a7a3c7500ed91073e7241d1305ea Mon Sep 17 00:00:00 2001 From: Guillaume Ayoub Date: Thu, 27 Jan 2011 00:04:30 +0100 Subject: [PATCH 09/12] Add simple support for calendar-user-address-set (references #181) --- radicale/xmlutils.py | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/radicale/xmlutils.py b/radicale/xmlutils.py index ed986f1d..af7e665c 100644 --- a/radicale/xmlutils.py +++ b/radicale/xmlutils.py @@ -140,11 +140,10 @@ def propfind(path, xml_request, calendar, depth): tag = ET.Element(_tag("D", "href")) tag.text = path element.append(tag) - elif tag == _tag("D", "principal-collection-set"): - tag = ET.Element(_tag("D", "href")) - tag.text = path - element.append(tag) - elif tag == _tag("C", "calendar-home-set"): + elif tag in ( + _tag("D", "principal-collection-set"), + _tag("C", "calendar-user-address-set"), + _tag("C", "calendar-home-set")): tag = ET.Element(_tag("D", "href")) tag.text = path element.append(tag) From c38c79a738dadcf4692ab948c7c9f3f60e4987cc Mon Sep 17 00:00:00 2001 From: Guillaume Ayoub Date: Fri, 28 Jan 2011 01:52:28 +0100 Subject: [PATCH 10/12] Fix typo --- radicale.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/radicale.py b/radicale.py index 704bcd63..03f6a147 100755 --- a/radicale.py +++ b/radicale.py @@ -28,7 +28,7 @@ """ Radicale Server entry point. -Launch the Radicale Serve according to configuration and command-line +Launch the Radicale Server according to configuration and command-line arguments. """ From 9b535ba4b2707c324735d9c6bc0894ca2a41e159 Mon Sep 17 00:00:00 2001 From: Guillaume Ayoub Date: Tue, 1 Feb 2011 17:01:30 +0100 Subject: [PATCH 11/12] Add support for MKCALENDAR requests --- radicale/__init__.py | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/radicale/__init__.py b/radicale/__init__.py index c23a98cb..ad943181 100644 --- a/radicale/__init__.py +++ b/radicale/__init__.py @@ -204,11 +204,18 @@ class CalendarHTTPHandler(server.BaseHTTPRequestHandler): # No item or ETag precondition not verified, do not delete item self.send_response(client.PRECONDITION_FAILED) + @check_rights + def do_MKCALENDAR(self): + """Manage MKCALENDAR request.""" + self.send_response(client.CREATED) + self.end_headers() + def do_OPTIONS(self): """Manage OPTIONS request.""" self.send_response(client.OK) self.send_header( - "Allow", "DELETE, HEAD, GET, OPTIONS, PROPFIND, PUT, REPORT") + "Allow", "DELETE, HEAD, GET, MKCALENDAR, " + "OPTIONS, PROPFIND, PUT, REPORT") self.send_header("DAV", "1, calendar-access") self.end_headers() From 2e1b51e3c17f622617af9b98d772dee7212d5484 Mon Sep 17 00:00:00 2001 From: Guillaume Ayoub Date: Sat, 12 Feb 2011 12:05:02 +0100 Subject: [PATCH 12/12] Softly ignore /user/ PROPFIND and REPORT requests (references #181) --- radicale/__init__.py | 5 +++++ radicale/xmlutils.py | 26 ++++++++++++++++---------- 2 files changed, 21 insertions(+), 10 deletions(-) diff --git a/radicale/__init__.py b/radicale/__init__.py index ad943181..905257b0 100644 --- a/radicale/__init__.py +++ b/radicale/__init__.py @@ -55,6 +55,11 @@ def _check(request, function): """Check if user has sufficient rights for performing ``request``.""" # ``_check`` decorator can access ``request`` protected functions # pylint: disable=W0212 + + # If we have no calendar, don't check rights + if not request._calendar: + return function(request) + authorization = request.headers.get("Authorization", None) if authorization: challenge = authorization.lstrip("Basic").strip().encode("ascii") diff --git a/radicale/xmlutils.py b/radicale/xmlutils.py index af7e665c..f811f7fe 100644 --- a/radicale/xmlutils.py +++ b/radicale/xmlutils.py @@ -95,12 +95,15 @@ def propfind(path, xml_request, calendar, depth): # Writing answer multistatus = ET.Element(_tag("D", "multistatus")) - if depth == "0": - items = [calendar] + if calendar: + if depth == "0": + items = [calendar] + else: + # depth is 1, infinity or not specified + # we limit ourselves to depth == 1 + items = [calendar] + calendar.events + calendar.todos else: - # depth is 1, infinity or not specified - # we limit ourselves to depth == 1 - items = [calendar] + calendar.events + calendar.todos + items = [] for item in items: is_calendar = isinstance(item, ical.Calendar) @@ -191,12 +194,15 @@ def report(path, xml_request, calendar): prop_list = prop_element.getchildren() props = [prop.tag for prop in prop_list] - if root.tag == _tag("C", "calendar-multiget"): - # Read rfc4791-7.9 for info - hreferences = set((href_element.text for href_element - in root.findall(_tag("D", "href")))) + if calendar: + if root.tag == _tag("C", "calendar-multiget"): + # Read rfc4791-7.9 for info + hreferences = set((href_element.text for href_element + in root.findall(_tag("D", "href")))) + else: + hreferences = (path,) else: - hreferences = (path,) + hreferences = () # Writing answer multistatus = ET.Element(_tag("D", "multistatus"))