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 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 text(self): components = ( ical.Timezone, ical.Event, ical.Todo, ical.Journal, ical.Card) items = set() for item in DBItem.objects.filter(collection__path=self.path): items.update(self._parse(item.text, components)) return ical.serialize( self.tag, self.headers, sorted(items, key=lambda x: x.name))
def append(self, name, text): new_items = self._parse(text, ICAL_TYPES, name) for new_item in new_items.values(): collection, ccreated = DBCollection.objects.get_or_create( path=self.path, parent_path=os.path.dirname(self.path)) item, icreated = DBItem.objects.get_or_create( collection=collection, name=name) item.text = ical.serialize( self.tag, self.headers, [new_item] + self.timezones) item.save()
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 write(self, headers=None, items=None): headers = headers or self.headers items = items if items is not None else self.items timezones = list(set(i for i in items if isinstance(i, ical.Timezone))) components = [i for i in items if isinstance(i, ical.Component)] for component in components: text = ical.serialize(self.tag, headers, [component] + timezones) collection, created = DBCollection.objects.get_or_create( path=self.path, parent_path='/'.join(self.path.split('/')[:-1])) item, created = DBItem.objects.get_or_create( collection=collection, name=component.name) item.text = text item.save()
def test_serialization(self): name = '20160729T101032Z-9313-1000-4291-10_localhost-20160729T101116Z.ics' for input_text, stored_text in self.DATA_CASES: items = ical.Collection._parse(input_text, ICAL_TYPES, name) self.assertEqual(name in items, True) timezones = list(filter( lambda x: x.tag == ical.Timezone.tag, items.values())) serialized_text = ical.serialize( self.TAG, self.HEADERS, [items[name]] + timezones) self.assertEqual(serialized_text, stored_text) items2 = ical.Collection._parse(serialized_text, ICAL_TYPES, name) self.assertEqual(name in items2, True)
def test_serialization(self): name = '20160729T101032Z-9313-1000-4291-10_localhost-20160729T101116Z.ics' for input_text, stored_text in self.DATA_CASES: items = ical.Collection._parse(input_text, ICAL_TYPES, name) self.assertEqual(name in items, True) timezones = list( filter(lambda x: x.tag == ical.Timezone.tag, items.values())) serialized_text = ical.serialize(self.TAG, self.HEADERS, [items[name]] + timezones) self.assertEqual(serialized_text, stored_text) items2 = ical.Collection._parse(serialized_text, ICAL_TYPES, name) self.assertEqual(name in items2, True)
def append(self, name, text): new_items = self._parse(text, ICAL_TYPES, name) timezones = list( filter(lambda x: x.tag == ical.Timezone.tag, new_items.values())) for new_item in new_items.values(): if new_item.tag == ical.Timezone.tag: continue collection, ccreated = DBCollection.objects.get_or_create( path=self.path, parent_path=os.path.dirname(self.path)) item, icreated = DBItem.objects.get_or_create( collection=collection, name=name) item.text = ical.serialize(self.tag, self.headers, [new_item] + timezones) item.save()
def append(self, name, text): new_items = self._parse(text, ICAL_TYPES, name) timezones = list(filter( lambda x: x.tag == ical.Timezone.tag, new_items.values())) for new_item in new_items.values(): if new_item.tag == ical.Timezone.tag: continue collection, ccreated = DBCollection.objects.get_or_create( path=self.path, parent_path=os.path.dirname(self.path)) item, icreated = DBItem.objects.get_or_create( collection=collection, name=name) item.text = ical.serialize( self.tag, self.headers, [new_item] + timezones) item.save()
def report(path, xml_request, collection): """Read and answer REPORT requests. Read rfc3253-3.6 for info. """ # Reading request root = ET.fromstring(xml_request.encode("utf8")) prop_element = root.find(_tag("D", "prop")) props = [prop.tag for prop in prop_element] if collection: if root.tag in (_tag("C", "calendar-multiget"), _tag("CR", "addressbook-multiget")): # Read rfc4791-7.9 for info hreferences = set(href_element.text for href_element in root.findall(_tag("D", "href"))) else: hreferences = (path,) else: hreferences = () # Writing answer multistatus = ET.Element(_tag("D", "multistatus")) collection_tag = collection.tag collection_items = collection.items collection_headers = collection.headers collection_timezones = collection.timezones for hreference in hreferences: # Check if the reference is an item or a collection name = name_from_path(hreference, collection) if name: # Reference is an item path = "/".join(hreference.split("/")[:-1]) + "/" items = (item for item in collection_items if item.name == name) else: # Reference is a collection path = hreference items = collection.components for item in items: response = ET.Element(_tag("D", "response")) multistatus.append(response) href = ET.Element(_tag("D", "href")) href.text = "%s/%s" % (path.rstrip("/"), item.name) response.append(href) propstat = ET.Element(_tag("D", "propstat")) response.append(propstat) prop = ET.Element(_tag("D", "prop")) propstat.append(prop) for tag in props: element = ET.Element(tag) if tag == _tag("D", "getetag"): element.text = item.etag elif tag in (_tag("C", "calendar-data"), _tag("CR", "address-data")): if isinstance(item, ical.Component): element.text = ical.serialize(collection_tag, collection_headers, collection_timezones + [item]) prop.append(element) status = ET.Element(_tag("D", "status")) status.text = _response(200) propstat.append(status) return _pretty_xml(multistatus)
def _propfind_response(path, item, props, user): """Build and return a PROPFIND response.""" is_collection = isinstance(item, ical.Collection) if is_collection: with item.props as properties: collection_props = properties response = ET.Element(_tag("D", "response")) href = ET.Element(_tag("D", "href")) uri = item.url if is_collection else "%s/%s" % (path, item.name) href.text = uri.replace("//", "/") response.append(href) propstat404 = ET.Element(_tag("D", "propstat")) propstat200 = ET.Element(_tag("D", "propstat")) response.append(propstat200) prop200 = ET.Element(_tag("D", "prop")) propstat200.append(prop200) prop404 = ET.Element(_tag("D", "prop")) propstat404.append(prop404) for tag in props: element = ET.Element(tag) is404 = False if tag == _tag("D", "getetag"): element.text = item.etag elif tag == _tag("D", "principal-URL"): tag = ET.Element(_tag("D", "href")) tag.text = path element.append(tag) elif tag in ( _tag("D", "principal-collection-set"), _tag("C", "calendar-user-address-set"), _tag("CR", "addressbook-home-set"), _tag("C", "calendar-home-set"), ): tag = ET.Element(_tag("D", "href")) tag.text = path element.append(tag) elif tag == _tag("C", "supported-calendar-component-set"): # This is not a Todo # pylint: disable=W0511 for component in ("VTODO", "VEVENT", "VJOURNAL"): comp = ET.Element(_tag("C", "comp")) comp.set("name", component) element.append(comp) # pylint: enable=W0511 elif tag == _tag("D", "current-user-principal") and user: tag = ET.Element(_tag("D", "href")) tag.text = "/%s/" % user element.append(tag) elif tag == _tag("D", "current-user-privilege-set"): privilege = ET.Element(_tag("D", "privilege")) privilege.append(ET.Element(_tag("D", "all"))) privilege.append(ET.Element(_tag("D", "read"))) privilege.append(ET.Element(_tag("D", "write"))) privilege.append(ET.Element(_tag("D", "write-properties"))) privilege.append(ET.Element(_tag("D", "write-content"))) element.append(privilege) elif tag == _tag("D", "supported-report-set"): for report_name in ( "principal-property-search", "sync-collection" "expand-property", "principal-search-property-set", ): supported = ET.Element(_tag("D", "supported-report")) report_tag = ET.Element(_tag("D", "report")) report_tag.text = report_name supported.append(report_tag) element.append(supported) elif is_collection: if tag == _tag("D", "getcontenttype"): element.text = item.mimetype elif tag == _tag("D", "resourcetype"): if item.is_principal: tag = ET.Element(_tag("D", "principal")) element.append(tag) if item.is_leaf(item.path): tag = ET.Element(_tag("C", item.resource_type)) element.append(tag) if not item.exists and item.resource_type: # Collection not stored yet, but guessed resource type tag = ET.Element(_tag("C", item.resource_type)) element.append(tag) tag = ET.Element(_tag("D", "collection")) element.append(tag) elif tag == _tag("D", "owner") and item.owner_url: element.text = item.owner_url elif tag == _tag("CS", "getctag"): element.text = item.etag elif tag == _tag("C", "calendar-timezone"): element.text = ical.serialize(item.tag, item.headers, item.timezones) else: human_tag = _tag_from_clark(tag) if human_tag in collection_props: element.text = collection_props[human_tag] else: is404 = True # Not for collections elif tag == _tag("D", "getcontenttype"): element.text = "%s; component=%s" % (item.mimetype, item.tag.lower()) elif tag == _tag("D", "resourcetype"): # resourcetype must be returned empty for non-collection elements pass else: is404 = True if is404: prop404.append(element) else: prop200.append(element) status200 = ET.Element(_tag("D", "status")) status200.text = _response(200) propstat200.append(status200) status404 = ET.Element(_tag("D", "status")) status404.text = _response(404) propstat404.append(status404) if len(prop404): response.append(propstat404) return response
def text(self): return ical.serialize(self.tag, self.headers, self.items.values())
def text(self): return ical.serialize(self.tag, self.headers, self.components)
def _propfind_response(path, item, props, user): """Build and return a PROPFIND response.""" is_collection = isinstance(item, ical.Collection) if is_collection: with item.props as properties: collection_props = properties response = ET.Element(_tag("D", "response")) href = ET.Element(_tag("D", "href")) uri = item.url if is_collection else "%s/%s" % (path, item.name) href.text = uri.replace("//", "/") response.append(href) propstat404 = ET.Element(_tag("D", "propstat")) propstat200 = ET.Element(_tag("D", "propstat")) response.append(propstat200) prop200 = ET.Element(_tag("D", "prop")) propstat200.append(prop200) prop404 = ET.Element(_tag("D", "prop")) propstat404.append(prop404) for tag in props: element = ET.Element(tag) is404 = False if tag == _tag("D", "getetag"): element.text = item.etag elif tag == _tag("D", "principal-URL"): tag = ET.Element(_tag("D", "href")) tag.text = path element.append(tag) elif tag in (_tag("D", "principal-collection-set"), _tag("C", "calendar-user-address-set"), _tag("CR", "addressbook-home-set"), _tag("C", "calendar-home-set")): tag = ET.Element(_tag("D", "href")) tag.text = path element.append(tag) elif tag == _tag("C", "supported-calendar-component-set"): # This is not a Todo # pylint: disable=W0511 for component in ("VTODO", "VEVENT", "VJOURNAL"): comp = ET.Element(_tag("C", "comp")) comp.set("name", component) element.append(comp) # pylint: enable=W0511 elif tag == _tag("D", "current-user-principal") and user: tag = ET.Element(_tag("D", "href")) tag.text = '/%s/' % user element.append(tag) elif tag == _tag("D", "current-user-privilege-set"): privilege = ET.Element(_tag("D", "privilege")) privilege.append(ET.Element(_tag("D", "all"))) element.append(privilege) elif tag == _tag("D", "supported-report-set"): for report_name in ("principal-property-search", "sync-collection" "expand-property", "principal-search-property-set"): supported = ET.Element(_tag("D", "supported-report")) report_tag = ET.Element(_tag("D", "report")) report_tag.text = report_name supported.append(report_tag) element.append(supported) elif is_collection: if tag == _tag("D", "getcontenttype"): element.text = item.mimetype elif tag == _tag("D", "resourcetype"): if item.is_principal: tag = ET.Element(_tag("D", "principal")) element.append(tag) else: tag = ET.Element(_tag("C", item.resource_type)) element.append(tag) tag = ET.Element(_tag("D", "collection")) element.append(tag) elif tag == _tag("D", "owner") and item.owner_url: element.text = item.owner_url elif tag == _tag("CS", "getctag"): element.text = item.etag elif tag == _tag("C", "calendar-timezone"): element.text = ical.serialize(item.tag, item.headers, item.timezones) else: human_tag = _tag_from_clark(tag) if human_tag in collection_props: element.text = collection_props[human_tag] else: is404 = True # Not for collections elif tag == _tag("D", "getcontenttype"): element.text = "%s; component=%s" % (item.mimetype, item.tag.lower()) elif tag == _tag("D", "resourcetype"): # resourcetype must be returned empty for non-collection elements pass else: is404 = True if is404: prop404.append(element) else: prop200.append(element) status200 = ET.Element(_tag("D", "status")) status200.text = _response(200) propstat200.append(status200) status404 = ET.Element(_tag("D", "status")) status404.text = _response(404) propstat404.append(status404) if len(prop404): response.append(propstat404) return response
def append(self, name, text): import pydevd pydevd.settrace('192.168.33.1', 5678) new_items = self._parse(text, ICAL_TYPES, name) timezones = list(filter( lambda x: x.tag == ical.Timezone.tag, new_items.values())) request = self._getRequestFromUrl(self.path) for new_item in new_items.values(): if new_item.tag == ical.Timezone.tag: continue if new_item.name not in self.items: self.items[new_item.name] = new_item text = ical.serialize(self.tag, self.headers, [new_item] + timezones) cal = vobject.readOne(text) # close ticket if hasattr(cal.vtodo, 'status') and cal.vtodo.status.value == 'COMPLETED': ticket = get_ticket_model() try: flow_end = get_flow_end() resolution = get_default_resolution() close_comment = _('closed via CalDAV') tic = ticket.objects.get(uuid=cal.vtodo.uid.value) tic.resolution = resolution tic.closed = True tic.close_date = timezone.now() tic.state = flow_end tic.save(user=request.user) com = tickets_comments() com.comment = _('ticket closed - resolution: %(resolution)s\n\n%(comment)s') % {'resolution': resolution.name, 'comment': close_comment} com.ticket = tic com.action = 1 com.save(user=request.user) check_references(request, com) touch_ticket(request.user, tic.id) add_history(request, tic, 1, close_comment) mail_comment(request, com.pk) jabber_comment(request, com.pk) except Exception: pass # change or new else: params = { 'caption': cal.vtodo.summary.value, 'description': cal.vtodo.description.value if hasattr(cal.vtodo, 'description') else None, 'uuid': cal.vtodo.uid.value, 'show_start': cal.vtodo.due.value if hasattr(cal.vtodo, 'due') else None, 'priority': convertPrio(cal.vtodo.priority.value) if hasattr(cal.vtodo, 'priority') else None } fakePOST = QueryDict(mutable=True) fakePOST.update(params) form = SimpleTickets(fakePOST) if form.is_valid(): cd = form.cleaned_data ticket = get_ticket_model() # change ticket try: tic = ticket.objects.get(uuid=cal.vtodo.uid.value) tic.caption = cd['caption'] tic.description = cd['description'] tic.priority = cd['priority'] # tic.assigned = cd['assigned'] tic.show_start = cd['show_start'] tic.save(user=request.user) # new ticket except ticket.DoesNotExist: tic = ticket() tic.caption = cd['caption'] tic.description = cd['description'] if 'priority' not in cd or not cd['priority']: if hasattr(settings, 'KEEP_IT_SIMPLE_DEFAULT_PRIORITY') and settings.KEEP_IT_SIMPLE_DEFAULT_PRIORITY: tic.priority_id = settings.KEEP_IT_SIMPLE_DEFAULT_PRIORITY else: tic.priority = cd['priority'] tic.assigned = request.user if hasattr(settings, 'KEEP_IT_SIMPLE_DEFAULT_CUSTOMER') and settings.KEEP_IT_SIMPLE_DEFAULT_CUSTOMER: if settings.KEEP_IT_SIMPLE_DEFAULT_CUSTOMER == -1: tic.customer = request.organisation else: tic.customer_id = settings.KEEP_IT_SIMPLE_DEFAULT_CUSTOME if hasattr(settings, 'KEEP_IT_SIMPLE_DEFAULT_COMPONENT') and settings.KEEP_IT_SIMPLE_DEFAULT_COMPONENT: tic.component_id = settings.KEEP_IT_SIMPLE_DEFAULT_COMPONENT tic.show_start = cd['show_start'] tic.uuid = cal.vtodo.uid.value tic.save(user=request.user) if tic.assigned: touch_ticket(tic.assigned, tic.pk) for ele in form.changed_data: form.initial[ele] = '' remember_changes(request, form, tic) touch_ticket(request.user, tic.pk) mail_ticket(request, tic.pk, form, rcpt=settings.TICKET_NEW_MAIL_RCPT, is_api=True) jabber_ticket(request, tic.pk, form, rcpt=settings.TICKET_NEW_JABBER_RCPT, is_api=True) else: raise Exception(form.errors)
def report(path, xml_request, calendar): """Read and answer REPORT requests. Read rfc3253-3.6 for info. """ # Reading request root = ET.fromstring(xml_request.encode("utf8")) start = end = None expand = limit_recurrence_set = False prop_element = root.find(_tag("D", "prop")) props = [] for prop in prop_element: props.append(prop.tag) for child in prop: if child.tag == _tag("C", "expand"): expand = True elif child.tag == _tag("C", "expand"): expand = limit_recurrence_set = True filter_element = root.find(_tag("C", "filter")) if filter_element is not None: for c in filter_element: for v in c: for filter_ in v: if filter_.tag == _tag("C", "time-range"): if 'start' in filter_.keys(): start = datetime.strptime(filter_.get('start'), '%Y%m%dT%H%M%SZ') if 'end' in filter_.keys(): end = datetime.strptime(filter_.get('end'), '%Y%m%dT%H%M%SZ') if calendar: if root.tag == _tag("C", "calendar-multiget"): # Read rfc4791-7.9 for info hreferences = set( href_element.text for href_element in root.findall(_tag("D", "href"))) else: hreferences = (path,) else: hreferences = () # Writing answer multistatus = ET.Element(_tag("D", "multistatus")) for hreference in hreferences: # Check if the reference is an item or a calendar name = name_from_path(hreference, calendar) if name: # Reference is an item path = "/".join(hreference.split("/")[:-1]) + "/" items = (item for item in calendar.items if item.name == name) else: # Reference is a calendar path = hreference items = calendar.components new_items = [] if expand: # Expand events for item in items: if item.rrule and end: i = -1 for dtstart in rrulestr(item.rrule.rrule, dtstart = item.dtstart): if dtstart >= end: break if not start or dtstart > start: i += 1 text = item.text if i > 0: text = re.sub(r"RRULE:.*\n", r"RECURRENCE-ID:%s\n" % \ item.dtstart.strftime("%Y%m%dT%H%M%SZ"), text) text = re.sub(r"SUMMARY:(.*)\n", r"SUMMARY:\1 (#%d)\n" % (i+1), text) if not limit_recurrence_set: # Remove rrule line text = re.sub(r"RRULE:.*\n", "", text) # Update start and end dates dtend = dtstart + (item.dtend - item.dtstart) text = re.sub(r"DTSTART:.*\n", "DTSTART:%s\n" % \ dtstart.strftime("%Y%m%dT%H%M%SZ"), text) text = re.sub(r"DTEND:.*\n", "DTEND:%s\n" % \ dtend.strftime("%Y%m%dT%H%M%SZ"), text) new_items.append(ical.Event(text, item.name)) else: if (not start or start < item.dtstart) and \ (not end or end > item.dtstart): new_items.append(item) # Order events by start date if len(new_items) > 0: items = sorted(new_items, key=lambda item: item.dtstart) for item in items: response = ET.Element(_tag("D", "response")) multistatus.append(response) href = ET.Element(_tag("D", "href")) href.text = "%s/%s" % (path, item.name) response.append(href) propstat = ET.Element(_tag("D", "propstat")) response.append(propstat) prop = ET.Element(_tag("D", "prop")) propstat.append(prop) for tag in props: element = ET.Element(tag) if tag == _tag("D", "getetag"): element.text = item.etag elif tag == _tag("C", "calendar-data"): if isinstance(item, (ical.Event, ical.Todo, ical.Journal)): element.text = ical.serialize( calendar.headers, calendar.timezones + [item]) prop.append(element) status = ET.Element(_tag("D", "status")) status.text = _response(200) propstat.append(status) return _pretty_xml(multistatus)
def report(path, xml_request, collection): """Read and answer REPORT requests. Read rfc3253-3.6 for info. """ # Reading request root = ET.fromstring(xml_request.encode("utf8")) prop_element = root.find(_tag("D", "prop")) props = [prop.tag for prop in prop_element] if collection: if root.tag in (_tag("C", "calendar-multiget"), _tag("CR", "addressbook-multiget")): # Read rfc4791-7.9 for info hreferences = set( href_element.text for href_element in root.findall(_tag("D", "href"))) else: hreferences = (path, ) else: hreferences = () # Writing answer multistatus = ET.Element(_tag("D", "multistatus")) collection_tag = collection.tag collection_items = collection.items collection_headers = collection.headers collection_timezones = collection.timezones for hreference in hreferences: # Check if the reference is an item or a collection name = name_from_path(hreference, collection) if name: # Reference is an item path = "/".join(hreference.split("/")[:-1]) + "/" items = (item for item in collection_items if item.name == name) else: # Reference is a collection path = hreference items = collection.components for item in items: response = ET.Element(_tag("D", "response")) multistatus.append(response) href = ET.Element(_tag("D", "href")) href.text = "%s/%s" % (path.rstrip("/"), item.name) response.append(href) propstat = ET.Element(_tag("D", "propstat")) response.append(propstat) prop = ET.Element(_tag("D", "prop")) propstat.append(prop) for tag in props: element = ET.Element(tag) if tag == _tag("D", "getetag"): element.text = item.etag elif tag in (_tag("C", "calendar-data"), _tag("CR", "address-data")): if isinstance(item, ical.Component): element.text = ical.serialize( collection_tag, collection_headers, collection_timezones + [item]) prop.append(element) status = ET.Element(_tag("D", "status")) status.text = _response(200) propstat.append(status) return _pretty_xml(multistatus)
def text(self): """ Docs: Collection as plain text. """ return ical.serialize(self.tag, self.headers, self.items.values())