def move(self, environ, collections, content, user): """Manage MOVE request.""" from_collection = collections[0] from_name = xmlutils.name_from_path( environ["PATH_INFO"], from_collection) if from_name: item = from_collection.get_item(from_name) if item: # Move the item to_url_parts = urlparse(environ["HTTP_DESTINATION"]) if to_url_parts.netloc == environ["HTTP_HOST"]: to_url = to_url_parts.path to_path, to_name = to_url.rstrip("/").rsplit("/", 1) to_collection = ical.Collection.from_path( to_path, depth="0")[0] to_collection.append(to_name, item.text) from_collection.remove(from_name) return client.CREATED, {}, None else: # Remote destination server, not supported return client.BAD_GATEWAY, {}, None else: # No item found return client.GONE, {}, None else: # Moving collections, not supported return client.FORBIDDEN, {}, None
def delete(self, environ, read_collections, write_collections, content, user): """Manage DELETE request.""" if not len(write_collections): return NOT_ALLOWED collection = write_collections[0] if collection.path == environ["PATH_INFO"].strip("/"): # Path matching the collection, the collection must be deleted item = collection else: # Try to get an item matching the path item = collection.get_item( xmlutils.name_from_path(environ["PATH_INFO"], collection)) if item: # Evolution bug workaround etag = environ.get("HTTP_IF_MATCH", item.etag).replace("\\", "") if etag == item.etag: # No ETag precondition or precondition verified, delete item answer = xmlutils.delete(environ["PATH_INFO"], collection) return client.OK, {}, answer # No item or ETag precondition not verified, do not delete item return client.PRECONDITION_FAILED, {}, None
def do_GET(self, environ, read_collections, write_collections, content, user): """Manage GET request. In Radicale, GET requests create collections when the URL is not available. This is useful for clients with no MKCOL or MKCALENDAR support. """ _logger.info('do_GET %s %s' % (content, user)) # Display a "Radicale works!" message if the root URL is requested if environ["PATH_INFO"] == "/": headers = {"Content-type": "text/html"} answer = b"<!DOCTYPE html>\n<title>Radicale</title>Radicale works!" return client.OK, headers, answer if not len(read_collections): return NOT_ALLOWED collection = read_collections[0] item_name = xmlutils.name_from_path(environ["PATH_INFO"], collection) if item_name: # Get collection item item = collection.items.get(item_name) if item: items = [item] if collection.resource_type == "calendar": items.extend(collection.timezones) answer_text = ical.serialize(collection.tag, collection.headers, items) etag = item.etag else: return client.NOT_FOUND, {}, None else: # Create the collection if it does not exist if not collection.exists: if collection in write_collections: log.LOGGER.debug("Creating collection %s" % collection.name) collection.write() else: log.LOGGER.debug( "Collection %s not available and could not be created " "due to missing write rights" % collection.name) return NOT_ALLOWED # Get whole collection answer_text = collection.text etag = collection.etag headers = { "Content-Type": collection.mimetype, "Last-Modified": collection.last_modified, "ETag": etag } answer = answer_text.encode(self.encoding) return client.OK, headers, answer
def get(self, environ, collections, content, user): """Manage GET request.""" # Display a "Radicale works!" message if the root URL is requested if environ["PATH_INFO"] == "/": headers = {"Content-type": "text/html"} answer = "<!DOCTYPE html>\n<title>Radicale</title>Radicale works!" return client.OK, headers, answer collection = collections[0] item_name = xmlutils.name_from_path(environ["PATH_INFO"], collection) if item_name: # Get collection item item = collection.get_item(item_name) if item: items = collection.timezones items.append(item) answer_text = ical.serialize(collection.tag, collection.headers, items) etag = item.etag else: return client.GONE, {}, None else: # Get whole collection answer_text = collection.text etag = collection.etag headers = { "Content-Type": collection.mimetype, "Last-Modified": collection.last_modified, "ETag": etag } answer = answer_text.encode(self.encoding) return client.OK, headers, answer
def move(self, environ, calendars, content, user): """Manage MOVE request.""" from_calendar = calendars[0] from_name = xmlutils.name_from_path( environ["PATH_INFO"], from_calendar) if from_name: item = from_calendar.get_item(from_name) if item: # Move the item to_url_parts = urlparse(environ["HTTP_DESTINATION"]) if to_url_parts.netloc == environ["HTTP_HOST"]: to_path, to_name = posixpath.split(to_url_parts.path) to_calendar = ical.Calendar.from_path(to_path) to_calendar.append(to_name, item.text) from_calendar.remove(from_name) return client.CREATED, {}, None else: # Remote destination server, not supported return client.BAD_GATEWAY, {}, None else: # No item found return client.GONE, {}, None else: # Moving calendars, not supported return client.FORBIDDEN, {}, None
def move(self, environ, collections, content, user): """Manage MOVE request.""" from_collection = collections[0] from_name = xmlutils.name_from_path(environ["PATH_INFO"], from_collection) if from_name: item = from_collection.get_item(from_name) if item: # Move the item to_url_parts = urlparse(environ["HTTP_DESTINATION"]) if to_url_parts.netloc == environ["HTTP_HOST"]: to_url = to_url_parts.path to_path, to_name = to_url.rstrip("/").rsplit("/", 1) to_collection = ical.Collection.from_path(to_path, depth="0")[0] to_collection.append(to_name, item.text) from_collection.remove(from_name) return client.CREATED, {}, None else: # Remote destination server, not supported return client.BAD_GATEWAY, {}, None else: # No item found return client.GONE, {}, None else: # Moving collections, not supported return client.FORBIDDEN, {}, None
def put(self, environ, read_collections, write_collections, content, user): """Manage PUT request.""" if not len(write_collections): return NOT_ALLOWED collection = write_collections[0] collection.set_mimetype(environ.get("CONTENT_TYPE")) headers = {} item_name = xmlutils.name_from_path(environ["PATH_INFO"], collection) item = collection.get_item(item_name) # Evolution bug workaround etag = environ.get("HTTP_IF_MATCH", "").replace("\\", "") match = environ.get("HTTP_IF_NONE_MATCH", "") == "*" if (not item and not etag) or ( item and ((etag or item.etag) == item.etag) and not match): # PUT allowed in 3 cases # Case 1: No item and no ETag precondition: Add new item # Case 2: Item and ETag precondition verified: Modify item # Case 3: Item and no Etag precondition: Force modifying item xmlutils.put(environ["PATH_INFO"], content, collection) status = client.CREATED # Try to return the etag in the header. # If the added item doesn't have the same name as the one given # by the client, then there's no obvious way to generate an # etag, we can safely ignore it. new_item = collection.get_item(item_name) if new_item: headers["ETag"] = new_item.etag else: # PUT rejected in all other cases status = client.PRECONDITION_FAILED return status, headers, None
def get(self, environ, calendars, content, user): """Manage GET request.""" # Display a "Radicale works!" message if the root URL is requested if environ["PATH_INFO"] == "/": headers = {"Content-type": "text/html"} answer = "<!DOCTYPE html>\n<title>Radicale</title>Radicale works!" return client.OK, headers, answer calendar = calendars[0] item_name = xmlutils.name_from_path(environ["PATH_INFO"], calendar) if item_name: # Get calendar item item = calendar.get_item(item_name) if item: items = calendar.timezones items.append(item) answer_text = ical.serialize( headers=calendar.headers, items=items) etag = item.etag else: return client.GONE, {}, None else: # Get whole calendar answer_text = calendar.text etag = calendar.etag headers = { "Content-Type": "text/calendar", "Last-Modified": calendar.last_modified, "ETag": etag} answer = answer_text.encode(self.encoding) return client.OK, headers, answer
def do_DELETE(self, content, user): """Manage DELETE request.""" _logger.info('do_delete %s %s' % (content, user)) if not len(write_collections): return NOT_ALLOWED collection = write_collections[0] if collection.path == environ["PATH_INFO"].strip("/"): # Path matching the collection, the collection must be deleted item = collection else: # Try to get an item matching the path name = xmlutils.name_from_path(environ["PATH_INFO"], collection) item = collection.items.get(name) if item: # Evolution bug workaround if_match = environ.get("HTTP_IF_MATCH", "*").replace("\\", "") if if_match in ("*", item.etag): # No ETag precondition or precondition verified, delete item answer = xmlutils.delete(environ["PATH_INFO"], collection) return client.OK, {}, answer else: # ETag precondition not verified, do not delete item return client.PRECONDITION_FAILED, {}, None # No item return client.NOT_FOUND, {}, None
def get(self, environ, read_collections, write_collections, content, user): """Manage GET request. In Radicale, GET requests create collections when the URL is not available. This is useful for clients with no MKCOL or MKCALENDAR support. """ # Display a "Radicale works!" message if the root URL is requested if environ["PATH_INFO"] == "/": headers = {"Content-type": "text/html"} answer = b"<!DOCTYPE html>\n<title>Radicale</title>Radicale works!" return client.OK, headers, answer if not len(read_collections): return NOT_ALLOWED collection = read_collections[0] item_name = xmlutils.name_from_path(environ["PATH_INFO"], collection) if item_name: # Get collection item item = collection.get_item(item_name) if item: items = collection.timezones items.append(item) answer_text = ical.serialize( collection.tag, collection.headers, items) etag = item.etag else: return client.GONE, {}, None else: # Create the collection if it does not exist if not collection.exists: if collection in write_collections: log.LOGGER.debug( "Creating collection %s" % collection.name) collection.write() else: log.LOGGER.debug( "Collection %s not available and could not be created " "due to missing write rights" % collection.name) return NOT_ALLOWED # Get whole collection answer_text = collection.text etag = collection.etag headers = { "Content-Type": collection.mimetype, "Last-Modified": collection.last_modified, "ETag": etag} answer = answer_text.encode(self.encoding) return client.OK, headers, answer
def delete(self, environ, calendars, content, user): """Manage DELETE request.""" calendar = calendars[0] item = calendar.get_item( xmlutils.name_from_path(environ["PATH_INFO"], calendar)) if item and environ.get("HTTP_IF_MATCH", item.etag) == item.etag: # No ETag precondition or precondition verified, delete item answer = xmlutils.delete(environ["PATH_INFO"], calendar) status = client.NO_CONTENT else: # No item or ETag precondition not verified, do not delete item answer = None status = client.PRECONDITION_FAILED return status, {}, answer
def put(self, environ, calendars, content, user): """Manage PUT request.""" calendar = calendars[0] headers = {} item_name = xmlutils.name_from_path(environ["PATH_INFO"], calendar) item = calendar.get_item(item_name) if (not item and not environ.get("HTTP_IF_MATCH")) or ( item and environ.get("HTTP_IF_MATCH", item.etag) == item.etag): # PUT allowed in 3 cases # Case 1: No item and no ETag precondition: Add new item # Case 2: Item and ETag precondition verified: Modify item # Case 3: Item and no Etag precondition: Force modifying item xmlutils.put(environ["PATH_INFO"], content, calendar) status = client.CREATED headers["ETag"] = calendar.get_item(item_name).etag else: # PUT rejected in all other cases status = client.PRECONDITION_FAILED return status, headers, None
def put(self, environ, collections, content, user): """Manage PUT request.""" collection = collections[0] collection.set_mimetype(environ.get("CONTENT_TYPE")) headers = {} item_name = xmlutils.name_from_path(environ["PATH_INFO"], collection) item = collection.get_item(item_name) if (not item and not environ.get("HTTP_IF_MATCH")) or ( item and environ.get("HTTP_IF_MATCH", item.etag) == item.etag): # PUT allowed in 3 cases # Case 1: No item and no ETag precondition: Add new item # Case 2: Item and ETag precondition verified: Modify item # Case 3: Item and no Etag precondition: Force modifying item xmlutils.put(environ["PATH_INFO"], content, collection) status = client.CREATED headers["ETag"] = collection.get_item(item_name).etag else: # PUT rejected in all other cases status = client.PRECONDITION_FAILED return status, headers, None
def delete(self, environ, collections, content, user): """Manage DELETE request.""" collection = collections[0] if collection.path == environ["PATH_INFO"].strip("/"): # Path matching the collection, the collection must be deleted item = collection else: # Try to get an item matching the path item = collection.get_item( xmlutils.name_from_path(environ["PATH_INFO"], collection)) if item and environ.get("HTTP_IF_MATCH", item.etag) == item.etag: # No ETag precondition or precondition verified, delete item answer = xmlutils.delete(environ["PATH_INFO"], collection) status = client.NO_CONTENT else: # No item or ETag precondition not verified, do not delete item answer = None status = client.PRECONDITION_FAILED return status, {}, answer
def do_MOVE(self, environ, read_collections, write_collections, content, user): """Manage MOVE request.""" _logger.info('do_MOVE %s %s' % (content, user)) if not len(write_collections): return NOT_ALLOWED from_collection = write_collections[0] from_name = xmlutils.name_from_path(environ["PATH_INFO"], from_collection) if from_name: item = from_collection.items.get(from_name) if item: # Move the item to_url_parts = urlparse(environ["HTTP_DESTINATION"]) if to_url_parts.netloc == environ["HTTP_HOST"]: to_url = to_url_parts.path to_path, to_name = to_url.rstrip("/").rsplit("/", 1) to_collection = ical.Collection.from_path(to_path, depth="0")[0] if to_collection in write_collections: to_collection.append(to_name, item.text) from_collection.remove(from_name) return client.CREATED, {}, None else: return NOT_ALLOWED else: # Remote destination server, not supported return client.BAD_GATEWAY, {}, None else: # No item found return client.GONE, {}, None else: # Moving collections, not supported return client.FORBIDDEN, {}, None
def do_PUT(self, environ, read_collections, write_collections, content, user): """Manage PUT request.""" _logger.info('do_PUT %s %s' % (content, user)) if not len(write_collections): return NOT_ALLOWED collection = write_collections[0] collection.set_mimetype(environ.get("CONTENT_TYPE")) headers = {} item_name = xmlutils.name_from_path(environ["PATH_INFO"], collection) item = collection.items.get(item_name) # Evolution bug workaround etag = environ.get("HTTP_IF_MATCH", "").replace("\\", "") match = environ.get("HTTP_IF_NONE_MATCH", "") == "*" if (not item and not etag) or (item and ((etag or item.etag) == item.etag) and not match): # PUT allowed in 3 cases # Case 1: No item and no ETag precondition: Add new item # Case 2: Item and ETag precondition verified: Modify item # Case 3: Item and no Etag precondition: Force modifying item xmlutils.put(environ["PATH_INFO"], content, collection) status = client.CREATED # Try to return the etag in the header. # If the added item doesn't have the same name as the one given # by the client, then there's no obvious way to generate an # etag, we can safely ignore it. new_item = collection.items.get(item_name) if new_item: headers["ETag"] = new_item.etag else: # PUT rejected in all other cases status = client.PRECONDITION_FAILED return status, headers, None
def put(self, environ, collections, content, user): """Manage PUT request.""" collection = collections[0] collection.set_mimetype(environ.get("CONTENT_TYPE")) headers = {} item_name = xmlutils.name_from_path(environ["PATH_INFO"], collection) item = collection.get_item(item_name) # Evolution bug workaround etag = environ.get("HTTP_IF_MATCH", "").replace("\\", "") if (not item and not etag) or ( item and ((etag or item.etag) == item.etag)): # PUT allowed in 3 cases # Case 1: No item and no ETag precondition: Add new item # Case 2: Item and ETag precondition verified: Modify item # Case 3: Item and no Etag precondition: Force modifying item xmlutils.put(environ["PATH_INFO"], content, collection) status = client.CREATED headers["ETag"] = collection.get_item(item_name).etag else: # PUT rejected in all other cases status = client.PRECONDITION_FAILED return status, headers, None