mirror of
https://github.com/Kozea/Radicale.git
synced 2025-08-28 19:40:54 +00:00
Add basic free-busy report
This commit is contained in:
parent
6b34323c1e
commit
7b0d88ff0d
5 changed files with 156 additions and 43 deletions
|
@ -23,6 +23,7 @@ import datetime
|
|||
import posixpath
|
||||
import socket
|
||||
import xml.etree.ElementTree as ET
|
||||
import vobject
|
||||
from http import client
|
||||
from typing import (Any, Callable, Iterable, Iterator, List, Optional,
|
||||
Sequence, Tuple, Union)
|
||||
|
@ -37,12 +38,38 @@ from radicale.app.base import Access, ApplicationBase
|
|||
from radicale.item import filter as radicale_filter
|
||||
from radicale.log import logger
|
||||
|
||||
def free_busy_report(base_prefix: str, path: str, xml_request: Optional[ET.Element],
|
||||
collection: storage.BaseCollection, encoding: str,
|
||||
unlock_storage_fn: Callable[[], None]
|
||||
) -> Tuple[int, str]:
|
||||
multistatus = ET.Element(xmlutils.make_clark("D:multistatus"))
|
||||
if xml_request is None:
|
||||
return client.MULTI_STATUS, multistatus
|
||||
root = xml_request
|
||||
if (root.tag == xmlutils.make_clark("C:free-busy-query") and
|
||||
collection.tag != "VCALENDAR"):
|
||||
logger.warning("Invalid REPORT method %r on %r requested",
|
||||
xmlutils.make_human_tag(root.tag), path)
|
||||
return client.FORBIDDEN, xmlutils.webdav_error("D:supported-report")
|
||||
|
||||
time_range_element = root.find(xmlutils.make_clark("C:time-range"))
|
||||
start,end = radicale_filter.time_range_timestamps(time_range_element)
|
||||
items = list(collection.get_by_time(start, end))
|
||||
|
||||
cal = vobject.iCalendar()
|
||||
for item in items:
|
||||
occurrences = radicale_filter.time_range_fill(item.vobject_item, time_range_element, "VEVENT")
|
||||
for occurrence in occurrences:
|
||||
vfb = cal.add('vfreebusy')
|
||||
vfb.add('dtstamp').value = item.vobject_item.vevent.dtstamp.value
|
||||
vfb.add('dtstart').value, vfb.add('dtend').value = occurrence
|
||||
return (client.OK, cal.serialize())
|
||||
|
||||
def xml_report(base_prefix: str, path: str, xml_request: Optional[ET.Element],
|
||||
collection: storage.BaseCollection, encoding: str,
|
||||
unlock_storage_fn: Callable[[], None]
|
||||
) -> Tuple[int, ET.Element]:
|
||||
"""Read and answer REPORT requests.
|
||||
"""Read and answer REPORT requests that return XML.
|
||||
|
||||
Read rfc3253-3.6 for info.
|
||||
|
||||
|
@ -426,13 +453,27 @@ class ApplicationPartReport(ApplicationBase):
|
|||
else:
|
||||
assert item.collection is not None
|
||||
collection = item.collection
|
||||
try:
|
||||
status, xml_answer = xml_report(
|
||||
base_prefix, path, xml_content, collection, self._encoding,
|
||||
lock_stack.close)
|
||||
except ValueError as e:
|
||||
logger.warning(
|
||||
"Bad REPORT request on %r: %s", path, e, exc_info=True)
|
||||
return httputils.BAD_REQUEST
|
||||
headers = {"Content-Type": "text/xml; charset=%s" % self._encoding}
|
||||
return status, headers, self._xml_response(xml_answer)
|
||||
|
||||
if xml_content is not None and \
|
||||
xml_content.tag == xmlutils.make_clark("C:free-busy-query"):
|
||||
try:
|
||||
status, body = free_busy_report(
|
||||
base_prefix, path, xml_content, collection, self._encoding,
|
||||
lock_stack.close)
|
||||
except ValueError as e:
|
||||
logger.warning(
|
||||
"Bad REPORT request on %r: %s", path, e, exc_info=True)
|
||||
return httputils.BAD_REQUEST
|
||||
headers = {"Content-Type": "text/calendar; charset=%s" % self._encoding}
|
||||
return status, headers, body
|
||||
else:
|
||||
try:
|
||||
status, xml_answer = xml_report(
|
||||
base_prefix, path, xml_content, collection, self._encoding,
|
||||
lock_stack.close)
|
||||
except ValueError as e:
|
||||
logger.warning(
|
||||
"Bad REPORT request on %r: %s", path, e, exc_info=True)
|
||||
return httputils.BAD_REQUEST
|
||||
headers = {"Content-Type": "text/xml; charset=%s" % self._encoding}
|
||||
return status, headers, self._xml_response(xml_answer)
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue