def xml_item_response(base_prefix, href, found_props=(), not_found_props=(), found_item=True): response = ET.Element(xmlutils.make_tag("D", "response")) href_tag = ET.Element(xmlutils.make_tag("D", "href")) href_tag.text = xmlutils.make_href(base_prefix, href) response.append(href_tag) if found_item: for code, props in ((200, found_props), (404, not_found_props)): if props: propstat = ET.Element(xmlutils.make_tag("D", "propstat")) status = ET.Element(xmlutils.make_tag("D", "status")) status.text = xmlutils.make_response(code) prop_tag = ET.Element(xmlutils.make_tag("D", "prop")) for prop in props: prop_tag.append(prop) propstat.append(prop_tag) propstat.append(status) response.append(propstat) else: status = ET.Element(xmlutils.make_tag("D", "status")) status.text = xmlutils.make_response(404) response.append(status) return response
def xml_item_response(base_prefix, href, found_props=(), not_found_props=(), found_item=True): response = ET.Element(xmlutils.make_clark("D:response")) href_element = ET.Element(xmlutils.make_clark("D:href")) href_element.text = xmlutils.make_href(base_prefix, href) response.append(href_element) if found_item: for code, props in ((200, found_props), (404, not_found_props)): if props: propstat = ET.Element(xmlutils.make_clark("D:propstat")) status = ET.Element(xmlutils.make_clark("D:status")) status.text = xmlutils.make_response(code) prop_element = ET.Element(xmlutils.make_clark("D:prop")) for prop in props: prop_element.append(prop) propstat.append(prop_element) propstat.append(status) response.append(propstat) else: status = ET.Element(xmlutils.make_clark("D:status")) status.text = xmlutils.make_response(404) response.append(status) return response
def xml_proppatch(base_prefix, path, xml_request, collection): """Read and answer PROPPATCH requests. Read rfc4918-9.2 for info. """ multistatus = ET.Element(xmlutils.make_clark("D:multistatus")) response = ET.Element(xmlutils.make_clark("D:response")) multistatus.append(response) href = ET.Element(xmlutils.make_clark("D:href")) href.text = xmlutils.make_href(base_prefix, path) response.append(href) # Create D:propstat element for props with status 200 OK propstat = ET.Element(xmlutils.make_clark("D:propstat")) status = ET.Element(xmlutils.make_clark("D:status")) status.text = xmlutils.make_response(200) props_ok = ET.Element(xmlutils.make_clark("D:prop")) propstat.append(props_ok) propstat.append(status) response.append(propstat) new_props = collection.get_meta() for short_name, value in xmlutils.props_from_request(xml_request).items(): if value is None: with contextlib.suppress(KeyError): del new_props[short_name] else: new_props[short_name] = value props_ok.append(ET.Element(xmlutils.make_clark(short_name))) radicale_item.check_and_sanitize_props(new_props) collection.set_meta(new_props) return multistatus
def xml_add_propstat_to(element, tag, status_number): """Add a PROPSTAT response structure to an element. The PROPSTAT answer structure is defined in rfc4918-9.1. It is added to the given ``element``, for the following ``tag`` with the given ``status_number``. """ propstat = ET.Element(xmlutils.make_tag("D", "propstat")) element.append(propstat) prop = ET.Element(xmlutils.make_tag("D", "prop")) propstat.append(prop) clark_tag = tag if "{" in tag else xmlutils.make_tag(*tag.split(":", 1)) prop_tag = ET.Element(clark_tag) prop.append(prop_tag) status = ET.Element(xmlutils.make_tag("D", "status")) status.text = xmlutils.make_response(status_number) propstat.append(status)
def xml_delete(base_prefix, path, collection, href=None): """Read and answer DELETE requests. Read rfc4918-9.6 for info. """ collection.delete(href) multistatus = ET.Element(xmlutils.make_tag("D", "multistatus")) response = ET.Element(xmlutils.make_tag("D", "response")) multistatus.append(response) href = ET.Element(xmlutils.make_tag("D", "href")) href.text = xmlutils.make_href(base_prefix, path) response.append(href) status = ET.Element(xmlutils.make_tag("D", "status")) status.text = xmlutils.make_response(200) response.append(status) return multistatus
def xml_propfind_response(base_prefix, path, item, props, user, encoding, write=False, propname=False, allprop=False): """Build and return a PROPFIND response.""" if propname and allprop or (props and (propname or allprop)): raise ValueError("Only use one of props, propname and allprops") is_collection = isinstance(item, storage.BaseCollection) if is_collection: is_leaf = item.get_meta("tag") in ("VADDRESSBOOK", "VCALENDAR") collection = item else: collection = item.collection response = ET.Element(xmlutils.make_clark("D:response")) href = ET.Element(xmlutils.make_clark("D:href")) if is_collection: # Some clients expect collections to end with / uri = pathutils.unstrip_path(item.path, True) else: uri = pathutils.unstrip_path(posixpath.join(collection.path, item.href)) href.text = xmlutils.make_href(base_prefix, uri) response.append(href) if propname or allprop: props = [] # Should list all properties that can be retrieved by the code below props.append(xmlutils.make_clark("D:principal-collection-set")) props.append(xmlutils.make_clark("D:current-user-principal")) props.append(xmlutils.make_clark("D:current-user-privilege-set")) props.append(xmlutils.make_clark("D:supported-report-set")) props.append(xmlutils.make_clark("D:resourcetype")) props.append(xmlutils.make_clark("D:owner")) if is_collection and collection.is_principal: props.append(xmlutils.make_clark("C:calendar-user-address-set")) props.append(xmlutils.make_clark("D:principal-URL")) props.append(xmlutils.make_clark("CR:addressbook-home-set")) props.append(xmlutils.make_clark("C:calendar-home-set")) if not is_collection or is_leaf: props.append(xmlutils.make_clark("D:getetag")) props.append(xmlutils.make_clark("D:getlastmodified")) props.append(xmlutils.make_clark("D:getcontenttype")) props.append(xmlutils.make_clark("D:getcontentlength")) if is_collection: if is_leaf: props.append(xmlutils.make_clark("D:displayname")) props.append(xmlutils.make_clark("D:sync-token")) if collection.get_meta("tag") == "VCALENDAR": props.append(xmlutils.make_clark("CS:getctag")) props.append( xmlutils.make_clark("C:supported-calendar-component-set")) meta = item.get_meta() for tag in meta: if tag == "tag": continue clark_tag = xmlutils.make_clark(tag) if clark_tag not in props: props.append(clark_tag) responses = collections.defaultdict(list) if propname: for tag in props: responses[200].append(ET.Element(tag)) props = () for tag in props: element = ET.Element(tag) is404 = False if tag == xmlutils.make_clark("D:getetag"): if not is_collection or is_leaf: element.text = item.etag else: is404 = True elif tag == xmlutils.make_clark("D:getlastmodified"): if not is_collection or is_leaf: element.text = item.last_modified else: is404 = True elif tag == xmlutils.make_clark("D:principal-collection-set"): child_element = ET.Element(xmlutils.make_clark("D:href")) child_element.text = xmlutils.make_href(base_prefix, "/") element.append(child_element) elif (tag in (xmlutils.make_clark("C:calendar-user-address-set"), xmlutils.make_clark("D:principal-URL"), xmlutils.make_clark("CR:addressbook-home-set"), xmlutils.make_clark("C:calendar-home-set")) and collection.is_principal and is_collection): child_element = ET.Element(xmlutils.make_clark("D:href")) child_element.text = xmlutils.make_href(base_prefix, path) element.append(child_element) elif tag == xmlutils.make_clark("C:supported-calendar-component-set"): human_tag = xmlutils.make_human_tag(tag) if is_collection and is_leaf: meta = item.get_meta(human_tag) if meta: components = meta.split(",") else: components = ("VTODO", "VEVENT", "VJOURNAL") for component in components: comp = ET.Element(xmlutils.make_clark("C:comp")) comp.set("name", component) element.append(comp) else: is404 = True elif tag == xmlutils.make_clark("D:current-user-principal"): if user: child_element = ET.Element(xmlutils.make_clark("D:href")) child_element.text = xmlutils.make_href( base_prefix, "/%s/" % user) element.append(child_element) else: element.append( ET.Element(xmlutils.make_clark("D:unauthenticated"))) elif tag == xmlutils.make_clark("D:current-user-privilege-set"): privileges = ["D:read"] if write: privileges.append("D:all") privileges.append("D:write") privileges.append("D:write-properties") privileges.append("D:write-content") for human_tag in privileges: privilege = ET.Element(xmlutils.make_clark("D:privilege")) privilege.append(ET.Element(xmlutils.make_clark(human_tag))) element.append(privilege) elif tag == xmlutils.make_clark("D:supported-report-set"): # These 3 reports are not implemented reports = [ "D:expand-property", "D:principal-search-property-set", "D:principal-property-search" ] if is_collection and is_leaf: reports.append("D:sync-collection") if item.get_meta("tag") == "VADDRESSBOOK": reports.append("CR:addressbook-multiget") reports.append("CR:addressbook-query") elif item.get_meta("tag") == "VCALENDAR": reports.append("C:calendar-multiget") reports.append("C:calendar-query") for human_tag in reports: supported_report = ET.Element( xmlutils.make_clark("D:supported-report")) report_element = ET.Element(xmlutils.make_clark("D:report")) report_element.append( ET.Element(xmlutils.make_clark(human_tag))) supported_report.append(report_element) element.append(supported_report) elif tag == xmlutils.make_clark("D:getcontentlength"): if not is_collection or is_leaf: element.text = str(len(item.serialize().encode(encoding))) else: is404 = True elif tag == xmlutils.make_clark("D:owner"): # return empty elment, if no owner available (rfc3744-5.1) if collection.owner: child_element = ET.Element(xmlutils.make_clark("D:href")) child_element.text = xmlutils.make_href( base_prefix, "/%s/" % collection.owner) element.append(child_element) elif is_collection: if tag == xmlutils.make_clark("D:getcontenttype"): if is_leaf: element.text = xmlutils.MIMETYPES[item.get_meta("tag")] else: is404 = True elif tag == xmlutils.make_clark("D:resourcetype"): if item.is_principal: child_element = ET.Element( xmlutils.make_clark("D:principal")) element.append(child_element) if is_leaf: if item.get_meta("tag") == "VADDRESSBOOK": child_element = ET.Element( xmlutils.make_clark("CR:addressbook")) element.append(child_element) elif item.get_meta("tag") == "VCALENDAR": child_element = ET.Element( xmlutils.make_clark("C:calendar")) element.append(child_element) child_element = ET.Element(xmlutils.make_clark("D:collection")) element.append(child_element) elif tag == xmlutils.make_clark("RADICALE:displayname"): # Only for internal use by the web interface displayname = item.get_meta("D:displayname") if displayname is not None: element.text = displayname else: is404 = True elif tag == xmlutils.make_clark("D:displayname"): displayname = item.get_meta("D:displayname") if not displayname and is_leaf: displayname = item.path if displayname is not None: element.text = displayname else: is404 = True elif tag == xmlutils.make_clark("CS:getctag"): if is_leaf: element.text = item.etag else: is404 = True elif tag == xmlutils.make_clark("D:sync-token"): if is_leaf: element.text, _ = item.sync() else: is404 = True else: human_tag = xmlutils.make_human_tag(tag) meta = item.get_meta(human_tag) if meta is not None: element.text = meta else: is404 = True # Not for collections elif tag == xmlutils.make_clark("D:getcontenttype"): element.text = xmlutils.get_content_type(item, encoding) elif tag == xmlutils.make_clark("D:resourcetype"): # resourcetype must be returned empty for non-collection elements pass else: is404 = True responses[404 if is404 else 200].append(element) for status_code, childs in responses.items(): if not childs: continue propstat = ET.Element(xmlutils.make_clark("D:propstat")) response.append(propstat) prop = ET.Element(xmlutils.make_clark("D:prop")) prop.extend(childs) propstat.append(prop) status = ET.Element(xmlutils.make_clark("D:status")) status.text = xmlutils.make_response(status_code) propstat.append(status) return response
def xml_propfind_response(base_prefix, path, item, props, user, write=False, propname=False, allprop=False): """Build and return a PROPFIND response.""" if propname and allprop or (props and (propname or allprop)): raise ValueError("Only use one of props, propname and allprops") is_collection = isinstance(item, storage.BaseCollection) if is_collection: is_leaf = item.get_meta("tag") in ("VADDRESSBOOK", "VCALENDAR") collection = item else: collection = item.collection response = ET.Element(xmlutils.make_tag("D", "response")) href = ET.Element(xmlutils.make_tag("D", "href")) if is_collection: # Some clients expect collections to end with / uri = pathutils.unstrip_path(item.path, True) else: uri = pathutils.unstrip_path( posixpath.join(collection.path, item.href)) href.text = xmlutils.make_href(base_prefix, uri) response.append(href) propstat404 = ET.Element(xmlutils.make_tag("D", "propstat")) propstat200 = ET.Element(xmlutils.make_tag("D", "propstat")) response.append(propstat200) prop200 = ET.Element(xmlutils.make_tag("D", "prop")) propstat200.append(prop200) prop404 = ET.Element(xmlutils.make_tag("D", "prop")) propstat404.append(prop404) if propname or allprop: props = [] # Should list all properties that can be retrieved by the code below props.append(xmlutils.make_tag("D", "principal-collection-set")) props.append(xmlutils.make_tag("D", "current-user-principal")) props.append(xmlutils.make_tag("D", "current-user-privilege-set")) props.append(xmlutils.make_tag("D", "supported-report-set")) props.append(xmlutils.make_tag("D", "resourcetype")) props.append(xmlutils.make_tag("D", "owner")) if is_collection and collection.is_principal: props.append(xmlutils.make_tag("C", "calendar-user-address-set")) props.append(xmlutils.make_tag("D", "principal-URL")) props.append(xmlutils.make_tag("CR", "addressbook-home-set")) props.append(xmlutils.make_tag("C", "calendar-home-set")) if not is_collection or is_leaf: props.append(xmlutils.make_tag("D", "getetag")) props.append(xmlutils.make_tag("D", "getlastmodified")) props.append(xmlutils.make_tag("D", "getcontenttype")) props.append(xmlutils.make_tag("D", "getcontentlength")) if is_collection: if is_leaf: props.append(xmlutils.make_tag("D", "displayname")) props.append(xmlutils.make_tag("D", "sync-token")) if collection.get_meta("tag") == "VCALENDAR": props.append(xmlutils.make_tag("CS", "getctag")) props.append( xmlutils.make_tag("C", "supported-calendar-component-set")) meta = item.get_meta() for tag in meta: if tag == "tag": continue clark_tag = xmlutils.tag_from_human(tag) if clark_tag not in props: props.append(clark_tag) if propname: for tag in props: prop200.append(ET.Element(tag)) props = () for tag in props: element = ET.Element(tag) is404 = False if tag == xmlutils.make_tag("D", "getetag"): if not is_collection or is_leaf: element.text = item.etag else: is404 = True elif tag == xmlutils.make_tag("D", "getlastmodified"): if not is_collection or is_leaf: element.text = item.last_modified else: is404 = True elif tag == xmlutils.make_tag("D", "principal-collection-set"): tag = ET.Element(xmlutils.make_tag("D", "href")) tag.text = xmlutils.make_href(base_prefix, "/") element.append(tag) elif (tag in (xmlutils.make_tag("C", "calendar-user-address-set"), xmlutils.make_tag("D", "principal-URL"), xmlutils.make_tag("CR", "addressbook-home-set"), xmlutils.make_tag("C", "calendar-home-set")) and collection.is_principal and is_collection): tag = ET.Element(xmlutils.make_tag("D", "href")) tag.text = xmlutils.make_href(base_prefix, path) element.append(tag) elif tag == xmlutils.make_tag("C", "supported-calendar-component-set"): human_tag = xmlutils.tag_from_clark(tag) if is_collection and is_leaf: meta = item.get_meta(human_tag) if meta: components = meta.split(",") else: components = ("VTODO", "VEVENT", "VJOURNAL") for component in components: comp = ET.Element(xmlutils.make_tag("C", "comp")) comp.set("name", component) element.append(comp) else: is404 = True elif tag == xmlutils.make_tag("D", "current-user-principal"): if user: tag = ET.Element(xmlutils.make_tag("D", "href")) tag.text = xmlutils.make_href(base_prefix, "/%s/" % user) element.append(tag) else: element.append(ET.Element( xmlutils.make_tag("D", "unauthenticated"))) elif tag == xmlutils.make_tag("D", "current-user-privilege-set"): privileges = [("D", "read")] if write: privileges.append(("D", "all")) privileges.append(("D", "write")) privileges.append(("D", "write-properties")) privileges.append(("D", "write-content")) for ns, privilege_name in privileges: privilege = ET.Element(xmlutils.make_tag("D", "privilege")) privilege.append(ET.Element( xmlutils.make_tag(ns, privilege_name))) element.append(privilege) elif tag == xmlutils.make_tag("D", "supported-report-set"): # These 3 reports are not implemented reports = [ ("D", "expand-property"), ("D", "principal-search-property-set"), ("D", "principal-property-search")] if is_collection and is_leaf: reports.append(("D", "sync-collection")) if item.get_meta("tag") == "VADDRESSBOOK": reports.append(("CR", "addressbook-multiget")) reports.append(("CR", "addressbook-query")) elif item.get_meta("tag") == "VCALENDAR": reports.append(("C", "calendar-multiget")) reports.append(("C", "calendar-query")) for ns, report_name in reports: supported = ET.Element( xmlutils.make_tag("D", "supported-report")) report_tag = ET.Element(xmlutils.make_tag("D", "report")) supported_report_tag = ET.Element( xmlutils.make_tag(ns, report_name)) report_tag.append(supported_report_tag) supported.append(report_tag) element.append(supported) elif tag == xmlutils.make_tag("D", "getcontentlength"): if not is_collection or is_leaf: encoding = collection.configuration.get("encoding", "request") element.text = str(len(item.serialize().encode(encoding))) else: is404 = True elif tag == xmlutils.make_tag("D", "owner"): # return empty elment, if no owner available (rfc3744-5.1) if collection.owner: tag = ET.Element(xmlutils.make_tag("D", "href")) tag.text = xmlutils.make_href( base_prefix, "/%s/" % collection.owner) element.append(tag) elif is_collection: if tag == xmlutils.make_tag("D", "getcontenttype"): if is_leaf: element.text = xmlutils.MIMETYPES[item.get_meta("tag")] else: is404 = True elif tag == xmlutils.make_tag("D", "resourcetype"): if item.is_principal: tag = ET.Element(xmlutils.make_tag("D", "principal")) element.append(tag) if is_leaf: if item.get_meta("tag") == "VADDRESSBOOK": tag = ET.Element( xmlutils.make_tag("CR", "addressbook")) element.append(tag) elif item.get_meta("tag") == "VCALENDAR": tag = ET.Element(xmlutils.make_tag("C", "calendar")) element.append(tag) tag = ET.Element(xmlutils.make_tag("D", "collection")) element.append(tag) elif tag == xmlutils.make_tag("RADICALE", "displayname"): # Only for internal use by the web interface displayname = item.get_meta("D:displayname") if displayname is not None: element.text = displayname else: is404 = True elif tag == xmlutils.make_tag("D", "displayname"): displayname = item.get_meta("D:displayname") if not displayname and is_leaf: displayname = item.path if displayname is not None: element.text = displayname else: is404 = True elif tag == xmlutils.make_tag("CS", "getctag"): if is_leaf: element.text = item.etag else: is404 = True elif tag == xmlutils.make_tag("D", "sync-token"): if is_leaf: element.text, _ = item.sync() else: is404 = True else: human_tag = xmlutils.tag_from_clark(tag) meta = item.get_meta(human_tag) if meta is not None: element.text = meta else: is404 = True # Not for collections elif tag == xmlutils.make_tag("D", "getcontenttype"): element.text = xmlutils.get_content_type(item) elif tag == xmlutils.make_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(xmlutils.make_tag("D", "status")) status200.text = xmlutils.make_response(200) propstat200.append(status200) status404 = ET.Element(xmlutils.make_tag("D", "status")) status404.text = xmlutils.make_response(404) propstat404.append(status404) if len(prop404): response.append(propstat404) return response
def xml_propfind_response(base_prefix, path, item, props, user, write=False, propname=False, allprop=False): """Build and return a PROPFIND response.""" if propname and allprop or (props and (propname or allprop)): raise ValueError("Only use one of props, propname and allprops") is_collection = isinstance(item, storage.BaseCollection) if is_collection: is_leaf = item.get_meta("tag") in ("VADDRESSBOOK", "VCALENDAR") collection = item else: collection = item.collection response = ET.Element(xmlutils.make_tag("D", "response")) href = ET.Element(xmlutils.make_tag("D", "href")) if is_collection: # Some clients expect collections to end with / uri = pathutils.unstrip_path(item.path, True) else: uri = pathutils.unstrip_path(posixpath.join(collection.path, item.href)) href.text = xmlutils.make_href(base_prefix, uri) response.append(href) propstat404 = ET.Element(xmlutils.make_tag("D", "propstat")) propstat200 = ET.Element(xmlutils.make_tag("D", "propstat")) response.append(propstat200) prop200 = ET.Element(xmlutils.make_tag("D", "prop")) propstat200.append(prop200) prop404 = ET.Element(xmlutils.make_tag("D", "prop")) propstat404.append(prop404) if propname or allprop: props = [] # Should list all properties that can be retrieved by the code below props.append(xmlutils.make_tag("D", "principal-collection-set")) props.append(xmlutils.make_tag("D", "current-user-principal")) props.append(xmlutils.make_tag("D", "current-user-privilege-set")) props.append(xmlutils.make_tag("D", "supported-report-set")) props.append(xmlutils.make_tag("D", "resourcetype")) props.append(xmlutils.make_tag("D", "owner")) if is_collection and collection.is_principal: props.append(xmlutils.make_tag("C", "calendar-user-address-set")) props.append(xmlutils.make_tag("D", "principal-URL")) props.append(xmlutils.make_tag("CR", "addressbook-home-set")) props.append(xmlutils.make_tag("C", "calendar-home-set")) if not is_collection or is_leaf: props.append(xmlutils.make_tag("D", "getetag")) props.append(xmlutils.make_tag("D", "getlastmodified")) props.append(xmlutils.make_tag("D", "getcontenttype")) props.append(xmlutils.make_tag("D", "getcontentlength")) if is_collection: if is_leaf: props.append(xmlutils.make_tag("D", "displayname")) props.append(xmlutils.make_tag("D", "sync-token")) if collection.get_meta("tag") == "VCALENDAR": props.append(xmlutils.make_tag("CS", "getctag")) props.append( xmlutils.make_tag("C", "supported-calendar-component-set")) meta = item.get_meta() for tag in meta: if tag == "tag": continue clark_tag = xmlutils.tag_from_human(tag) if clark_tag not in props: props.append(clark_tag) if propname: for tag in props: prop200.append(ET.Element(tag)) props = () for tag in props: element = ET.Element(tag) is404 = False if tag == xmlutils.make_tag("D", "getetag"): if not is_collection or is_leaf: element.text = item.etag else: is404 = True elif tag == xmlutils.make_tag("D", "getlastmodified"): if not is_collection or is_leaf: element.text = item.last_modified else: is404 = True elif tag == xmlutils.make_tag("D", "principal-collection-set"): tag = ET.Element(xmlutils.make_tag("D", "href")) tag.text = xmlutils.make_href(base_prefix, "/") element.append(tag) elif (tag in (xmlutils.make_tag("C", "calendar-user-address-set"), xmlutils.make_tag("D", "principal-URL"), xmlutils.make_tag("CR", "addressbook-home-set"), xmlutils.make_tag("C", "calendar-home-set")) and collection.is_principal and is_collection): tag = ET.Element(xmlutils.make_tag("D", "href")) tag.text = xmlutils.make_href(base_prefix, path) element.append(tag) elif tag == xmlutils.make_tag("C", "supported-calendar-component-set"): human_tag = xmlutils.tag_from_clark(tag) if is_collection and is_leaf: meta = item.get_meta(human_tag) if meta: components = meta.split(",") else: components = ("VTODO", "VEVENT", "VJOURNAL") for component in components: comp = ET.Element(xmlutils.make_tag("C", "comp")) comp.set("name", component) element.append(comp) else: is404 = True elif tag == xmlutils.make_tag("D", "current-user-principal"): if user: tag = ET.Element(xmlutils.make_tag("D", "href")) tag.text = xmlutils.make_href(base_prefix, "/%s/" % user) element.append(tag) else: element.append( ET.Element(xmlutils.make_tag("D", "unauthenticated"))) elif tag == xmlutils.make_tag("D", "current-user-privilege-set"): privileges = [("D", "read")] if write: privileges.append(("D", "all")) privileges.append(("D", "write")) privileges.append(("D", "write-properties")) privileges.append(("D", "write-content")) for ns, privilege_name in privileges: privilege = ET.Element(xmlutils.make_tag("D", "privilege")) privilege.append( ET.Element(xmlutils.make_tag(ns, privilege_name))) element.append(privilege) elif tag == xmlutils.make_tag("D", "supported-report-set"): # These 3 reports are not implemented reports = [("D", "expand-property"), ("D", "principal-search-property-set"), ("D", "principal-property-search")] if is_collection and is_leaf: reports.append(("D", "sync-collection")) if item.get_meta("tag") == "VADDRESSBOOK": reports.append(("CR", "addressbook-multiget")) reports.append(("CR", "addressbook-query")) elif item.get_meta("tag") == "VCALENDAR": reports.append(("C", "calendar-multiget")) reports.append(("C", "calendar-query")) for ns, report_name in reports: supported = ET.Element( xmlutils.make_tag("D", "supported-report")) report_tag = ET.Element(xmlutils.make_tag("D", "report")) supported_report_tag = ET.Element( xmlutils.make_tag(ns, report_name)) report_tag.append(supported_report_tag) supported.append(report_tag) element.append(supported) elif tag == xmlutils.make_tag("D", "getcontentlength"): if not is_collection or is_leaf: encoding = collection.configuration.get("encoding", "request") element.text = str(len(item.serialize().encode(encoding))) else: is404 = True elif tag == xmlutils.make_tag("D", "owner"): # return empty elment, if no owner available (rfc3744-5.1) if collection.owner: tag = ET.Element(xmlutils.make_tag("D", "href")) tag.text = xmlutils.make_href(base_prefix, "/%s/" % collection.owner) element.append(tag) elif is_collection: if tag == xmlutils.make_tag("D", "getcontenttype"): if is_leaf: element.text = xmlutils.MIMETYPES[item.get_meta("tag")] else: is404 = True elif tag == xmlutils.make_tag("D", "resourcetype"): if item.is_principal: tag = ET.Element(xmlutils.make_tag("D", "principal")) element.append(tag) if is_leaf: if item.get_meta("tag") == "VADDRESSBOOK": tag = ET.Element(xmlutils.make_tag( "CR", "addressbook")) element.append(tag) elif item.get_meta("tag") == "VCALENDAR": tag = ET.Element(xmlutils.make_tag("C", "calendar")) element.append(tag) tag = ET.Element(xmlutils.make_tag("D", "collection")) element.append(tag) elif tag == xmlutils.make_tag("RADICALE", "displayname"): # Only for internal use by the web interface displayname = item.get_meta("D:displayname") if displayname is not None: element.text = displayname else: is404 = True elif tag == xmlutils.make_tag("D", "displayname"): displayname = item.get_meta("D:displayname") if not displayname and is_leaf: displayname = item.path if displayname is not None: element.text = displayname else: is404 = True elif tag == xmlutils.make_tag("CS", "getctag"): if is_leaf: element.text = item.etag else: is404 = True elif tag == xmlutils.make_tag("D", "sync-token"): if is_leaf: element.text, _ = item.sync() else: is404 = True else: human_tag = xmlutils.tag_from_clark(tag) meta = item.get_meta(human_tag) if meta is not None: element.text = meta else: is404 = True # Not for collections elif tag == xmlutils.make_tag("D", "getcontenttype"): element.text = xmlutils.get_content_type(item) elif tag == xmlutils.make_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(xmlutils.make_tag("D", "status")) status200.text = xmlutils.make_response(200) propstat200.append(status200) status404 = ET.Element(xmlutils.make_tag("D", "status")) status404.text = xmlutils.make_response(404) propstat404.append(status404) if len(prop404): response.append(propstat404) return response