Rework XML helpers functions
- Merge make_tag, tag_from_clark and tag_from_human into make_clark and make_human - Don't use RegEx for parsing
This commit is contained in:
parent
262d76cc87
commit
d3776e55fb
@ -374,10 +374,9 @@ class Application(
|
|||||||
xml_declaration=True)
|
xml_declaration=True)
|
||||||
return f.getvalue()
|
return f.getvalue()
|
||||||
|
|
||||||
def _webdav_error_response(self, namespace, name,
|
def _webdav_error_response(self, human_tag,
|
||||||
status=httputils.WEBDAV_PRECONDITION_FAILED[0]):
|
status=httputils.WEBDAV_PRECONDITION_FAILED[0]):
|
||||||
"""Generate XML error response."""
|
"""Generate XML error response."""
|
||||||
headers = {"Content-Type": "text/xml; charset=%s" % self._encoding}
|
headers = {"Content-Type": "text/xml; charset=%s" % self._encoding}
|
||||||
content = self._write_xml_content(
|
content = self._write_xml_content(xmlutils.webdav_error(human_tag))
|
||||||
xmlutils.webdav_error(namespace, name))
|
|
||||||
return status, headers, content
|
return status, headers, content
|
||||||
|
@ -31,15 +31,15 @@ def xml_delete(base_prefix, path, collection, href=None):
|
|||||||
"""
|
"""
|
||||||
collection.delete(href)
|
collection.delete(href)
|
||||||
|
|
||||||
multistatus = ET.Element(xmlutils.make_tag("D", "multistatus"))
|
multistatus = ET.Element(xmlutils.make_clark("D:multistatus"))
|
||||||
response = ET.Element(xmlutils.make_tag("D", "response"))
|
response = ET.Element(xmlutils.make_clark("D:response"))
|
||||||
multistatus.append(response)
|
multistatus.append(response)
|
||||||
|
|
||||||
href = ET.Element(xmlutils.make_tag("D", "href"))
|
href = ET.Element(xmlutils.make_clark("D:href"))
|
||||||
href.text = xmlutils.make_href(base_prefix, path)
|
href.text = xmlutils.make_href(base_prefix, path)
|
||||||
response.append(href)
|
response.append(href)
|
||||||
|
|
||||||
status = ET.Element(xmlutils.make_tag("D", "status"))
|
status = ET.Element(xmlutils.make_clark("D:status"))
|
||||||
status.text = xmlutils.make_response(200)
|
status.text = xmlutils.make_response(200)
|
||||||
response.append(status)
|
response.append(status)
|
||||||
|
|
||||||
|
@ -54,8 +54,7 @@ class ApplicationMkcalendarMixin:
|
|||||||
with self._storage.acquire_lock("w", user):
|
with self._storage.acquire_lock("w", user):
|
||||||
item = next(self._storage.discover(path), None)
|
item = next(self._storage.discover(path), None)
|
||||||
if item:
|
if item:
|
||||||
return self._webdav_error_response(
|
return self._webdav_error_response("D:resource-must-be-null")
|
||||||
"D", "resource-must-be-null")
|
|
||||||
parent_path = pathutils.unstrip_path(
|
parent_path = pathutils.unstrip_path(
|
||||||
posixpath.dirname(pathutils.strip_path(path)), True)
|
posixpath.dirname(pathutils.strip_path(path)), True)
|
||||||
parent_item = next(self._storage.discover(parent_path), None)
|
parent_item = next(self._storage.discover(parent_path), None)
|
||||||
|
@ -74,8 +74,8 @@ class ApplicationMoveMixin:
|
|||||||
not to_item and
|
not to_item and
|
||||||
to_collection.path != item.collection.path and
|
to_collection.path != item.collection.path and
|
||||||
to_collection.has_uid(item.uid)):
|
to_collection.has_uid(item.uid)):
|
||||||
return self._webdav_error_response(
|
return self._webdav_error_response("%s:no-uid-conflict" % (
|
||||||
"C" if tag == "VCALENDAR" else "CR", "no-uid-conflict")
|
"C" if tag == "VCALENDAR" else "CR"))
|
||||||
to_href = posixpath.basename(pathutils.strip_path(to_path))
|
to_href = posixpath.basename(pathutils.strip_path(to_path))
|
||||||
try:
|
try:
|
||||||
self._storage.move(item, to_collection, to_href)
|
self._storage.move(item, to_collection, to_href)
|
||||||
|
@ -41,26 +41,26 @@ def xml_propfind(base_prefix, path, xml_request, allowed_items, user,
|
|||||||
# A client may choose not to submit a request body. An empty PROPFIND
|
# A client may choose not to submit a request body. An empty PROPFIND
|
||||||
# request body MUST be treated as if it were an 'allprop' request.
|
# request body MUST be treated as if it were an 'allprop' request.
|
||||||
top_tag = (xml_request[0] if xml_request is not None else
|
top_tag = (xml_request[0] if xml_request is not None else
|
||||||
ET.Element(xmlutils.make_tag("D", "allprop")))
|
ET.Element(xmlutils.make_clark("D:allprop")))
|
||||||
|
|
||||||
props = ()
|
props = ()
|
||||||
allprop = False
|
allprop = False
|
||||||
propname = False
|
propname = False
|
||||||
if top_tag.tag == xmlutils.make_tag("D", "allprop"):
|
if top_tag.tag == xmlutils.make_clark("D:allprop"):
|
||||||
allprop = True
|
allprop = True
|
||||||
elif top_tag.tag == xmlutils.make_tag("D", "propname"):
|
elif top_tag.tag == xmlutils.make_clark("D:propname"):
|
||||||
propname = True
|
propname = True
|
||||||
elif top_tag.tag == xmlutils.make_tag("D", "prop"):
|
elif top_tag.tag == xmlutils.make_clark("D:prop"):
|
||||||
props = [prop.tag for prop in top_tag]
|
props = [prop.tag for prop in top_tag]
|
||||||
|
|
||||||
if xmlutils.make_tag("D", "current-user-principal") in props and not user:
|
if xmlutils.make_clark("D:current-user-principal") in props and not user:
|
||||||
# Ask for authentication
|
# Ask for authentication
|
||||||
# Returning the DAV:unauthenticated pseudo-principal as specified in
|
# Returning the DAV:unauthenticated pseudo-principal as specified in
|
||||||
# RFC 5397 doesn't seem to work with DAVdroid.
|
# RFC 5397 doesn't seem to work with DAVdroid.
|
||||||
return client.FORBIDDEN, None
|
return client.FORBIDDEN, None
|
||||||
|
|
||||||
# Writing answer
|
# Writing answer
|
||||||
multistatus = ET.Element(xmlutils.make_tag("D", "multistatus"))
|
multistatus = ET.Element(xmlutils.make_clark("D:multistatus"))
|
||||||
|
|
||||||
for item, permission in allowed_items:
|
for item, permission in allowed_items:
|
||||||
write = permission == "w"
|
write = permission == "w"
|
||||||
@ -83,9 +83,8 @@ def xml_propfind_response(base_prefix, path, item, props, user, encoding,
|
|||||||
else:
|
else:
|
||||||
collection = item.collection
|
collection = item.collection
|
||||||
|
|
||||||
response = ET.Element(xmlutils.make_tag("D", "response"))
|
response = ET.Element(xmlutils.make_clark("D:response"))
|
||||||
|
href = ET.Element(xmlutils.make_clark("D:href"))
|
||||||
href = ET.Element(xmlutils.make_tag("D", "href"))
|
|
||||||
if is_collection:
|
if is_collection:
|
||||||
# Some clients expect collections to end with /
|
# Some clients expect collections to end with /
|
||||||
uri = pathutils.unstrip_path(item.path, True)
|
uri = pathutils.unstrip_path(item.path, True)
|
||||||
@ -98,39 +97,39 @@ def xml_propfind_response(base_prefix, path, item, props, user, encoding,
|
|||||||
if propname or allprop:
|
if propname or allprop:
|
||||||
props = []
|
props = []
|
||||||
# Should list all properties that can be retrieved by the code below
|
# 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_clark("D:principal-collection-set"))
|
||||||
props.append(xmlutils.make_tag("D", "current-user-principal"))
|
props.append(xmlutils.make_clark("D:current-user-principal"))
|
||||||
props.append(xmlutils.make_tag("D", "current-user-privilege-set"))
|
props.append(xmlutils.make_clark("D:current-user-privilege-set"))
|
||||||
props.append(xmlutils.make_tag("D", "supported-report-set"))
|
props.append(xmlutils.make_clark("D:supported-report-set"))
|
||||||
props.append(xmlutils.make_tag("D", "resourcetype"))
|
props.append(xmlutils.make_clark("D:resourcetype"))
|
||||||
props.append(xmlutils.make_tag("D", "owner"))
|
props.append(xmlutils.make_clark("D:owner"))
|
||||||
|
|
||||||
if is_collection and collection.is_principal:
|
if is_collection and collection.is_principal:
|
||||||
props.append(xmlutils.make_tag("C", "calendar-user-address-set"))
|
props.append(xmlutils.make_clark("C:calendar-user-address-set"))
|
||||||
props.append(xmlutils.make_tag("D", "principal-URL"))
|
props.append(xmlutils.make_clark("D:principal-URL"))
|
||||||
props.append(xmlutils.make_tag("CR", "addressbook-home-set"))
|
props.append(xmlutils.make_clark("CR:addressbook-home-set"))
|
||||||
props.append(xmlutils.make_tag("C", "calendar-home-set"))
|
props.append(xmlutils.make_clark("C:calendar-home-set"))
|
||||||
|
|
||||||
if not is_collection or is_leaf:
|
if not is_collection or is_leaf:
|
||||||
props.append(xmlutils.make_tag("D", "getetag"))
|
props.append(xmlutils.make_clark("D:getetag"))
|
||||||
props.append(xmlutils.make_tag("D", "getlastmodified"))
|
props.append(xmlutils.make_clark("D:getlastmodified"))
|
||||||
props.append(xmlutils.make_tag("D", "getcontenttype"))
|
props.append(xmlutils.make_clark("D:getcontenttype"))
|
||||||
props.append(xmlutils.make_tag("D", "getcontentlength"))
|
props.append(xmlutils.make_clark("D:getcontentlength"))
|
||||||
|
|
||||||
if is_collection:
|
if is_collection:
|
||||||
if is_leaf:
|
if is_leaf:
|
||||||
props.append(xmlutils.make_tag("D", "displayname"))
|
props.append(xmlutils.make_clark("D:displayname"))
|
||||||
props.append(xmlutils.make_tag("D", "sync-token"))
|
props.append(xmlutils.make_clark("D:sync-token"))
|
||||||
if collection.get_meta("tag") == "VCALENDAR":
|
if collection.get_meta("tag") == "VCALENDAR":
|
||||||
props.append(xmlutils.make_tag("CS", "getctag"))
|
props.append(xmlutils.make_clark("CS:getctag"))
|
||||||
props.append(
|
props.append(
|
||||||
xmlutils.make_tag("C", "supported-calendar-component-set"))
|
xmlutils.make_clark("C:supported-calendar-component-set"))
|
||||||
|
|
||||||
meta = item.get_meta()
|
meta = item.get_meta()
|
||||||
for tag in meta:
|
for tag in meta:
|
||||||
if tag == "tag":
|
if tag == "tag":
|
||||||
continue
|
continue
|
||||||
clark_tag = xmlutils.tag_from_human(tag)
|
clark_tag = xmlutils.make_clark(tag)
|
||||||
if clark_tag not in props:
|
if clark_tag not in props:
|
||||||
props.append(clark_tag)
|
props.append(clark_tag)
|
||||||
|
|
||||||
@ -142,30 +141,30 @@ def xml_propfind_response(base_prefix, path, item, props, user, encoding,
|
|||||||
for tag in props:
|
for tag in props:
|
||||||
element = ET.Element(tag)
|
element = ET.Element(tag)
|
||||||
is404 = False
|
is404 = False
|
||||||
if tag == xmlutils.make_tag("D", "getetag"):
|
if tag == xmlutils.make_clark("D:getetag"):
|
||||||
if not is_collection or is_leaf:
|
if not is_collection or is_leaf:
|
||||||
element.text = item.etag
|
element.text = item.etag
|
||||||
else:
|
else:
|
||||||
is404 = True
|
is404 = True
|
||||||
elif tag == xmlutils.make_tag("D", "getlastmodified"):
|
elif tag == xmlutils.make_clark("D:getlastmodified"):
|
||||||
if not is_collection or is_leaf:
|
if not is_collection or is_leaf:
|
||||||
element.text = item.last_modified
|
element.text = item.last_modified
|
||||||
else:
|
else:
|
||||||
is404 = True
|
is404 = True
|
||||||
elif tag == xmlutils.make_tag("D", "principal-collection-set"):
|
elif tag == xmlutils.make_clark("D:principal-collection-set"):
|
||||||
tag = ET.Element(xmlutils.make_tag("D", "href"))
|
tag = ET.Element(xmlutils.make_clark("D:href"))
|
||||||
tag.text = xmlutils.make_href(base_prefix, "/")
|
tag.text = xmlutils.make_href(base_prefix, "/")
|
||||||
element.append(tag)
|
element.append(tag)
|
||||||
elif (tag in (xmlutils.make_tag("C", "calendar-user-address-set"),
|
elif (tag in (xmlutils.make_clark("C:calendar-user-address-set"),
|
||||||
xmlutils.make_tag("D", "principal-URL"),
|
xmlutils.make_clark("D:principal-URL"),
|
||||||
xmlutils.make_tag("CR", "addressbook-home-set"),
|
xmlutils.make_clark("CR:addressbook-home-set"),
|
||||||
xmlutils.make_tag("C", "calendar-home-set")) and
|
xmlutils.make_clark("C:calendar-home-set")) and
|
||||||
collection.is_principal and is_collection):
|
collection.is_principal and is_collection):
|
||||||
tag = ET.Element(xmlutils.make_tag("D", "href"))
|
tag = ET.Element(xmlutils.make_clark("D:href"))
|
||||||
tag.text = xmlutils.make_href(base_prefix, path)
|
tag.text = xmlutils.make_href(base_prefix, path)
|
||||||
element.append(tag)
|
element.append(tag)
|
||||||
elif tag == xmlutils.make_tag("C", "supported-calendar-component-set"):
|
elif tag == xmlutils.make_clark("C:supported-calendar-component-set"):
|
||||||
human_tag = xmlutils.tag_from_clark(tag)
|
human_tag = xmlutils.make_human_tag(tag)
|
||||||
if is_collection and is_leaf:
|
if is_collection and is_leaf:
|
||||||
meta = item.get_meta(human_tag)
|
meta = item.get_meta(human_tag)
|
||||||
if meta:
|
if meta:
|
||||||
@ -173,94 +172,91 @@ def xml_propfind_response(base_prefix, path, item, props, user, encoding,
|
|||||||
else:
|
else:
|
||||||
components = ("VTODO", "VEVENT", "VJOURNAL")
|
components = ("VTODO", "VEVENT", "VJOURNAL")
|
||||||
for component in components:
|
for component in components:
|
||||||
comp = ET.Element(xmlutils.make_tag("C", "comp"))
|
comp = ET.Element(xmlutils.make_clark("C:comp"))
|
||||||
comp.set("name", component)
|
comp.set("name", component)
|
||||||
element.append(comp)
|
element.append(comp)
|
||||||
else:
|
else:
|
||||||
is404 = True
|
is404 = True
|
||||||
elif tag == xmlutils.make_tag("D", "current-user-principal"):
|
elif tag == xmlutils.make_clark("D:current-user-principal"):
|
||||||
if user:
|
if user:
|
||||||
tag = ET.Element(xmlutils.make_tag("D", "href"))
|
tag = ET.Element(xmlutils.make_clark("D:href"))
|
||||||
tag.text = xmlutils.make_href(base_prefix, "/%s/" % user)
|
tag.text = xmlutils.make_href(base_prefix, "/%s/" % user)
|
||||||
element.append(tag)
|
element.append(tag)
|
||||||
else:
|
else:
|
||||||
element.append(ET.Element(
|
element.append(ET.Element(
|
||||||
xmlutils.make_tag("D", "unauthenticated")))
|
xmlutils.make_clark("D:unauthenticated")))
|
||||||
elif tag == xmlutils.make_tag("D", "current-user-privilege-set"):
|
elif tag == xmlutils.make_clark("D:current-user-privilege-set"):
|
||||||
privileges = [("D", "read")]
|
privileges = ["D:read"]
|
||||||
if write:
|
if write:
|
||||||
privileges.append(("D", "all"))
|
privileges.append("D:all")
|
||||||
privileges.append(("D", "write"))
|
privileges.append("D:write")
|
||||||
privileges.append(("D", "write-properties"))
|
privileges.append("D:write-properties")
|
||||||
privileges.append(("D", "write-content"))
|
privileges.append("D:write-content")
|
||||||
for ns, privilege_name in privileges:
|
for human_tag in privileges:
|
||||||
privilege = ET.Element(xmlutils.make_tag("D", "privilege"))
|
privilege = ET.Element(xmlutils.make_clark("D:privilege"))
|
||||||
privilege.append(ET.Element(
|
privilege.append(ET.Element(
|
||||||
xmlutils.make_tag(ns, privilege_name)))
|
xmlutils.make_clark(human_tag)))
|
||||||
element.append(privilege)
|
element.append(privilege)
|
||||||
elif tag == xmlutils.make_tag("D", "supported-report-set"):
|
elif tag == xmlutils.make_clark("D:supported-report-set"):
|
||||||
# These 3 reports are not implemented
|
# These 3 reports are not implemented
|
||||||
reports = [
|
reports = ["D:expand-property",
|
||||||
("D", "expand-property"),
|
"D:principal-search-property-set",
|
||||||
("D", "principal-search-property-set"),
|
"D:principal-property-search"]
|
||||||
("D", "principal-property-search")]
|
|
||||||
if is_collection and is_leaf:
|
if is_collection and is_leaf:
|
||||||
reports.append(("D", "sync-collection"))
|
reports.append("D:sync-collection")
|
||||||
if item.get_meta("tag") == "VADDRESSBOOK":
|
if item.get_meta("tag") == "VADDRESSBOOK":
|
||||||
reports.append(("CR", "addressbook-multiget"))
|
reports.append("CR:addressbook-multiget")
|
||||||
reports.append(("CR", "addressbook-query"))
|
reports.append("CR:addressbook-query")
|
||||||
elif item.get_meta("tag") == "VCALENDAR":
|
elif item.get_meta("tag") == "VCALENDAR":
|
||||||
reports.append(("C", "calendar-multiget"))
|
reports.append("C:calendar-multiget")
|
||||||
reports.append(("C", "calendar-query"))
|
reports.append("C:calendar-query")
|
||||||
for ns, report_name in reports:
|
for human_tag in reports:
|
||||||
supported = ET.Element(
|
supported_report = ET.Element(
|
||||||
xmlutils.make_tag("D", "supported-report"))
|
xmlutils.make_clark("D:supported-report"))
|
||||||
report_tag = ET.Element(xmlutils.make_tag("D", "report"))
|
report_tag = ET.Element(xmlutils.make_clark("D:report"))
|
||||||
supported_report_tag = ET.Element(
|
report_tag.append(ET.Element(xmlutils.make_clark(human_tag)))
|
||||||
xmlutils.make_tag(ns, report_name))
|
supported_report.append(report_tag)
|
||||||
report_tag.append(supported_report_tag)
|
element.append(supported_report)
|
||||||
supported.append(report_tag)
|
elif tag == xmlutils.make_clark("D:getcontentlength"):
|
||||||
element.append(supported)
|
|
||||||
elif tag == xmlutils.make_tag("D", "getcontentlength"):
|
|
||||||
if not is_collection or is_leaf:
|
if not is_collection or is_leaf:
|
||||||
element.text = str(len(item.serialize().encode(encoding)))
|
element.text = str(len(item.serialize().encode(encoding)))
|
||||||
else:
|
else:
|
||||||
is404 = True
|
is404 = True
|
||||||
elif tag == xmlutils.make_tag("D", "owner"):
|
elif tag == xmlutils.make_clark("D:owner"):
|
||||||
# return empty elment, if no owner available (rfc3744-5.1)
|
# return empty elment, if no owner available (rfc3744-5.1)
|
||||||
if collection.owner:
|
if collection.owner:
|
||||||
tag = ET.Element(xmlutils.make_tag("D", "href"))
|
tag = ET.Element(xmlutils.make_clark("D:href"))
|
||||||
tag.text = xmlutils.make_href(
|
tag.text = xmlutils.make_href(
|
||||||
base_prefix, "/%s/" % collection.owner)
|
base_prefix, "/%s/" % collection.owner)
|
||||||
element.append(tag)
|
element.append(tag)
|
||||||
elif is_collection:
|
elif is_collection:
|
||||||
if tag == xmlutils.make_tag("D", "getcontenttype"):
|
if tag == xmlutils.make_clark("D:getcontenttype"):
|
||||||
if is_leaf:
|
if is_leaf:
|
||||||
element.text = xmlutils.MIMETYPES[item.get_meta("tag")]
|
element.text = xmlutils.MIMETYPES[item.get_meta("tag")]
|
||||||
else:
|
else:
|
||||||
is404 = True
|
is404 = True
|
||||||
elif tag == xmlutils.make_tag("D", "resourcetype"):
|
elif tag == xmlutils.make_clark("D:resourcetype"):
|
||||||
if item.is_principal:
|
if item.is_principal:
|
||||||
tag = ET.Element(xmlutils.make_tag("D", "principal"))
|
tag = ET.Element(xmlutils.make_clark("D:principal"))
|
||||||
element.append(tag)
|
element.append(tag)
|
||||||
if is_leaf:
|
if is_leaf:
|
||||||
if item.get_meta("tag") == "VADDRESSBOOK":
|
if item.get_meta("tag") == "VADDRESSBOOK":
|
||||||
tag = ET.Element(
|
tag = ET.Element(
|
||||||
xmlutils.make_tag("CR", "addressbook"))
|
xmlutils.make_clark("CR:addressbook"))
|
||||||
element.append(tag)
|
element.append(tag)
|
||||||
elif item.get_meta("tag") == "VCALENDAR":
|
elif item.get_meta("tag") == "VCALENDAR":
|
||||||
tag = ET.Element(xmlutils.make_tag("C", "calendar"))
|
tag = ET.Element(xmlutils.make_clark("C:calendar"))
|
||||||
element.append(tag)
|
element.append(tag)
|
||||||
tag = ET.Element(xmlutils.make_tag("D", "collection"))
|
tag = ET.Element(xmlutils.make_clark("D:collection"))
|
||||||
element.append(tag)
|
element.append(tag)
|
||||||
elif tag == xmlutils.make_tag("RADICALE", "displayname"):
|
elif tag == xmlutils.make_clark("RADICALE:displayname"):
|
||||||
# Only for internal use by the web interface
|
# Only for internal use by the web interface
|
||||||
displayname = item.get_meta("D:displayname")
|
displayname = item.get_meta("D:displayname")
|
||||||
if displayname is not None:
|
if displayname is not None:
|
||||||
element.text = displayname
|
element.text = displayname
|
||||||
else:
|
else:
|
||||||
is404 = True
|
is404 = True
|
||||||
elif tag == xmlutils.make_tag("D", "displayname"):
|
elif tag == xmlutils.make_clark("D:displayname"):
|
||||||
displayname = item.get_meta("D:displayname")
|
displayname = item.get_meta("D:displayname")
|
||||||
if not displayname and is_leaf:
|
if not displayname and is_leaf:
|
||||||
displayname = item.path
|
displayname = item.path
|
||||||
@ -268,27 +264,27 @@ def xml_propfind_response(base_prefix, path, item, props, user, encoding,
|
|||||||
element.text = displayname
|
element.text = displayname
|
||||||
else:
|
else:
|
||||||
is404 = True
|
is404 = True
|
||||||
elif tag == xmlutils.make_tag("CS", "getctag"):
|
elif tag == xmlutils.make_clark("CS:getctag"):
|
||||||
if is_leaf:
|
if is_leaf:
|
||||||
element.text = item.etag
|
element.text = item.etag
|
||||||
else:
|
else:
|
||||||
is404 = True
|
is404 = True
|
||||||
elif tag == xmlutils.make_tag("D", "sync-token"):
|
elif tag == xmlutils.make_clark("D:sync-token"):
|
||||||
if is_leaf:
|
if is_leaf:
|
||||||
element.text, _ = item.sync()
|
element.text, _ = item.sync()
|
||||||
else:
|
else:
|
||||||
is404 = True
|
is404 = True
|
||||||
else:
|
else:
|
||||||
human_tag = xmlutils.tag_from_clark(tag)
|
human_tag = xmlutils.make_human_tag(tag)
|
||||||
meta = item.get_meta(human_tag)
|
meta = item.get_meta(human_tag)
|
||||||
if meta is not None:
|
if meta is not None:
|
||||||
element.text = meta
|
element.text = meta
|
||||||
else:
|
else:
|
||||||
is404 = True
|
is404 = True
|
||||||
# Not for collections
|
# Not for collections
|
||||||
elif tag == xmlutils.make_tag("D", "getcontenttype"):
|
elif tag == xmlutils.make_clark("D:getcontenttype"):
|
||||||
element.text = xmlutils.get_content_type(item, encoding)
|
element.text = xmlutils.get_content_type(item, encoding)
|
||||||
elif tag == xmlutils.make_tag("D", "resourcetype"):
|
elif tag == xmlutils.make_clark("D:resourcetype"):
|
||||||
# resourcetype must be returned empty for non-collection elements
|
# resourcetype must be returned empty for non-collection elements
|
||||||
pass
|
pass
|
||||||
else:
|
else:
|
||||||
@ -299,12 +295,12 @@ def xml_propfind_response(base_prefix, path, item, props, user, encoding,
|
|||||||
for status_code, childs in responses.items():
|
for status_code, childs in responses.items():
|
||||||
if not childs:
|
if not childs:
|
||||||
continue
|
continue
|
||||||
propstat = ET.Element(xmlutils.make_tag("D", "propstat"))
|
propstat = ET.Element(xmlutils.make_clark("D:propstat"))
|
||||||
response.append(propstat)
|
response.append(propstat)
|
||||||
prop = ET.Element(xmlutils.make_tag("D", "prop"))
|
prop = ET.Element(xmlutils.make_clark("D:prop"))
|
||||||
prop.extend(childs)
|
prop.extend(childs)
|
||||||
propstat.append(prop)
|
propstat.append(prop)
|
||||||
status = ET.Element(xmlutils.make_tag("D", "status"))
|
status = ET.Element(xmlutils.make_clark("D:status"))
|
||||||
status.text = xmlutils.make_response(status_code)
|
status.text = xmlutils.make_response(status_code)
|
||||||
propstat.append(status)
|
propstat.append(status)
|
||||||
|
|
||||||
|
@ -35,17 +35,17 @@ def xml_add_propstat_to(element, tag, status_number):
|
|||||||
``status_number``.
|
``status_number``.
|
||||||
|
|
||||||
"""
|
"""
|
||||||
propstat = ET.Element(xmlutils.make_tag("D", "propstat"))
|
propstat = ET.Element(xmlutils.make_clark("D:propstat"))
|
||||||
element.append(propstat)
|
element.append(propstat)
|
||||||
|
|
||||||
prop = ET.Element(xmlutils.make_tag("D", "prop"))
|
prop = ET.Element(xmlutils.make_clark("D:prop"))
|
||||||
propstat.append(prop)
|
propstat.append(prop)
|
||||||
|
|
||||||
clark_tag = tag if "{" in tag else xmlutils.make_tag(*tag.split(":", 1))
|
clark_tag = xmlutils.make_clark(tag)
|
||||||
prop_tag = ET.Element(clark_tag)
|
prop_tag = ET.Element(clark_tag)
|
||||||
prop.append(prop_tag)
|
prop.append(prop_tag)
|
||||||
|
|
||||||
status = ET.Element(xmlutils.make_tag("D", "status"))
|
status = ET.Element(xmlutils.make_clark("D:status"))
|
||||||
status.text = xmlutils.make_response(status_number)
|
status.text = xmlutils.make_response(status_number)
|
||||||
propstat.append(status)
|
propstat.append(status)
|
||||||
|
|
||||||
@ -60,11 +60,11 @@ def xml_proppatch(base_prefix, path, xml_request, collection):
|
|||||||
props_to_remove = xmlutils.props_from_request(xml_request,
|
props_to_remove = xmlutils.props_from_request(xml_request,
|
||||||
actions=("remove",))
|
actions=("remove",))
|
||||||
|
|
||||||
multistatus = ET.Element(xmlutils.make_tag("D", "multistatus"))
|
multistatus = ET.Element(xmlutils.make_clark("D:multistatus"))
|
||||||
response = ET.Element(xmlutils.make_tag("D", "response"))
|
response = ET.Element(xmlutils.make_clark("D:response"))
|
||||||
multistatus.append(response)
|
multistatus.append(response)
|
||||||
|
|
||||||
href = ET.Element(xmlutils.make_tag("D", "href"))
|
href = ET.Element(xmlutils.make_clark("D:href"))
|
||||||
href.text = xmlutils.make_href(base_prefix, path)
|
href.text = xmlutils.make_href(base_prefix, path)
|
||||||
response.append(href)
|
response.append(href)
|
||||||
|
|
||||||
|
@ -201,9 +201,8 @@ class ApplicationPutMixin:
|
|||||||
prepared_item, = prepared_items
|
prepared_item, = prepared_items
|
||||||
if (item and item.uid != prepared_item.uid or
|
if (item and item.uid != prepared_item.uid or
|
||||||
not item and parent_item.has_uid(prepared_item.uid)):
|
not item and parent_item.has_uid(prepared_item.uid)):
|
||||||
return self._webdav_error_response(
|
return self._webdav_error_response("%s:no-uid-conflict" % (
|
||||||
"C" if tag == "VCALENDAR" else "CR",
|
"C" if tag == "VCALENDAR" else "CR"))
|
||||||
"no-uid-conflict")
|
|
||||||
|
|
||||||
href = posixpath.basename(pathutils.strip_path(path))
|
href = posixpath.basename(pathutils.strip_path(path))
|
||||||
try:
|
try:
|
||||||
|
@ -36,42 +36,42 @@ def xml_report(base_prefix, path, xml_request, collection, encoding,
|
|||||||
Read rfc3253-3.6 for info.
|
Read rfc3253-3.6 for info.
|
||||||
|
|
||||||
"""
|
"""
|
||||||
multistatus = ET.Element(xmlutils.make_tag("D", "multistatus"))
|
multistatus = ET.Element(xmlutils.make_clark("D:multistatus"))
|
||||||
if xml_request is None:
|
if xml_request is None:
|
||||||
return client.MULTI_STATUS, multistatus
|
return client.MULTI_STATUS, multistatus
|
||||||
root = xml_request
|
root = xml_request
|
||||||
if root.tag in (
|
if root.tag in (
|
||||||
xmlutils.make_tag("D", "principal-search-property-set"),
|
xmlutils.make_clark("D:principal-search-property-set"),
|
||||||
xmlutils.make_tag("D", "principal-property-search"),
|
xmlutils.make_clark("D:principal-property-search"),
|
||||||
xmlutils.make_tag("D", "expand-property")):
|
xmlutils.make_clark("D:expand-property")):
|
||||||
# We don't support searching for principals or indirect retrieving of
|
# We don't support searching for principals or indirect retrieving of
|
||||||
# properties, just return an empty result.
|
# properties, just return an empty result.
|
||||||
# InfCloud asks for expand-property reports (even if we don't announce
|
# InfCloud asks for expand-property reports (even if we don't announce
|
||||||
# support for them) and stops working if an error code is returned.
|
# support for them) and stops working if an error code is returned.
|
||||||
logger.warning("Unsupported REPORT method %r on %r requested",
|
logger.warning("Unsupported REPORT method %r on %r requested",
|
||||||
xmlutils.tag_from_clark(root.tag), path)
|
xmlutils.make_human_tag(root.tag), path)
|
||||||
return client.MULTI_STATUS, multistatus
|
return client.MULTI_STATUS, multistatus
|
||||||
if (root.tag == xmlutils.make_tag("C", "calendar-multiget") and
|
if (root.tag == xmlutils.make_clark("C:calendar-multiget") and
|
||||||
collection.get_meta("tag") != "VCALENDAR" or
|
collection.get_meta("tag") != "VCALENDAR" or
|
||||||
root.tag == xmlutils.make_tag("CR", "addressbook-multiget") and
|
root.tag == xmlutils.make_clark("CR:addressbook-multiget") and
|
||||||
collection.get_meta("tag") != "VADDRESSBOOK" or
|
collection.get_meta("tag") != "VADDRESSBOOK" or
|
||||||
root.tag == xmlutils.make_tag("D", "sync-collection") and
|
root.tag == xmlutils.make_clark("D:sync-collection") and
|
||||||
collection.get_meta("tag") not in ("VADDRESSBOOK", "VCALENDAR")):
|
collection.get_meta("tag") not in ("VADDRESSBOOK", "VCALENDAR")):
|
||||||
logger.warning("Invalid REPORT method %r on %r requested",
|
logger.warning("Invalid REPORT method %r on %r requested",
|
||||||
xmlutils.tag_from_clark(root.tag), path)
|
xmlutils.make_human_tag(root.tag), path)
|
||||||
return (client.CONFLICT,
|
return (client.CONFLICT,
|
||||||
xmlutils.webdav_error("D", "supported-report"))
|
xmlutils.webdav_error("D:supported-report"))
|
||||||
prop_element = root.find(xmlutils.make_tag("D", "prop"))
|
prop_element = root.find(xmlutils.make_clark("D:prop"))
|
||||||
props = (
|
props = (
|
||||||
[prop.tag for prop in prop_element]
|
[prop.tag for prop in prop_element]
|
||||||
if prop_element is not None else [])
|
if prop_element is not None else [])
|
||||||
|
|
||||||
if root.tag in (
|
if root.tag in (
|
||||||
xmlutils.make_tag("C", "calendar-multiget"),
|
xmlutils.make_clark("C:calendar-multiget"),
|
||||||
xmlutils.make_tag("CR", "addressbook-multiget")):
|
xmlutils.make_clark("CR:addressbook-multiget")):
|
||||||
# Read rfc4791-7.9 for info
|
# Read rfc4791-7.9 for info
|
||||||
hreferences = set()
|
hreferences = set()
|
||||||
for href_element in root.findall(xmlutils.make_tag("D", "href")):
|
for href_element in root.findall(xmlutils.make_clark("D:href")):
|
||||||
href_path = pathutils.sanitize_path(
|
href_path = pathutils.sanitize_path(
|
||||||
unquote(urlparse(href_element.text).path))
|
unquote(urlparse(href_element.text).path))
|
||||||
if (href_path + "/").startswith(base_prefix + "/"):
|
if (href_path + "/").startswith(base_prefix + "/"):
|
||||||
@ -79,9 +79,9 @@ def xml_report(base_prefix, path, xml_request, collection, encoding,
|
|||||||
else:
|
else:
|
||||||
logger.warning("Skipping invalid path %r in REPORT request on "
|
logger.warning("Skipping invalid path %r in REPORT request on "
|
||||||
"%r", href_path, path)
|
"%r", href_path, path)
|
||||||
elif root.tag == xmlutils.make_tag("D", "sync-collection"):
|
elif root.tag == xmlutils.make_clark("D:sync-collection"):
|
||||||
old_sync_token_element = root.find(
|
old_sync_token_element = root.find(
|
||||||
xmlutils.make_tag("D", "sync-token"))
|
xmlutils.make_clark("D:sync-token"))
|
||||||
old_sync_token = ""
|
old_sync_token = ""
|
||||||
if old_sync_token_element is not None and old_sync_token_element.text:
|
if old_sync_token_element is not None and old_sync_token_element.text:
|
||||||
old_sync_token = old_sync_token_element.text.strip()
|
old_sync_token = old_sync_token_element.text.strip()
|
||||||
@ -93,18 +93,18 @@ def xml_report(base_prefix, path, xml_request, collection, encoding,
|
|||||||
logger.warning("Client provided invalid sync token %r: %s",
|
logger.warning("Client provided invalid sync token %r: %s",
|
||||||
old_sync_token, e, exc_info=True)
|
old_sync_token, e, exc_info=True)
|
||||||
return (client.CONFLICT,
|
return (client.CONFLICT,
|
||||||
xmlutils.webdav_error("D", "valid-sync-token"))
|
xmlutils.webdav_error("D:valid-sync-token"))
|
||||||
hreferences = (pathutils.unstrip_path(
|
hreferences = (pathutils.unstrip_path(
|
||||||
posixpath.join(collection.path, n)) for n in names)
|
posixpath.join(collection.path, n)) for n in names)
|
||||||
# Append current sync token to response
|
# Append current sync token to response
|
||||||
sync_token_element = ET.Element(xmlutils.make_tag("D", "sync-token"))
|
sync_token_element = ET.Element(xmlutils.make_clark("D:sync-token"))
|
||||||
sync_token_element.text = sync_token
|
sync_token_element.text = sync_token
|
||||||
multistatus.append(sync_token_element)
|
multistatus.append(sync_token_element)
|
||||||
else:
|
else:
|
||||||
hreferences = (path,)
|
hreferences = (path,)
|
||||||
filters = (
|
filters = (
|
||||||
root.findall("./%s" % xmlutils.make_tag("C", "filter")) +
|
root.findall("./%s" % xmlutils.make_clark("C:filter")) +
|
||||||
root.findall("./%s" % xmlutils.make_tag("CR", "filter")))
|
root.findall("./%s" % xmlutils.make_clark("CR:filter")))
|
||||||
|
|
||||||
def retrieve_items(collection, hreferences, multistatus):
|
def retrieve_items(collection, hreferences, multistatus):
|
||||||
"""Retrieves all items that are referenced in ``hreferences`` from
|
"""Retrieves all items that are referenced in ``hreferences`` from
|
||||||
@ -157,18 +157,18 @@ def xml_report(base_prefix, path, xml_request, collection, encoding,
|
|||||||
def match(item, filter_):
|
def match(item, filter_):
|
||||||
tag = collection_tag
|
tag = collection_tag
|
||||||
if (tag == "VCALENDAR" and
|
if (tag == "VCALENDAR" and
|
||||||
filter_.tag != xmlutils.make_tag("C", filter_)):
|
filter_.tag != xmlutils.make_clark("C:%s" % filter_)):
|
||||||
if len(filter_) == 0:
|
if len(filter_) == 0:
|
||||||
return True
|
return True
|
||||||
if len(filter_) > 1:
|
if len(filter_) > 1:
|
||||||
raise ValueError("Filter with %d children" % len(filter_))
|
raise ValueError("Filter with %d children" % len(filter_))
|
||||||
if filter_[0].tag != xmlutils.make_tag("C", "comp-filter"):
|
if filter_[0].tag != xmlutils.make_clark("C:comp-filter"):
|
||||||
raise ValueError("Unexpected %r in filter" % filter_[0].tag)
|
raise ValueError("Unexpected %r in filter" % filter_[0].tag)
|
||||||
return radicale_filter.comp_match(item, filter_[0])
|
return radicale_filter.comp_match(item, filter_[0])
|
||||||
if (tag == "VADDRESSBOOK" and
|
if (tag == "VADDRESSBOOK" and
|
||||||
filter_.tag != xmlutils.make_tag("CR", filter_)):
|
filter_.tag != xmlutils.make_clark("CR:%s" % filter_)):
|
||||||
for child in filter_:
|
for child in filter_:
|
||||||
if child.tag != xmlutils.make_tag("CR", "prop-filter"):
|
if child.tag != xmlutils.make_clark("CR:prop-filter"):
|
||||||
raise ValueError("Unexpected %r in filter" % child.tag)
|
raise ValueError("Unexpected %r in filter" % child.tag)
|
||||||
test = filter_.get("test", "anyof")
|
test = filter_.get("test", "anyof")
|
||||||
if test == "anyof":
|
if test == "anyof":
|
||||||
@ -203,15 +203,15 @@ def xml_report(base_prefix, path, xml_request, collection, encoding,
|
|||||||
|
|
||||||
for tag in props:
|
for tag in props:
|
||||||
element = ET.Element(tag)
|
element = ET.Element(tag)
|
||||||
if tag == xmlutils.make_tag("D", "getetag"):
|
if tag == xmlutils.make_clark("D:getetag"):
|
||||||
element.text = item.etag
|
element.text = item.etag
|
||||||
found_props.append(element)
|
found_props.append(element)
|
||||||
elif tag == xmlutils.make_tag("D", "getcontenttype"):
|
elif tag == xmlutils.make_clark("D:getcontenttype"):
|
||||||
element.text = xmlutils.get_content_type(item, encoding)
|
element.text = xmlutils.get_content_type(item, encoding)
|
||||||
found_props.append(element)
|
found_props.append(element)
|
||||||
elif tag in (
|
elif tag in (
|
||||||
xmlutils.make_tag("C", "calendar-data"),
|
xmlutils.make_clark("C:calendar-data"),
|
||||||
xmlutils.make_tag("CR", "address-data")):
|
xmlutils.make_clark("CR:address-data")):
|
||||||
element.text = item.serialize()
|
element.text = item.serialize()
|
||||||
found_props.append(element)
|
found_props.append(element)
|
||||||
else:
|
else:
|
||||||
@ -228,26 +228,26 @@ def xml_report(base_prefix, path, xml_request, collection, encoding,
|
|||||||
|
|
||||||
def xml_item_response(base_prefix, href, found_props=(), not_found_props=(),
|
def xml_item_response(base_prefix, href, found_props=(), not_found_props=(),
|
||||||
found_item=True):
|
found_item=True):
|
||||||
response = ET.Element(xmlutils.make_tag("D", "response"))
|
response = ET.Element(xmlutils.make_clark("D:response"))
|
||||||
|
|
||||||
href_tag = ET.Element(xmlutils.make_tag("D", "href"))
|
href_tag = ET.Element(xmlutils.make_clark("D:href"))
|
||||||
href_tag.text = xmlutils.make_href(base_prefix, href)
|
href_tag.text = xmlutils.make_href(base_prefix, href)
|
||||||
response.append(href_tag)
|
response.append(href_tag)
|
||||||
|
|
||||||
if found_item:
|
if found_item:
|
||||||
for code, props in ((200, found_props), (404, not_found_props)):
|
for code, props in ((200, found_props), (404, not_found_props)):
|
||||||
if props:
|
if props:
|
||||||
propstat = ET.Element(xmlutils.make_tag("D", "propstat"))
|
propstat = ET.Element(xmlutils.make_clark("D:propstat"))
|
||||||
status = ET.Element(xmlutils.make_tag("D", "status"))
|
status = ET.Element(xmlutils.make_clark("D:status"))
|
||||||
status.text = xmlutils.make_response(code)
|
status.text = xmlutils.make_response(code)
|
||||||
prop_tag = ET.Element(xmlutils.make_tag("D", "prop"))
|
prop_tag = ET.Element(xmlutils.make_clark("D:prop"))
|
||||||
for prop in props:
|
for prop in props:
|
||||||
prop_tag.append(prop)
|
prop_tag.append(prop)
|
||||||
propstat.append(prop_tag)
|
propstat.append(prop_tag)
|
||||||
propstat.append(status)
|
propstat.append(status)
|
||||||
response.append(propstat)
|
response.append(propstat)
|
||||||
else:
|
else:
|
||||||
status = ET.Element(xmlutils.make_tag("D", "status"))
|
status = ET.Element(xmlutils.make_clark("D:status"))
|
||||||
status.text = xmlutils.make_response(404)
|
status.text = xmlutils.make_response(404)
|
||||||
response.append(status)
|
response.append(status)
|
||||||
|
|
||||||
|
@ -75,7 +75,7 @@ def comp_match(item, filter_, level=0):
|
|||||||
# Point #1 of rfc4791-9.7.1
|
# Point #1 of rfc4791-9.7.1
|
||||||
return name == tag
|
return name == tag
|
||||||
if len(filter_) == 1:
|
if len(filter_) == 1:
|
||||||
if filter_[0].tag == xmlutils.make_tag("C", "is-not-defined"):
|
if filter_[0].tag == xmlutils.make_clark("C:is-not-defined"):
|
||||||
# Point #2 of rfc4791-9.7.1
|
# Point #2 of rfc4791-9.7.1
|
||||||
return name != tag
|
return name != tag
|
||||||
if name != tag:
|
if name != tag:
|
||||||
@ -89,14 +89,14 @@ def comp_match(item, filter_, level=0):
|
|||||||
else list(getattr(item.vobject_item,
|
else list(getattr(item.vobject_item,
|
||||||
"%s_list" % tag.lower())))
|
"%s_list" % tag.lower())))
|
||||||
for child in filter_:
|
for child in filter_:
|
||||||
if child.tag == xmlutils.make_tag("C", "prop-filter"):
|
if child.tag == xmlutils.make_clark("C:prop-filter"):
|
||||||
if not any(prop_match(comp, child, "C")
|
if not any(prop_match(comp, child, "C")
|
||||||
for comp in components):
|
for comp in components):
|
||||||
return False
|
return False
|
||||||
elif child.tag == xmlutils.make_tag("C", "time-range"):
|
elif child.tag == xmlutils.make_clark("C:time-range"):
|
||||||
if not time_range_match(item.vobject_item, filter_[0], tag):
|
if not time_range_match(item.vobject_item, filter_[0], tag):
|
||||||
return False
|
return False
|
||||||
elif child.tag == xmlutils.make_tag("C", "comp-filter"):
|
elif child.tag == xmlutils.make_clark("C:comp-filter"):
|
||||||
if not comp_match(item, child, level=level + 1):
|
if not comp_match(item, child, level=level + 1):
|
||||||
return False
|
return False
|
||||||
else:
|
else:
|
||||||
@ -115,20 +115,20 @@ def prop_match(vobject_item, filter_, ns):
|
|||||||
# Point #1 of rfc4791-9.7.2
|
# Point #1 of rfc4791-9.7.2
|
||||||
return name in vobject_item.contents
|
return name in vobject_item.contents
|
||||||
if len(filter_) == 1:
|
if len(filter_) == 1:
|
||||||
if filter_[0].tag == xmlutils.make_tag("C", "is-not-defined"):
|
if filter_[0].tag == xmlutils.make_clark("C:is-not-defined"):
|
||||||
# Point #2 of rfc4791-9.7.2
|
# Point #2 of rfc4791-9.7.2
|
||||||
return name not in vobject_item.contents
|
return name not in vobject_item.contents
|
||||||
if name not in vobject_item.contents:
|
if name not in vobject_item.contents:
|
||||||
return False
|
return False
|
||||||
# Point #3 and #4 of rfc4791-9.7.2
|
# Point #3 and #4 of rfc4791-9.7.2
|
||||||
for child in filter_:
|
for child in filter_:
|
||||||
if ns == "C" and child.tag == xmlutils.make_tag("C", "time-range"):
|
if ns == "C" and child.tag == xmlutils.make_clark("C:time-range"):
|
||||||
if not time_range_match(vobject_item, child, name):
|
if not time_range_match(vobject_item, child, name):
|
||||||
return False
|
return False
|
||||||
elif child.tag == xmlutils.make_tag(ns, "text-match"):
|
elif child.tag == xmlutils.make_clark("%s:text-match" % ns):
|
||||||
if not text_match(vobject_item, child, name, ns):
|
if not text_match(vobject_item, child, name, ns):
|
||||||
return False
|
return False
|
||||||
elif child.tag == xmlutils.make_tag(ns, "param-filter"):
|
elif child.tag == xmlutils.make_clark("%s:param-filter" % ns):
|
||||||
if not param_filter_match(vobject_item, child, name, ns):
|
if not param_filter_match(vobject_item, child, name, ns):
|
||||||
return False
|
return False
|
||||||
else:
|
else:
|
||||||
@ -464,10 +464,10 @@ def param_filter_match(vobject_item, filter_, parent_name, ns):
|
|||||||
children = getattr(vobject_item, "%s_list" % parent_name, [])
|
children = getattr(vobject_item, "%s_list" % parent_name, [])
|
||||||
condition = any(name in child.params for child in children)
|
condition = any(name in child.params for child in children)
|
||||||
if len(filter_) > 0:
|
if len(filter_) > 0:
|
||||||
if filter_[0].tag == xmlutils.make_tag(ns, "text-match"):
|
if filter_[0].tag == xmlutils.make_clark("%s:text-match" % ns):
|
||||||
return condition and text_match(
|
return condition and text_match(
|
||||||
vobject_item, filter_[0], parent_name, ns, name)
|
vobject_item, filter_[0], parent_name, ns, name)
|
||||||
elif filter_[0].tag == xmlutils.make_tag(ns, "is-not-defined"):
|
elif filter_[0].tag == xmlutils.make_clark("%s:is-not-defined" % ns):
|
||||||
return not condition
|
return not condition
|
||||||
else:
|
else:
|
||||||
return condition
|
return condition
|
||||||
@ -488,18 +488,18 @@ def simplify_prefilters(filters, collection_tag="VCALENDAR"):
|
|||||||
if collection_tag != "VCALENDAR":
|
if collection_tag != "VCALENDAR":
|
||||||
simple = False
|
simple = False
|
||||||
break
|
break
|
||||||
if (col_filter.tag != xmlutils.make_tag("C", "comp-filter") or
|
if (col_filter.tag != xmlutils.make_clark("C:comp-filter") or
|
||||||
col_filter.get("name").upper() != "VCALENDAR"):
|
col_filter.get("name").upper() != "VCALENDAR"):
|
||||||
simple = False
|
simple = False
|
||||||
continue
|
continue
|
||||||
simple &= len(col_filter) <= 1
|
simple &= len(col_filter) <= 1
|
||||||
for comp_filter in col_filter:
|
for comp_filter in col_filter:
|
||||||
if comp_filter.tag != xmlutils.make_tag("C", "comp-filter"):
|
if comp_filter.tag != xmlutils.make_clark("C:comp-filter"):
|
||||||
simple = False
|
simple = False
|
||||||
continue
|
continue
|
||||||
tag = comp_filter.get("name").upper()
|
tag = comp_filter.get("name").upper()
|
||||||
if comp_filter.find(
|
if comp_filter.find(
|
||||||
xmlutils.make_tag("C", "is-not-defined")) is not None:
|
xmlutils.make_clark("C:is-not-defined")) is not None:
|
||||||
simple = False
|
simple = False
|
||||||
continue
|
continue
|
||||||
simple &= len(comp_filter) <= 1
|
simple &= len(comp_filter) <= 1
|
||||||
@ -507,7 +507,7 @@ def simplify_prefilters(filters, collection_tag="VCALENDAR"):
|
|||||||
if tag not in ("VTODO", "VEVENT", "VJOURNAL"):
|
if tag not in ("VTODO", "VEVENT", "VJOURNAL"):
|
||||||
simple = False
|
simple = False
|
||||||
break
|
break
|
||||||
if time_filter.tag != xmlutils.make_tag("C", "time-range"):
|
if time_filter.tag != xmlutils.make_clark("C:time-range"):
|
||||||
simple = False
|
simple = False
|
||||||
continue
|
continue
|
||||||
start = time_filter.get("start")
|
start = time_filter.get("start")
|
||||||
|
@ -23,7 +23,6 @@ Helper functions for XML.
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
import copy
|
import copy
|
||||||
import re
|
|
||||||
import xml.etree.ElementTree as ET
|
import xml.etree.ElementTree as ET
|
||||||
from collections import OrderedDict
|
from collections import OrderedDict
|
||||||
from http import client
|
from http import client
|
||||||
@ -54,9 +53,6 @@ for short, url in NAMESPACES.items():
|
|||||||
NAMESPACES_REV[url] = short
|
NAMESPACES_REV[url] = short
|
||||||
ET.register_namespace("" if short == "D" else short, url)
|
ET.register_namespace("" if short == "D" else short, url)
|
||||||
|
|
||||||
CLARK_TAG_REGEX = re.compile(r"{(?P<namespace>[^}]*)}(?P<tag>.*)", re.VERBOSE)
|
|
||||||
HUMAN_REGEX = re.compile(r"(?P<namespace>[^:{}]*):(?P<tag>.*)", re.VERBOSE)
|
|
||||||
|
|
||||||
|
|
||||||
def pretty_xml(element, level=0):
|
def pretty_xml(element, level=0):
|
||||||
"""Indent an ElementTree ``element`` and its children."""
|
"""Indent an ElementTree ``element`` and its children."""
|
||||||
@ -79,34 +75,47 @@ def pretty_xml(element, level=0):
|
|||||||
return '<?xml version="1.0"?>\n%s' % ET.tostring(element, "unicode")
|
return '<?xml version="1.0"?>\n%s' % ET.tostring(element, "unicode")
|
||||||
|
|
||||||
|
|
||||||
def make_tag(short_name, local):
|
def make_clark(human_tag):
|
||||||
"""Get XML Clark notation {uri(``short_name``)}``local``."""
|
"""Get XML Clark notation from human tag ``human_tag``.
|
||||||
return "{%s}%s" % (NAMESPACES[short_name], local)
|
|
||||||
|
|
||||||
|
If ``human_tag`` is already in XML Clark notation it is returned as-is.
|
||||||
def tag_from_clark(name):
|
|
||||||
"""Get a human-readable variant of the XML Clark notation tag ``name``.
|
|
||||||
|
|
||||||
For a given name using the XML Clark notation, return a human-readable
|
|
||||||
variant of the tag name for known namespaces. Otherwise, return the name as
|
|
||||||
is.
|
|
||||||
|
|
||||||
"""
|
"""
|
||||||
match = CLARK_TAG_REGEX.match(name)
|
if human_tag.startswith("{"):
|
||||||
if match and match.group("namespace") in NAMESPACES_REV:
|
ns, tag = human_tag[len("{"):].split("}", maxsplit=1)
|
||||||
args = {
|
if not ns or not tag:
|
||||||
"ns": NAMESPACES_REV[match.group("namespace")],
|
raise ValueError("Invalid XML tag: %r" % human_tag)
|
||||||
"tag": match.group("tag")}
|
return human_tag
|
||||||
return "%(ns)s:%(tag)s" % args
|
ns_prefix, tag = human_tag.split(":", maxsplit=1)
|
||||||
return name
|
if not ns_prefix or not tag:
|
||||||
|
raise ValueError("Invalid XML tag: %r" % human_tag)
|
||||||
|
ns = NAMESPACES.get(ns_prefix)
|
||||||
|
if not ns:
|
||||||
|
raise ValueError("Unknown XML namespace prefix: %r" % human_tag)
|
||||||
|
return "{%s}%s" % (ns, tag)
|
||||||
|
|
||||||
|
|
||||||
def tag_from_human(name):
|
def make_human_tag(clark_tag):
|
||||||
"""Get an XML Clark notation tag from human-readable variant ``name``."""
|
"""Replace known namespaces in XML Clark notation ``clark_tag`` with
|
||||||
match = HUMAN_REGEX.match(name)
|
prefix.
|
||||||
if match and match.group("namespace") in NAMESPACES:
|
|
||||||
return make_tag(match.group("namespace"), match.group("tag"))
|
If the namespace is not in ``NAMESPACES`` the tag is returned as-is.
|
||||||
return name
|
|
||||||
|
"""
|
||||||
|
if not clark_tag.startswith("{"):
|
||||||
|
ns_prefix, tag = clark_tag.split(":", maxsplit=1)
|
||||||
|
if not ns_prefix or not tag:
|
||||||
|
raise ValueError("Invalid XML tag: %r" % clark_tag)
|
||||||
|
if ns_prefix not in NAMESPACES:
|
||||||
|
raise ValueError("Unknown XML namespace prefix: %r" % clark_tag)
|
||||||
|
return clark_tag
|
||||||
|
ns, tag = clark_tag[len("{"):].split("}", maxsplit=1)
|
||||||
|
if not ns or not tag:
|
||||||
|
raise ValueError("Invalid XML tag: %r" % clark_tag)
|
||||||
|
ns_prefix = NAMESPACES_REV.get(ns)
|
||||||
|
if ns_prefix:
|
||||||
|
return "%s:%s" % (ns_prefix, tag)
|
||||||
|
return clark_tag
|
||||||
|
|
||||||
|
|
||||||
def make_response(code):
|
def make_response(code):
|
||||||
@ -120,10 +129,10 @@ def make_href(base_prefix, href):
|
|||||||
return quote("%s%s" % (base_prefix, href))
|
return quote("%s%s" % (base_prefix, href))
|
||||||
|
|
||||||
|
|
||||||
def webdav_error(namespace, name):
|
def webdav_error(human_tag):
|
||||||
"""Generate XML error message."""
|
"""Generate XML error message."""
|
||||||
root = ET.Element(make_tag("D", "error"))
|
root = ET.Element(make_clark("D:error"))
|
||||||
root.append(ET.Element(make_tag(namespace, name)))
|
root.append(ET.Element(human_tag))
|
||||||
return root
|
return root
|
||||||
|
|
||||||
|
|
||||||
@ -145,29 +154,29 @@ def props_from_request(xml_request, actions=("set", "remove")):
|
|||||||
return result
|
return result
|
||||||
|
|
||||||
for action in actions:
|
for action in actions:
|
||||||
action_element = xml_request.find(make_tag("D", action))
|
action_element = xml_request.find(make_clark("D:%s" % action))
|
||||||
if action_element is not None:
|
if action_element is not None:
|
||||||
break
|
break
|
||||||
else:
|
else:
|
||||||
action_element = xml_request
|
action_element = xml_request
|
||||||
|
|
||||||
prop_element = action_element.find(make_tag("D", "prop"))
|
prop_element = action_element.find(make_clark("D:prop"))
|
||||||
if prop_element is not None:
|
if prop_element is not None:
|
||||||
for prop in prop_element:
|
for prop in prop_element:
|
||||||
if prop.tag == make_tag("D", "resourcetype"):
|
if prop.tag == make_clark("D:resourcetype"):
|
||||||
for resource_type in prop:
|
for resource_type in prop:
|
||||||
if resource_type.tag == make_tag("C", "calendar"):
|
if resource_type.tag == make_clark("C:calendar"):
|
||||||
result["tag"] = "VCALENDAR"
|
result["tag"] = "VCALENDAR"
|
||||||
break
|
break
|
||||||
elif resource_type.tag == make_tag("CR", "addressbook"):
|
elif resource_type.tag == make_clark("CR:addressbook"):
|
||||||
result["tag"] = "VADDRESSBOOK"
|
result["tag"] = "VADDRESSBOOK"
|
||||||
break
|
break
|
||||||
elif prop.tag == make_tag("C", "supported-calendar-component-set"):
|
elif prop.tag == make_clark("C:supported-calendar-component-set"):
|
||||||
result[tag_from_clark(prop.tag)] = ",".join(
|
result[make_human_tag(prop.tag)] = ",".join(
|
||||||
supported_comp.attrib["name"]
|
supported_comp.attrib["name"]
|
||||||
for supported_comp in prop
|
for supported_comp in prop
|
||||||
if supported_comp.tag == make_tag("C", "comp"))
|
if supported_comp.tag == make_clark("C:comp"))
|
||||||
else:
|
else:
|
||||||
result[tag_from_clark(prop.tag)] = prop.text
|
result[make_human_tag(prop.tag)] = prop.text
|
||||||
|
|
||||||
return result
|
return result
|
||||||
|
Loading…
Reference in New Issue
Block a user