def propfind(self, path, collections, request_body, environ): """ Manage PROPFIND request. According to [RFC 4918], it should have the following request body : <D:propfind> <D:prop> ... </D:prop> </D:propfind> It should return the following content : 207 Multi-Status <D:multistatus> <D:response> <D:href>calendar uri</D:href> <D:propstat> <D:prop> ... </D:prop> <D:status>...</D:status> </D:propstat> </D:response> ... </D:multistatus> """ headers = { 'DAV': '1, 2, access-control, calendar-access', 'Content-Type': 'text/xml', } # Read request dom = ET.fromstring(request_body) dprop = dom.find(xmlutils.tag('D', 'prop')) props = [prop.tag for prop in dprop] # Write answer multistatus = ET.Element(xmlutils.tag('D', 'multistatus')) for collection in collections: response = xmlutils.propfind_response(path, collection, props) multistatus.append(response) return 207, headers, [xmlutils.render(multistatus)]
def delete(self, path, collections, request_body, environ): """ Manage DELETE request. The URL contains the element to delete : /path/to/calendar/element-uid.ics : delete an item /path/to/calendar/ : delete the whole calendar """ collection = collections[0] if collection.path == path.strip('/'): # Path match the collection, delete the whole collection item = collection else: # Path match an item, delete the item item = collection.get_item(self.wsgi_name_from_path(path, collection)) if item and environ.get('HTTP_IF_MATCH', item.etag) == item.etag: # No ETag precondition, or precondition verified if item is collection: collection.delete() else: collection.remove(item.name) # Write response body multistatus = ET.Element(xmlutils.tag('D', 'multistatus')) response = ET.Element(xmlutils.tag('D', 'response')) multistatus.append(response) href = ET.Element(xmlutils.tag('D', 'href')) href.text = path response.append(href) status = ET.Element(xmlutils.tag('D', 'status')) status.text = util.http_response(200) response.append(status) return 204, {}, [xmlutils.render(multistatus)] # No item or ETag precondition not verified return 412, {}, []
def report(self, path, collections, request_body, environ): """ Manage REPORT request. According to [RFC 3253], it should return 207 Multi-Status. The request body contains : <C:calendar-multiget / calendar-query> <D:href>...</D:href> <D:prop> ... </D:prop> </C:calendar-multiget / calendar-query> It should returns the following content : <D:multistatus> <D:response> <D:href> <D:propstat> <D:prop> ... </D:prop> <D:status>...</D:status> </D:propstat> </D:response> ... </D:multistatus> """ headers = { 'Content-Type': 'text/xml', } collection = collections[0] # Parse request body dom = ET.fromstring(request_body) dprop = dom.find(xmlutils.tag('D', 'prop')) properties = [prop.tag for prop in dprop] if collection: if dom.tag == xmlutils.tag('C', 'calendar-multiget'): hrefs = set(href.text for href in dom.findall(xmlutils.tag('D', 'href'))) else: hrefs = (path,) else: hrefs = () # Write response body multistatus = ET.Element(xmlutils.tag('D', 'multistatus')) for href in hrefs: name = self.wsgi_name_from_path(href, collection) if name: # The reference is an item path = '/'.join(href.split('/')[:-1]) + '/' items = (item for item in collection.items if item.name == name) else: # The reference is a collection path = href items = collection.components # Create a response element for all items for item in items: response = ET.Element(xmlutils.tag('D', 'response')) multistatus.append(response) xmlhref = ET.Element(xmlutils.tag('D', 'href')) xmlhref.text = '/'.join([path.rstrip('/'), item.name]) + '.ics' response.append(xmlhref) propstat = ET.Element(xmlutils.tag('D', 'propstat')) response.append(propstat) prop = ET.Element(xmlutils.tag('D', 'prop')) propstat.append(prop) for tag in properties: element = ET.Element(tag) if tag == xmlutils.tag('D', 'getetag'): element.text = item.etag elif tag == xmlutils.tag('C', 'calendar-data'): if isinstance(item, ical.Component): element.text = item.to_ical() prop.append(element) status = ET.Element(xmlutils.tag('D', 'status')) status.text = util.http_response(200) propstat.append(status) return 207, headers, [xmlutils.render(multistatus)]