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

View File

@ -174,6 +174,12 @@ class Calendar(object):
return items 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): def append(self, name, text):
"""Append items from ``text`` to calendar. """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]) 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 Radicale item name from ``path``."""
return path.split("/")[-1] return path.split("/")[-1]
@ -62,7 +62,7 @@ def delete(path, calendar):
""" """
# Reading request # Reading request
calendar.remove(_name_from_path(path)) calendar.remove(name_from_path(path))
# Writing answer # Writing answer
multistatus = ET.Element(_tag("D", "multistatus")) multistatus = ET.Element(_tag("D", "multistatus"))
@ -142,7 +142,7 @@ def propfind(path, xml_request, calendar):
def put(path, ical_request, calendar): def put(path, ical_request, calendar):
"""Read PUT requests.""" """Read PUT requests."""
name = _name_from_path(path) name = name_from_path(path)
if name in (item.name for item in calendar.items): if name in (item.name for item in calendar.items):
# PUT is modifying an existing item # PUT is modifying an existing item
calendar.replace(name, ical_request) calendar.replace(name, ical_request)
@ -176,7 +176,7 @@ def report(path, xml_request, calendar):
for hreference in hreferences: for hreference in hreferences:
# Check if the reference is an item or a calendar # Check if the reference is an item or a calendar
name = hreference.split("/")[-1] name = name_from_path(hreference)
if name: if name:
# Reference is an item # Reference is an item
path = "/".join(hreference.split("/")[:-1]) + "/" path = "/".join(hreference.split("/")[:-1]) + "/"