Check ETag before modifying or adding items.

This commit is contained in:
Guillaume Ayoub 2010-04-12 14:43:40 +02:00
parent 71b928d58b
commit f479b4ba67
3 changed files with 31 additions and 17 deletions

View File

@ -153,14 +153,18 @@ class CalendarHTTPHandler(server.BaseHTTPRequestHandler):
@check_rights
def do_DELETE(self):
"""Manage DELETE request."""
# TODO: Check etag before deleting
etag = self.headers.get("If-Match", None)
answer = xmlutils.delete(self.path, self._calendar)
item = self._calendar.get_item(xmlutils.name_from_path(self.path))
if item and self.headers.get("If-Match", item.etag) == item.etag:
# No ETag precondition or precondition verified, delete item
answer = xmlutils.delete(self.path, self._calendar)
self.send_response(client.NO_CONTENT)
self.send_header("Content-Length", len(answer))
self.end_headers()
self.wfile.write(answer)
self.send_response(client.NO_CONTENT)
self.send_header("Content-Length", len(answer))
self.end_headers()
self.wfile.write(answer)
else:
# No item or ETag precondition not verified, do not delete item
self.send_response(client.PRECONDITION_FAILED)
def do_OPTIONS(self):
"""Manage OPTIONS request."""
@ -183,13 +187,17 @@ class CalendarHTTPHandler(server.BaseHTTPRequestHandler):
@check_rights
def do_PUT(self):
"""Manage PUT request."""
# TODO: Check etag before putting
etag = self.headers.get("If-Match", None)
ical_request = self._decode(
self.rfile.read(int(self.headers["Content-Length"])))
xmlutils.put(self.path, ical_request, self._calendar)
item = self._calendar.get_item(xmlutils.name_from_path(self.path))
if not item or self.headers.get("If-Match", item.etag) == item.etag:
# No item, no ETag precondition or precondition verified, put item
ical_request = self._decode(
self.rfile.read(int(self.headers["Content-Length"])))
xmlutils.put(self.path, ical_request, self._calendar)
self.send_response(client.CREATED)
self.send_response(client.CREATED)
else:
# ETag precondition not verified, do not put item
self.send_response(client.PRECONDITION_FAILED)
@check_rights
def do_REPORT(self):

View File

@ -174,6 +174,12 @@ class Calendar(object):
return items
def get_item(self, name):
"""Get calendar item called ``name``."""
for item in self.items:
if item.name == name:
return item
def append(self, name, text):
"""Append items from ``text`` to calendar.

View File

@ -50,7 +50,7 @@ def _response(code):
return "HTTP/1.1 %i %s" % (code, client.responses[code])
def _name_from_path(path):
def name_from_path(path):
"""Return Radicale item name from ``path``."""
return path.split("/")[-1]
@ -62,7 +62,7 @@ def delete(path, calendar):
"""
# Reading request
calendar.remove(_name_from_path(path))
calendar.remove(name_from_path(path))
# Writing answer
multistatus = ET.Element(_tag("D", "multistatus"))
@ -142,7 +142,7 @@ def propfind(path, xml_request, calendar):
def put(path, ical_request, calendar):
"""Read PUT requests."""
name = _name_from_path(path)
name = name_from_path(path)
if name in (item.name for item in calendar.items):
# PUT is modifying an existing item
calendar.replace(name, ical_request)
@ -176,7 +176,7 @@ def report(path, xml_request, calendar):
for hreference in hreferences:
# Check if the reference is an item or a calendar
name = hreference.split("/")[-1]
name = name_from_path(hreference)
if name:
# Reference is an item
path = "/".join(hreference.split("/")[:-1]) + "/"