Hi, Debian has recently switched to libical >= 2.0.0 that hides some previously exported symbols.
I rewrote custom icalrecur_add_rule to reconstruct RRULE from XML or JSON to be reparsed again with icalrecurrencetype_from_string(char *). I understand this is not optimal, but I believe that simplicity of the code outweights the speed. And I suggest to drop support for libical << 2.0.0 for simplicity. And in that case I will weed out the HAVE_ICAL_<foo> macros and send another patch with that (0018-* is just basic to get it compiled). Please review (and apply) attached patch. I used buf_* functions to reconstruct the cstring, but it desperately needs a review if I am using those correctly and if it doesn't leak memory (it probably does? But in that case json_x_value leaks it as well). But hey it compiles! :) Cheers, -- Ondřej Surý <ond...@sury.org> Knot DNS (https://www.knot-dns.cz/) – a high-performance DNS server Knot Resolver (https://www.knot-resolver.cz/) – secure, privacy-aware, fast DNS(SEC) resolver Vše pro chleba (https://vseprochleba.cz) – Potřeby pro pečení chleba všeho druhu
From: =?utf-8?q?Ond=C5=99ej_Sur=C3=BD?= <ond...@sury.org> Date: Mon, 23 May 2016 23:15:44 +0200 Subject: Replace the custom icalrecur_add_rule() with reconstructing RRULE and parsing it with standard icalrecurrencetype_from_string() --- imap/jcal.c | 22 ++++++------ imap/xcal.c | 112 +++++++++++------------------------------------------------- 2 files changed, 30 insertions(+), 104 deletions(-) diff --git a/imap/jcal.c b/imap/jcal.c index 52b2534..98f8f31 100644 --- a/imap/jcal.c +++ b/imap/jcal.c @@ -455,10 +455,6 @@ struct icalrecur_parser { }; extern icalrecurrencetype_frequency icalrecur_string_to_freq(const char* str); -extern void icalrecur_add_byrules(struct icalrecur_parser *parser, short *array, - int size, char* vals); -extern void icalrecur_add_bydayrules(struct icalrecur_parser *parser, - const char* vals); static const char *_json_x_value(json_t *jvalue) { @@ -549,19 +545,23 @@ static icalvalue *json_object_to_icalvalue(json_t *jvalue, case ICAL_RECUR_VALUE: if (json_is_object(jvalue)) { - struct icalrecurrencetype *rt = NULL; + struct icalrecurrencetype rt; + static struct buf buf = BUF_INITIALIZER; const char *key; json_t *val; json_object_foreach(jvalue, key, val) { - rt = icalrecur_add_rule(&rt, key, val, - (int (*)(void *)) &json_integer_value, - (const char * (*)(void *)) &json_x_value); - if (!rt) break; + buf_appendcstr(&buf, (const char *)key); + buf_appendcstr(&buf, "="); + buf_appendcstr(&buf, (const char *)json_x_value(val)); + buf_appendcstr(&buf, ";"); } - if (rt && rt->freq != ICAL_NO_RECURRENCE) - value = icalvalue_new_recur(*rt); + /* Now reparse it with libical function */ + rt = icalrecurrencetype_from_string((const char *)buf_cstring(&buf)); + + if (rt.freq != ICAL_NO_RECURRENCE) + value = icalvalue_new_recur(rt); } else syslog(LOG_WARNING, "jCal object object expected"); diff --git a/imap/xcal.c b/imap/xcal.c index e9f73b0..79f30ca 100644 --- a/imap/xcal.c +++ b/imap/xcal.c @@ -681,92 +681,6 @@ extern icalrecurrencetype_frequency icalrecur_string_to_freq(const char* str); #ifdef HAVE_RSCALE extern icalrecurrencetype_skip icalrecur_string_to_skip(const char* str); #endif -extern void icalrecur_add_byrules(struct icalrecur_parser *parser, short *array, - int size, char* vals); -extern void icalrecur_add_bydayrules(struct icalrecur_parser *parser, - const char* vals); - -struct icalrecurrencetype *icalrecur_add_rule(struct icalrecurrencetype **rt, - const char *rpart, void *data, - int (*get_int)(void *), - const char* (*get_str)(void *)) -{ - static struct icalrecur_parser parser; - - if (!*rt) { - /* Initialize */ - *rt = &parser.rt; - icalrecurrencetype_clear(*rt); - } - - if (!strcmp(rpart, "freq")) { - (*rt)->freq = icalrecur_string_to_freq(get_str(data)); - } -#ifdef HAVE_RSCALE - else if (!strcmp(rpart, "rscale")) { - (*rt)->rscale = icalmemory_tmp_copy(get_str(data)); - } - else if (!strcmp(rpart, "skip")) { - (*rt)->skip = icalrecur_string_to_skip(get_str(data)); - } -#endif - else if (!strcmp(rpart, "count")) { - (*rt)->count = get_int(data); - } - else if (!strcmp(rpart, "until")) { - (*rt)->until = icaltime_from_string(get_str(data)); - } - else if (!strcmp(rpart, "interval")) { - (*rt)->interval = get_int(data); - if ((*rt)->interval < 1) (*rt)->interval = 1; /* MUST be >= 1 */ - } - else if (!strcmp(rpart, "wkst")) { - (*rt)->week_start = icalrecur_string_to_weekday(get_str(data)); - } - else if (!strcmp(rpart, "byday")) { - icalrecur_add_bydayrules(&parser, get_str(data)); - } - else { - int i; - - for (i = 0; recurmap[i].str && strcmp(rpart, recurmap[i].str); i++); - - if (recurmap[i].str) { - short *array = - (short *)((size_t) *rt + recurmap[i].offset); - int limit = recurmap[i].limit; - - icalrecur_add_byrules(&parser, array, limit, - icalmemory_tmp_copy(get_str(data))); - } - else { - syslog(LOG_WARNING, "Unknown recurrence rule-part: %s", rpart); - icalrecurrencetype_clear(*rt); - *rt = NULL; - } - } - -#ifdef HAVE_RSCALE - /* When "RSCALE" is not present the default is "YES". - When "RSCALE" is present the default is "BACKWARD". */ - if (!(*rt)->rscale) (*rt)->skip = ICAL_SKIP_YES; - else if ((*rt)->skip == ICAL_SKIP_NO) (*rt)->skip = ICAL_SKIP_BACKWARD; -#endif - - return *rt; -} - - -int xmlElementContent_to_int(void *content) -{ - return atoi((const char *) content); -} - -const char *xmlElementContent_to_str(void *content) -{ - return (const char *) content; -} - /* * Construct an iCalendar property value from XML content. @@ -868,22 +782,34 @@ static icalvalue *xml_element_to_icalvalue(xmlNodePtr xtype, } case ICAL_RECUR_VALUE: { - struct icalrecurrencetype *rt = NULL; + static struct buf buf = BUF_INITIALIZER; + struct icalrecurrencetype rt; + buf_reset(&buf); + + char *dst, *str; + size_t dst_len = 0, str_len; + + /* First we count required length of the RRULE string */ for (node = xmlFirstElementChild(xtype); node; node = xmlNextElementSibling(node)) { content = xmlNodeGetContent(node); - rt = icalrecur_add_rule(&rt, (const char *) node->name, content, - &xmlElementContent_to_int, - &xmlElementContent_to_str); + + buf_appendcstr(&buf, (const char *)node->name); + buf_appendcstr(&buf, (const char *)"="); + buf_appendcstr(&buf, (const char *)content); + buf_appendcstr(&buf, (const char *)";"); + xmlFree(content); content = NULL; - if (!rt) break; } - if (rt && rt->freq != ICAL_NO_RECURRENCE) - value = icalvalue_new_recur(*rt); + /* Now reparse it with libical function */ + rt = icalrecurrencetype_from_string((const char *)buf_cstring(&buf)); + + if (rt.freq != ICAL_NO_RECURRENCE) + value = icalvalue_new_recur(rt); break; }
From: =?utf-8?q?Ond=C5=99ej_Sur=C3=BD?= <ond...@sury.org> Date: Fri, 13 May 2016 15:27:35 +0200 Subject: Require libical >= 2.0 and define the libical feature macros according to that --- configure.ac | 22 +++++++++------------- 1 file changed, 9 insertions(+), 13 deletions(-) diff --git a/configure.ac b/configure.ac index 8e460d3..cfeb4de 100644 --- a/configure.ac +++ b/configure.ac @@ -1209,7 +1209,7 @@ dnl ENABLE_RSS=yes ENABLE_DAV=yes PKG_CHECK_MODULES([XML2], [libxml-2.0],,AC_MSG_ERROR([Need libxml-2.0 for http])) - PKG_CHECK_MODULES([ICAL], [libical],,AC_MSG_ERROR([Need libical for http])) + PKG_CHECK_MODULES([ICAL], [libical >= 2.0],,AC_MSG_ERROR([Need libical >= 2.0.0 for http])) PKG_CHECK_MODULES([SQLITE3], [sqlite3],,AC_MSG_ERROR([Need sqlite3 for http])) PKG_CHECK_MODULES([JSON], [jansson],,AC_MSG_ERROR([Need jansson for http])) @@ -1227,9 +1227,8 @@ dnl AC_DEFINE(HAVE_TZ_BY_REF,[], [Build TZ by ref support into httpd?])) - AC_EGREP_HEADER(ICAL_TZUNTIL_PROPERTY, ical.h, - AC_DEFINE(HAVE_TZDIST_PROPS,[], - [Do we have built-in support for TZdist props?])) + AC_DEFINE(HAVE_TZDIST_PROPS,[], + [Do we have built-in support for TZdist props?]) CYRUS_OPENDKIM_CHK() if test "$opendkimlib" = "yes"; then @@ -1238,17 +1237,14 @@ dnl AC_DEFINE(WITH_DKIM,[],[Build DKIM support into iSchedule?]) fi - AC_EGREP_HEADER(ICAL_SCHEDULESTATUS_PARAMETER, ical.h, - AC_DEFINE(HAVE_SCHEDULING_PARAMS,[], - [Do we have built-in support for scheduling params?])) + AC_DEFINE(HAVE_SCHEDULING_PARAMS,[], + [Do we have built-in support for scheduling params?]) - AC_EGREP_HEADER(ICAL_VAVAILABILITY_COMPONENT, ical.h, - AC_DEFINE(HAVE_VAVAILABILITY,[], - [Build VAVAILABILITY support into httpd?])) + AC_DEFINE(HAVE_VAVAILABILITY,[], + [Build VAVAILABILITY support into httpd?]) - AC_EGREP_HEADER(ICAL_VPOLL_COMPONENT, ical.h, - AC_DEFINE(HAVE_VPOLL,[], - [Build VPOLL support into httpd?])) + AC_DEFINE(HAVE_VPOLL,[], + [Build VPOLL support into httpd?]) ENABLE_RSCALE=yes PKG_CHECK_MODULES([ICU], [icu-i18n],, ENABLE_RSCALE=no)