diff --git a/radicale/__init__.py b/radicale/__init__.py index 641fba5..ef11e52 100644 --- a/radicale/__init__.py +++ b/radicale/__init__.py @@ -188,6 +188,8 @@ class CalendarHTTPHandler(server.BaseHTTPRequestHandler): # ``normpath`` should clean malformed and malicious request paths attributes = posixpath.normpath(self.path.strip("/")).split("/") if attributes: + if attributes[-1].endswith('.ics'): + attributes.pop() path = "/".join(attributes[:min(len(attributes), 2)]) return ical.Calendar(path) @@ -231,7 +233,7 @@ class CalendarHTTPHandler(server.BaseHTTPRequestHandler): @check_rights def do_HEAD(self): """Manage HEAD request.""" - item_name = xmlutils.name_from_path(self.path) + item_name = xmlutils.name_from_path(self.path, self._calendar) if item_name: # Get calendar item item = self._calendar.get_item(item_name) @@ -262,7 +264,8 @@ class CalendarHTTPHandler(server.BaseHTTPRequestHandler): @check_rights def do_DELETE(self): """Manage DELETE request.""" - item = self._calendar.get_item(xmlutils.name_from_path(self.path)) + item = self._calendar.get_item( + xmlutils.name_from_path(self.path, self._calendar)) if item and self.headers.get("If-Match", item.etag) == item.etag: # No ETag precondition or precondition verified, delete item self._answer = xmlutils.delete(self.path, self._calendar) @@ -310,7 +313,7 @@ class CalendarHTTPHandler(server.BaseHTTPRequestHandler): @check_rights def do_PUT(self): """Manage PUT request.""" - item_name = xmlutils.name_from_path(self.path) + item_name = xmlutils.name_from_path(self.path, self._calendar) item = self._calendar.get_item(item_name) if (not item and not self.headers.get("If-Match")) or \ (item and self.headers.get("If-Match", item.etag) == item.etag): diff --git a/radicale/ical.py b/radicale/ical.py index fcfbdaf..df1a053 100644 --- a/radicale/ical.py +++ b/radicale/ical.py @@ -144,6 +144,7 @@ class Calendar(object): split_path = path.split("/") self.owner = split_path[0] if len(split_path) > 1 else None self.path = os.path.join(FOLDER, path.replace("/", os.path.sep)) + self.local_path = path @staticmethod def _parse(text, item_types, name=None): diff --git a/radicale/xmlutils.py b/radicale/xmlutils.py index 48f494c..1196883 100644 --- a/radicale/xmlutils.py +++ b/radicale/xmlutils.py @@ -48,10 +48,11 @@ def _response(code): return "HTTP/1.1 %i %s" % (code, client.responses[code]) -def name_from_path(path): +def name_from_path(path, calendar): """Return Radicale item name from ``path``.""" + calendar_parts = calendar.local_path.strip("/").split("/") path_parts = path.strip("/").split("/") - return path_parts[-1] if len(path_parts) >= 2 else None + return path_parts[-1] if (len(path_parts) - len(calendar_parts)) else None def delete(path, calendar): @@ -61,7 +62,7 @@ def delete(path, calendar): """ # Reading request - calendar.remove(name_from_path(path)) + calendar.remove(name_from_path(path, calendar)) # Writing answer multistatus = ET.Element(_tag("D", "multistatus")) @@ -180,7 +181,7 @@ def propfind(path, xml_request, calendar, depth): def put(path, ical_request, calendar): """Read PUT requests.""" - name = name_from_path(path) + name = name_from_path(path, calendar) if name in (item.name for item in calendar.items): # PUT is modifying an existing item calendar.replace(name, ical_request) @@ -217,7 +218,7 @@ def report(path, xml_request, calendar): for hreference in hreferences: # Check if the reference is an item or a calendar - name = name_from_path(hreference) + name = name_from_path(hreference, calendar) if name: # Reference is an item path = "/".join(hreference.split("/")[:-1]) + "/"