Try new strategy for CalDAV report filter parsing.
[citadel.git] / webcit-ng / server / caldav_reports.c
index 31fe712bacf66662156fbe47c7c95b9cba5c0b16..05d3b9ef65e9b37c5b92a26f280e9d2b9f063fbf 100644 (file)
@@ -4,9 +4,8 @@
 
 #include "webcit.h"
 
-// Shorthand for the XML namespace of CalDAV
-#define CAL "urn:ietf:params:xml:ns:caldav:"
-#define CALLEN sizeof(CAL)-1
+#define CAL "urn:ietf:params:xml:ns:caldav:"           // Shorthand for the XML namespace of CalDAV
+#define CALLEN sizeof(CAL)-1                           // And the length of that string
 
 // A CalDAV REPORT can only be one type.  This is stored in the report_type member.
 enum cr_type {
@@ -273,78 +272,56 @@ void caldav_report_one_item(struct http_transaction *h, struct ctdlsession *c, S
 }
 
 
-// Called by caldav_apply_filters() to apply ONE filter.
-// Returns 0 if the calendar item does not match the filter.
-// Returns 1 if the calendar item DOES match the filter.
-int caldav_apply_one_filter(void *cal, char *filter) {
-       syslog(LOG_DEBUG, "applying filter: %s", filter);
-
-       char this_filter[SIZ];          // we have to copy the filter string because we will destructively tokenize it
-       safestrncpy(this_filter, filter, sizeof(this_filter));
-
-       char *t[10] = { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL } ;
-       char *f = this_filter;
-       int num_tokens = 0;
-       while ( (t[num_tokens]=strtok_r(f, "|", &f)) && (num_tokens<10) ) {
-               ++num_tokens;
-       }
-
-       // BEGIN experimental block -- see what happens when we cast to the wrong type
-
-       //icalcomponent *foo_comp = (icalcomponent *) cal;
-       //icalproperty *foo_prop = (icalproperty *) cal;
-       //icalparameter *foo_param = (icalparameter *) cal;
-
-       // END experimental block
-
-       // Handle the individual filters defined in RFC4791 9.7.1 through 9.7.5
-
-       if (!strcasecmp(t[1], "comp-filter")) {                         // RFC4791 9.7.1 - filter by component
-               syslog(LOG_DEBUG, "component filter FIXME not implemented yet");
-               if (icalcomponent_isa_component(cal)) {
-                       syslog(LOG_DEBUG, "\033[32m yes this is a component \033[0m");
-               }
-               else {
-                       syslog(LOG_DEBUG, "\033[31m no this is not a component \033[0m");
+// Recursive function to apply CalDAV FILTERS to a calendar item.
+// Returns zero if the calendar item was disqualified by a filter, nonzero if the calendar item still qualifies.
+int caldav_apply_filters(void *cal, Array *filters) {
+
+       int f = 0;                                      // filter number iterator
+       int qual = 1;                                   // 0 for disqualify, 1 for qualify
+
+       while ( (f<array_len(filters)) && (qual) ) {
+               syslog(LOG_DEBUG, "caldav_apply_filters(%d) %s", f, array_get_element_at(filters, f) );
+
+               // Tokenize the filter (a future performance hack would be to pre-tokenize instead of storing delimited strings)
+               char this_filter[SIZ];
+               safestrncpy(this_filter, array_get_element_at(filters, f), sizeof(this_filter));
+               char *t[10] = { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL } ;
+               char *ft = this_filter;
+               int num_tokens = 0;
+               while ( (t[num_tokens]=strtok_r(ft, "|", &ft)) && (num_tokens<10) ) {
+                       ++num_tokens;
                }
-       }
+               int level = atoi(t[0]);
 
-       else if (!strcasecmp(t[1], "prop-filter")) {                    // RFC4791 9.7.2 - filter by property
-               syslog(LOG_DEBUG, "property filter FIXME not implemented yet");
-       }
+               // Handle the individual filters defined in RFC4791 9.7.1 through 9.7.5
 
-       else if (!strcasecmp(t[1], "param-filter")) {                   // RFC4791 9.7.3 - filter by parameter
-               syslog(LOG_DEBUG, "parameter filter FIXME not implemented yet");
-       }
-
-       else if (!strcasecmp(t[1], "is-not-defined")) {                 // RFC4791 9.7.4
-               syslog(LOG_DEBUG, "is-not-defined filter FIXME not implemented yet");
-       }
-
-       else if (!strcasecmp(t[1], "text-match")) {                     // RFC4791 9.7.5
-               syslog(LOG_DEBUG, "text match filter FIXME not implemented yet");
-       }
+               if (!strcasecmp(t[1], "comp-filter")) {                         // RFC4791 9.7.1 - filter by component
+                       syslog(LOG_DEBUG, "component filter at level %d FIXME not implemented yet", level);
+                       if (icalcomponent_isa_component(cal)) {
+                               // yes this is a component
+                       }
+               }
 
-       return(1);
-}
+               else if (!strcasecmp(t[1], "prop-filter")) {                    // RFC4791 9.7.2 - filter by property
+                       syslog(LOG_DEBUG, "property filter FIXME not implemented yet");
+               }
 
+               else if (!strcasecmp(t[1], "param-filter")) {                   // RFC4791 9.7.3 - filter by parameter
+                       syslog(LOG_DEBUG, "parameter filter FIXME not implemented yet");
+               }
 
-// Recursive function to apply CalDAV FILTERS to a calendar item.
-// Returns zero if the calendar item was disqualified by a filter, nonzero if the calendar item still qualifies.
-int caldav_apply_filters(void *cal, Array *filters, int index) {
+               else if (!strcasecmp(t[1], "is-not-defined")) {                 // RFC4791 9.7.4
+                       syslog(LOG_DEBUG, "is-not-defined filter FIXME not implemented yet");
+               }
 
-       // Apply *this* filter.
-       if (caldav_apply_one_filter(cal, array_get_element_at(filters, index)) == 0) {
-               return(0);
-       }
+               else if (!strcasecmp(t[1], "text-match")) {                     // RFC4791 9.7.5
+                       syslog(LOG_DEBUG, "text match filter FIXME not implemented yet");
+               }
 
-       // If we get to this point, the current filter has passed, and we move on to the next one.
-       if (index < array_len(filters)-1) {
-               return(caldav_apply_filters(cal, filters, index+1));
+               ++f;
        }
 
-       // If we got this far, every filter passed, and the calendar item qualifies for output.
-       return(1);
+       return(qual);
 }
 
 
@@ -409,7 +386,7 @@ void caldav_report(struct http_transaction *h, struct ctdlsession *c) {
                                int qualify = 1;
 
                                // If there was a filter stanza, run this calendar item through the filters.
-                               qualify = caldav_apply_filters(cal, crp.filters, 0);
+                               qualify = caldav_apply_filters(cal, crp.filters);
                                syslog(LOG_DEBUG, "Message %ld does%s qualify", m, (qualify ? "" : " NOT"));
 
                                // Did this calendar item match the query?  If so, output it.