From: Art Cancro Date: Tue, 13 Feb 2024 22:31:28 +0000 (-0500) Subject: Yet another attempted framework for caldav filters. X-Git-Tag: v999~46 X-Git-Url: https://code.citadel.org/?p=citadel.git;a=commitdiff_plain;h=f6edf9b754dcd04e8eab7fa53dc62b57ad5b14cc Yet another attempted framework for caldav filters. CalDAV is stupid, the people who created it are stupid, and anyone who still thinks it was a good idea are stupid. But now we're stuck with it and I have to implement it. --- diff --git a/webcit-ng/server/caldav_reports.c b/webcit-ng/server/caldav_reports.c index 5883c7347..b28554e0c 100644 --- a/webcit-ng/server/caldav_reports.c +++ b/webcit-ng/server/caldav_reports.c @@ -16,17 +16,18 @@ enum cr_type { // Data type for CalDAV Report Parameters. // As we slog our way through the XML we learn what the client is asking for // and build up the contents of this data type. -struct cr_parms { +struct cr_params { int tag_nesting_level; // not needed, just kept for pretty-printing enum cr_type report_type; // which RFC4791 section 7 REPORT are we generating StrBuf *Chardata; // XML chardata in between tags is built up here StrBuf *Hrefs; // list of items requested by a `calendar-multiget` REPORT + Array *filters; // If the query contains a FILTER stanza, the filter criteria are populated here }; // XML parser callback void caldav_xml_start(void *data, const char *el, const char **attr) { - struct cr_parms *crp = (struct cr_parms *) data; + struct cr_params *crp = (struct cr_params *) data; #ifdef DEBUG_XML_PARSE // logging @@ -34,13 +35,13 @@ void caldav_xml_start(void *data, const char *el, const char **attr) { char indent[256]; indent[0] = 0; for (i=0; itag_nesting_level; ++i) { - strcat(indent, "··"); + strcat(indent, " "); } syslog(LOG_DEBUG, "%s<%s>", indent, el); ++crp->tag_nesting_level; indent[0] = 0; for (i=0; itag_nesting_level; ++i) { - strcat(indent, "··"); + strcat(indent, " "); } for (i = 0; attr[i] != NULL; i += 2) { syslog(LOG_DEBUG, "%sAttribute '%s' = '%s'", indent, attr[i], attr[i + 1]); @@ -63,12 +64,64 @@ void caldav_xml_start(void *data, const char *el, const char **attr) { crp->report_type = cr_freebusy_query; } + // RFC4791 9.7 create a filter array if this query contains a "CALDAV:filter" stanza + else if (!strcasecmp(el, "urn:ietf:params:xml:ns:caldav:filter")) { + crp->filters = array_new(SIZ); + } + + // RFC4791 9.7.1 CALDAV:comp-filter XML Element + else if ( (!strcasecmp(el, "urn:ietf:params:xml:ns:caldav:comp-filter")) + && (crp->filters) + && (attr[0]) + && (attr[1]) + ) { + char newfilter[SIZ]; + snprintf(newfilter, SIZ, "comp-filter|%s|%s", attr[0], attr[1]); + array_append(crp->filters, newfilter); + syslog(LOG_DEBUG, "%s", newfilter); + } + + // RFC4791 9.7.2 CALDAV:prop-filter XML Element + else if (!strcasecmp(el, "urn:ietf:params:xml:ns:caldav:prop-filter")) { + if (crp->filters) { + char newfilter[SIZ]; + snprintf(newfilter, SIZ, "hi there"); + array_append(crp->filters, newfilter); + } + } + + // RFC4791 9.7.3 CALDAV:param-filter XML Element + else if (!strcasecmp(el, "urn:ietf:params:xml:ns:caldav:param-filter")) { + if (crp->filters) { + char newfilter[SIZ]; + snprintf(newfilter, SIZ, "hi there"); + array_append(crp->filters, newfilter); + } + } + + // RFC4791 9.7.4 CALDAV:is-not-defined XML Element + else if (!strcasecmp(el, "urn:ietf:params:xml:ns:caldav:is-not-defined")) { + if (crp->filters) { + char newfilter[SIZ]; + snprintf(newfilter, SIZ, "hi there"); + array_append(crp->filters, newfilter); + } + } + + // RFC4791 9.7.5 CALDAV:text-match XML Element + else if (!strcasecmp(el, "urn:ietf:params:xml:ns:caldav:text-match")) { + if (crp->filters) { + char newfilter[SIZ]; + snprintf(newfilter, SIZ, "hi there"); + array_append(crp->filters, newfilter); + } + } } // XML parser callback void caldav_xml_end(void *data, const char *el) { - struct cr_parms *crp = (struct cr_parms *) data; + struct cr_params *crp = (struct cr_params *) data; --crp->tag_nesting_level; @@ -78,7 +131,7 @@ void caldav_xml_end(void *data, const char *el) { char indent[256]; indent[0] = 0; for (i=0; itag_nesting_level; ++i) { - strcat(indent, "··"); + strcat(indent, " "); } syslog(LOG_DEBUG, "%s", indent, el); // end logging @@ -103,7 +156,7 @@ void caldav_xml_end(void *data, const char *el) { // XML parser callback void caldav_xml_chardata(void *data, const XML_Char *s, int len) { - struct cr_parms *crp = (struct cr_parms *) data; + struct cr_params *crp = (struct cr_params *) data; char *app = malloc(len+1); if (!app) { @@ -126,7 +179,7 @@ void caldav_xml_chardata(void *data, const XML_Char *s, int len) { char indent[256]; indent[0] = 0; for (i=0; itag_nesting_level; ++i) { - strcat(indent, "··"); + strcat(indent, " "); } syslog(LOG_DEBUG, "%s%s", indent, app, len); } @@ -240,14 +293,19 @@ void caldav_report_one_item(struct http_transaction *h, struct ctdlsession *c, S } +void caldav_apply_filter(struct cr_params *crp, char *xml_body, long xml_length) { + TRACE; +} + + // Called by report_the_room_itself() in room_functions.c when a CalDAV REPORT method // is requested on a calendar room. We fire up an XML Parser to decode the request and // hopefully produce the correct output. void caldav_report(struct http_transaction *h, struct ctdlsession *c) { - struct cr_parms crp; + struct cr_params crp; char buf[1024]; - memset(&crp, 0, sizeof(struct cr_parms)); + memset(&crp, 0, sizeof(struct cr_params)); XML_Parser xp = XML_ParserCreateNS("UTF-8", ':'); if (xp == NULL) { @@ -297,11 +355,13 @@ void caldav_report(struct http_transaction *h, struct ctdlsession *c) { StrBuf *one_item = fetch_ical(c, m); icalcomponent *cal = icalcomponent_new_from_string(ChrPtr(one_item)); - // qualify will be set to nonzero if this calendar item is a match for the QUERY. - int qualify = 0; + // Does this calendar item qualify for output? + int qualify = 1; - // this is a horrible temporary hack to output every item (for now) - qualify = 1; + // FIXME put filters here + if (crp.filters) { + // apply the filters + } // Did this calendar item match the query? If so, output it. if (qualify) { @@ -340,6 +400,10 @@ void caldav_report(struct http_transaction *h, struct ctdlsession *c) { FreeStrBuf(&crp.Hrefs); crp.Hrefs = NULL; } + if (crp.filters) { + array_free(crp.filters); + crp.filters = NULL; + } StrBufAppendPrintf(ReportOut, "\n"); // End the REPORT. diff --git a/webcit-ng/server/webcit.h b/webcit-ng/server/webcit.h index a773a32c5..ec66ece33 100644 --- a/webcit-ng/server/webcit.h +++ b/webcit-ng/server/webcit.h @@ -9,7 +9,7 @@ //#define DEBUG_HTTP //#define REQUEST_BODY_TO_STDERR //#define RESPONSE_BODY_TO_STDERR -#define DEBUG_XML_PARSE +//#define DEBUG_XML_PARSE #define SHOW_ME_VAPPEND_PRINTF