From a1d55ebed7ccd8c4217b827b395d4d0bc6e75aa2 Mon Sep 17 00:00:00 2001 From: David Woodhouse Date: Sun, 18 Jul 2010 22:24:23 +0100 Subject: [PATCH] Convert completely to using ical structures for building events --- ews2ical.c | 538 ++++++++++++++++++++++++++++++++--------------------- 1 file changed, 328 insertions(+), 210 deletions(-) diff --git a/ews2ical.c b/ews2ical.c index ed37688..ce672bb 100644 --- a/ews2ical.c +++ b/ews2ical.c @@ -1,3 +1,4 @@ +#define _GNU_SOURCE /* for asprintf */ #include #include @@ -15,16 +16,22 @@ #include FILE *calfile; - -int process_organizer(xmlNode *xml_node); -int process_required_attendees(xmlNode *xml_node); -int process_start(xmlNode *xml_node, icaltimezone *zone); -int process_end(xmlNode *xml_node, icaltimezone *zone); -int process_location(xmlNode *xml_node); -int process_body(xmlNode *xml_node); -int process_subject(xmlNode *xml_node); -int process_recurrence(xmlNode *xml_node); -int process_itemid(xmlNode *xmlnode); +int process_relativeyearlyrecurrence(xmlNode *xml_node, struct icalrecurrencetype *ical_recur); +int process_absoluteyearlyrecurrence(xmlNode *xml_node, struct icalrecurrencetype *ical_recur); +int process_relativemonthlyrecurrence(xmlNode *xml_node, struct icalrecurrencetype *ical_recur); +int process_absolutemonthlyrecurrence(xmlNode *xml_node, struct icalrecurrencetype *ical_recur); +int process_weeklyrecurrence(xmlNode *xml_node, struct icalrecurrencetype *ical_recur); +int process_dailyrecurrence(xmlNode *xml_node, struct icalrecurrencetype *ical_recur); + +int process_organizer(icalcomponent *comp, xmlNode *xml_node); +int process_required_attendees(icalcomponent *comp, xmlNode *xml_node); +int process_start(icalcomponent *comp, xmlNode *xml_node, icaltimezone *zone); +int process_end(icalcomponent *comp, xmlNode *xml_node, icaltimezone *zone); +int process_location(icalcomponent *comp, xmlNode *xml_node); +int process_body(icalcomponent *comp, xmlNode *xml_node); +int process_subject(icalcomponent *comp, xmlNode *xml_node); +int process_recurrence(icalcomponent *comp, xmlNode *xml_node); +int process_itemid(icalcomponent *comp, xmlNode *xmlnode); icaltimezone *get_timezone(xmlNode *xmlnode); icaltimezone *get_meeting_timezone(xmlNode *xml_node); @@ -33,6 +40,7 @@ int main(int argc, char **argv) xmlDocPtr xml_doc; xmlNode *xml_node; icaltimezone *icaltz; + icalcomponent *comp; int xmlfd = 0; /* stdin */ char buf[1]; @@ -141,36 +149,41 @@ int main(int argc, char **argv) fprintf(calfile, "%s", vtz); free(vtz); } - fprintf(calfile, "BEGIN:VEVENT\n"); + comp = icalcomponent_new(ICAL_VEVENT_COMPONENT); for (xml_node = xml_node->children; xml_node; xml_node = xml_node->next) { if (xml_node->type != XML_ELEMENT_NODE) continue; if (!strcmp((char *)xml_node->name, "Organizer")) - process_organizer(xml_node); + process_organizer(comp, xml_node); else if (!strcmp((char *)xml_node->name, "RequiredAttendees")) - process_required_attendees(xml_node); + process_required_attendees(comp, xml_node); else if (!strcmp((char *)xml_node->name, "Start")) - process_start(xml_node, icaltz); + process_start(comp, xml_node, icaltz); else if (!strcmp((char *)xml_node->name, "End")) - process_end(xml_node, icaltz); + process_end(comp, xml_node, icaltz); else if (!strcmp((char *)xml_node->name, "Body")) - process_body(xml_node); + process_body(comp, xml_node); else if (!strcmp((char *)xml_node->name, "Location")) - process_location(xml_node); + process_location(comp, xml_node); else if (!strcmp((char *)xml_node->name, "Subject")) - process_subject(xml_node); + process_subject(comp, xml_node); else if (!strcmp((char *)xml_node->name, "Recurrence")) - process_recurrence(xml_node); + process_recurrence(comp, xml_node); else if (!strcmp((char *)xml_node->name, "ItemId")) - process_itemid(xml_node); + process_itemid(comp, xml_node); #if 0 else fprintf(stderr, "Unhandled node type '%s'\n", xml_node->name); #endif } - fprintf(calfile, "END:VEVENT\n"); + if (1) { + char *vtz = icalcomponent_as_ical_string_r(comp); + fprintf(calfile, "%s", vtz); + free(vtz); + } fprintf(calfile, "END:VCALENDAR\n"); + return 0; } @@ -202,52 +215,74 @@ int process_mailbox(xmlNode *xml_node, const char **r_name, const char **r_email return 0; } -int process_organizer(xmlNode *xml_node) +int process_organizer(icalcomponent *comp, xmlNode *xml_node) { + icalproperty *prop; + icalparameter *param; + for (xml_node = xml_node->children; xml_node; xml_node = xml_node->next) { if (xml_node->type != XML_ELEMENT_NODE) continue; if (!strcmp((char *)xml_node->name, "Mailbox")) { const char *name = NULL, *email = NULL; + char *mailtoname; if (process_mailbox(xml_node, &name, &email)) return -1; - fprintf(calfile, "ORGANIZER;CN=\"%s\":MAILTO:%s\n", - name, email); + + asprintf(&mailtoname, "mailto:%s", email); + + prop = icalproperty_new_organizer(mailtoname); + free(mailtoname); + param = icalparameter_new_cn(name); + icalproperty_add_parameter(prop, param); + icalcomponent_add_property(comp, prop); } } return 0; } -int process_required_attendee(xmlNode *xml_node) +int process_required_attendee(icalcomponent *comp, xmlNode *xml_node) { + icalproperty *prop; + icalparameter *param; + for (xml_node = xml_node->children; xml_node; xml_node = xml_node->next) { if (xml_node->type != XML_ELEMENT_NODE) continue; if (!strcmp((char *)xml_node->name, "Mailbox")) { const char *name = NULL, *email = NULL; + char *mailtoname; if (process_mailbox(xml_node, &name, &email)) return -1; - fprintf(calfile, "ATTENDEE;ROLE=REQ-PARTICIPANT;CN=\"%s\":MAILTO:%s\n", - name, email); + + asprintf(&mailtoname, "mailto:%s", email); + + prop = icalproperty_new_organizer(mailtoname); + free(mailtoname); + param = icalparameter_new_cn(name); + icalproperty_add_parameter(prop, param); + param = icalparameter_new_role(ICAL_ROLE_REQPARTICIPANT); + icalproperty_add_parameter(prop, param); + icalcomponent_add_property(comp, prop); } } return 0; } -int process_required_attendees(xmlNode *xml_node) +int process_required_attendees(icalcomponent *comp, xmlNode *xml_node) { for (xml_node = xml_node->children; xml_node; xml_node = xml_node->next) { if (xml_node->type != XML_ELEMENT_NODE) continue; if (!strcmp((char *)xml_node->name, "Attendee")) { - if (process_required_attendee(xml_node)) + if (process_required_attendee(comp, xml_node)) { } } } return 0; } -int process_time(xmlNode *xml_node, const char *name, icaltimezone *zone) +int process_time(icalcomponent *comp, xmlNode *xml_node, int dtend, icaltimezone *zone) { char *ews_time = (char *)xmlNodeGetContent(xml_node); struct icaltimetype ical_time; @@ -258,75 +293,70 @@ int process_time(xmlNode *xml_node, const char *name, icaltimezone *zone) if (zone) ical_time = icaltime_convert_to_zone(ical_time, zone); - fprintf(calfile, "%s", name); - - if (zone) - fprintf(calfile, ";TZID=\"%s\"", icaltimezone_get_tzid(zone)); - fprintf(calfile, ":%04d%02d%02dT%02d%02d%02d%s\n", - ical_time.year, ical_time.month, ical_time.day, - ical_time.hour, ical_time.minute, ical_time.second, - zone?"":"Z"); + if (dtend) + icalcomponent_set_dtend(comp, ical_time); + else + icalcomponent_set_dtstart(comp, ical_time); return 0; } -int process_start(xmlNode *xml_node, icaltimezone *zone) +int process_start(icalcomponent *comp, xmlNode *xml_node, icaltimezone *zone) { - return process_time(xml_node, "DTSTART", zone); + return process_time(comp, xml_node, 0, zone); } -int process_end(xmlNode *xml_node, icaltimezone *zone) +int process_end(icalcomponent *comp, xmlNode *xml_node, icaltimezone *zone) { - return process_time(xml_node, "DTEND", zone); + return process_time(comp, xml_node, 1, zone); } -int process_location (xmlNode *xml_node) +int process_location (icalcomponent *comp, xmlNode *xml_node) { - const char *dur = (char *)xmlNodeGetContent(xml_node); - if (!dur) + const char *loc = (char *)xmlNodeGetContent(xml_node); + + if (!loc) return -1; - fprintf(calfile, "LOCATION: %s\n", dur); + icalcomponent_set_location(comp, loc); return 0; } -int process_body(xmlNode *xml_node) +int process_body(icalcomponent *comp, xmlNode *xml_node) { const char *body = (char *)xmlNodeGetContent(xml_node); - int col; if (!body) return -1; - col = fprintf(calfile, "DESCRIPTION:"); + if (!strncasecmp(body, "= 76) { - fprintf(calfile, "\n "); - col = 1; - } + prop = icalproperty_new_x(body); + icalproperty_set_x_name(prop, "X-ALT-DESC"); + + param = icalparameter_new_fmttype("text/html"); + icalproperty_add_parameter(prop, param); + icalcomponent_add_property(comp, prop); +#endif + /* FIXME: html2text */ + icalcomponent_set_description(comp, body); + } else { + icalcomponent_set_description(comp, body); } - fputc('\n', calfile); + + return 0; } -int process_subject(xmlNode *xml_node) +int process_subject(icalcomponent *comp, xmlNode *xml_node) { const char *subject = (char *)xmlNodeGetContent(xml_node); + if (!subject) return -1; - fprintf(calfile, "SUMMARY:\"%s\"\n", subject); + icalcomponent_set_summary(comp, subject); return 0; } @@ -350,7 +380,9 @@ static int weekday_to_number(const char *day) { static char *days[] = { "Sunday", "Monday", "Tuesday", "Wednesday", - "Thursday", "Friday", "Saturday" + "Thursday", "Friday", "Saturday", + /* "Day", "Weekday", "WeekendDay" */ + }; int daynr; for (daynr = 0; daynr < 7; daynr++) { @@ -362,32 +394,6 @@ static int weekday_to_number(const char *day) return 0; } #define ARRAY_SIZE(x) (sizeof(x) / sizeof(x[0])) -static const char *weekday_to_ical(const char *weekday) -{ - static struct { - const char *exch; - const char *ical; - } table[] = { - { "Sunday", "SU" }, - { "Monday", "MO" }, - { "Tuesday", "TU" }, - { "Wednesday", "WE" }, - { "Thursday", "TH" }, - { "Friday", "FR" }, - { "Saturday", "SA" }, - { "Day", "SU,MO,TU,WE,TH,FR,SA" }, - { "Weekday", "MO,TU,WE,TH,FR" }, - { "WeekendDay", "SA,SU" }, - }; - int i; - - for (i=0 ; i < ARRAY_SIZE(table); i++) { - if (!strcmp(weekday, table[i].exch)) - return table[i].ical; - } - fprintf(stderr, "Unrecognised DaysOfWeek '%s'\n", weekday); - return NULL; -} static int weekindex_to_ical(const char *week) { @@ -411,84 +417,36 @@ static int weekindex_to_ical(const char *week) return 0; } -int process_recurrence(xmlNode *xml_node) +int process_recurrence(icalcomponent *comp, xmlNode *xml_node) { + struct icalrecurrencetype ical_recur; + char *end_date = NULL, *nr_occurrences = NULL; + icalproperty *prop; xmlNode *xml_node2; - const char *weekly_interval = NULL; - const char *weekday = NULL; - const char *daily_interval = NULL; - const char *monthly_interval = NULL; - const char *day_of_month = NULL; - const char *month = NULL; - const char *week_index = NULL; - const char *end_date = NULL; - const char *nr_recurrences = NULL; + + ical_recur.freq = ICAL_NO_RECURRENCE; for (xml_node = xml_node->children; xml_node; xml_node = xml_node->next) { if (xml_node->type != XML_ELEMENT_NODE) continue; if (!strcmp((char *)xml_node->name, "WeeklyRecurrence")) { - for (xml_node2 = xml_node->children; xml_node2; - xml_node2 = xml_node2->next) { - if (xml_node2->type != XML_ELEMENT_NODE) - continue; - if (!strcmp((char *)xml_node2->name, "Interval")) - weekly_interval = (char *)xmlNodeGetContent(xml_node2); - else if (!strcmp((char *)xml_node2->name, "DaysOfWeek")) - weekday = (char *)xmlNodeGetContent(xml_node2); - } + if (process_weeklyrecurrence(xml_node, &ical_recur)) + return -1; } else if (!strcmp((char *)xml_node->name, "DailyRecurrence")) { - for (xml_node2 = xml_node->children; xml_node2; - xml_node2 = xml_node2->next) { - if (xml_node2->type != XML_ELEMENT_NODE) - continue; - if (!strcmp((char *)xml_node2->name, "Interval")) - daily_interval = (char *)xmlNodeGetContent(xml_node2); - } + if (process_dailyrecurrence(xml_node, &ical_recur)) + return -1; } else if (!strcmp((char *)xml_node->name, "AbsoluteYearlyRecurrence")) { - for (xml_node2 = xml_node->children; xml_node2; - xml_node2 = xml_node2->next) { - if (xml_node2->type != XML_ELEMENT_NODE) - continue; - if (!strcmp((char *)xml_node2->name, "DayOfMonth")) - day_of_month = (char *)xmlNodeGetContent(xml_node2); - else if (!strcmp((char *)xml_node2->name, "Month")) - month = (char *)xmlNodeGetContent(xml_node2); - } + if (process_absoluteyearlyrecurrence(xml_node, &ical_recur)) + return -1; } else if (!strcmp((char *)xml_node->name, "RelativeYearlyRecurrence")) { - for (xml_node2 = xml_node->children; xml_node2; - xml_node2 = xml_node2->next) { - if (xml_node2->type != XML_ELEMENT_NODE) - continue; - if (!strcmp((char *)xml_node2->name, "DaysOfWeek")) - weekday = (char *)xmlNodeGetContent(xml_node2); - else if (!strcmp((char *)xml_node2->name, "Month")) - month = (char *)xmlNodeGetContent(xml_node2); - else if (!strcmp((char *)xml_node2->name, "DayOfWeekIndex")) - week_index = (char *)xmlNodeGetContent(xml_node2); - } + if (process_relativeyearlyrecurrence(xml_node, &ical_recur)) + return -1; } else if (!strcmp((char *)xml_node->name, "AbsoluteMonthlyRecurrence")) { - for (xml_node2 = xml_node->children; xml_node2; - xml_node2 = xml_node2->next) { - if (xml_node2->type != XML_ELEMENT_NODE) - continue; - if (!strcmp((char *)xml_node2->name, "DayOfMonth")) - day_of_month = (char *)xmlNodeGetContent(xml_node2); - else if (!strcmp((char *)xml_node2->name, "Interval")) - monthly_interval = (char *)xmlNodeGetContent(xml_node2); - } + if (process_absolutemonthlyrecurrence(xml_node, &ical_recur)) + return -1; } else if (!strcmp((char *)xml_node->name, "RelativeMonthlyRecurrence")) { - for (xml_node2 = xml_node->children; xml_node2; - xml_node2 = xml_node2->next) { - if (xml_node2->type != XML_ELEMENT_NODE) - continue; - if (!strcmp((char *)xml_node2->name, "DaysOfWeek")) - weekday = (char *)xmlNodeGetContent(xml_node2); - else if (!strcmp((char *)xml_node2->name, "Interval")) - monthly_interval = (char *)xmlNodeGetContent(xml_node2); - else if (!strcmp((char *)xml_node2->name, "DayOfWeekIndex")) - week_index = (char *)xmlNodeGetContent(xml_node2); - } + if (process_relativemonthlyrecurrence(xml_node, &ical_recur)) + return -1; } else if (!strcmp((char *)xml_node->name, "EndDateRecurrence")) { for (xml_node2 = xml_node->children; xml_node2; xml_node2 = xml_node2->next) { @@ -503,69 +461,42 @@ int process_recurrence(xmlNode *xml_node) if (xml_node2->type != XML_ELEMENT_NODE) continue; if (!strcmp((char *)xml_node2->name, "NumberOfOccurrences")) - nr_recurrences = (char *)xmlNodeGetContent(xml_node2); + nr_occurrences = (char *)xmlNodeGetContent(xml_node2); } } } - if (daily_interval) { - fprintf(calfile, "RRULE:FREQ=DAILY;INTERVAL=%s", daily_interval); - } else if (weekday && month && week_index) { - int monthnr = month_to_number(month); - int week = weekindex_to_ical(week_index); - const char *weekday_ical = weekday_to_ical(weekday); - if (!monthnr || !week || !weekday_ical) - return -1; - - fprintf(calfile, "RRULE:FREQ=YEARLY;MONTH=%d;BYDAY=%d%s", - monthnr, week, weekday_ical); - /* Relative Yearly */ - } else if (monthly_interval && weekday && week_index) { - int week = weekindex_to_ical(week_index); - const char *weekday_ical = weekday_to_ical(weekday); - if (!week || !weekday_ical) - return -1; - fprintf(calfile, "RRULE:FREQ=MONTHLY;INTERVAL=%s;BYDAY=%d%s", - monthly_interval, week, weekday_ical); - } else if (day_of_month && month) { - int monthnr = month_to_number(month); - if (!monthnr) - return -1; - fprintf(calfile, "RRULE:FREQ=YEARLY;BYMONTH=%d;BYMONTHDAY=%s", - monthnr, day_of_month); - } else if (monthly_interval && day_of_month) { - fprintf(calfile, "RRULE:FREQ=MONTHLY;INTERVAL=%s;BYMONTHDAY=%s", - monthly_interval, day_of_month); - } else if (weekly_interval && weekday) { - char day[3]; - day[0] = toupper(weekday[0]); - day[1] = toupper(weekday[1]); - day[2] = 0; - - fprintf(calfile, "RRULE:FREQ=WEEKLY;INTERVAL=%s;BYDAY=%s;WKST=SU", - weekly_interval, day); - } else { - fprintf(stderr, "Unknown Recurrence type\n"); + if (ical_recur.freq == ICAL_NO_RECURRENCE) { + fprintf(stderr, "No recognised Recurrence type\n"); return -1; } if (end_date) { - fprintf(calfile, ";UNTIL=%.4s%.2s%.2sT235959Z", - end_date, end_date + 5, end_date + 8); - } else if (nr_recurrences) { - fprintf(calfile, ";COUNT=%s", nr_recurrences); + if (strlen(end_date) != 11 || end_date[4] != '-' || + end_date[7] != '-' || end_date[10] != 'Z') { + fprintf(stderr, "Failed to parse Recurrence EndDate '%s'\n", + end_date); + return -1; + } + end_date = strdup(end_date); + end_date[10] = 0; + ical_recur.until = icaltime_from_string(end_date); + printf("parsed as %04d-%02d-%02d\n", + ical_recur.until.year, ical_recur.until.month, ical_recur.until.day); + } else if (nr_occurrences) { + ical_recur.count = strtol(nr_occurrences, NULL, 10); } - - fputc('\n', calfile); + prop = icalproperty_new_rrule(ical_recur); + icalcomponent_add_property(comp, prop); return 0; } -int process_itemid(xmlNode *xml_node) +int process_itemid(icalcomponent *comp, xmlNode *xml_node) { const char *id = (char *)xmlGetProp(xml_node, (unsigned char *)"Id"); if (!id) return -1; - fprintf(calfile, "UID:%s\n", id); + icalcomponent_set_uid(comp, id); return 0; } @@ -778,7 +709,7 @@ int process_relativeyearlyrecurrence(xmlNode *xml_node, struct icalrecurrencetyp } } if (!week || !month || !weekday) { - fprintf(stderr, "RelativeWeeklyRecurrence missing essential fields (%s,%s,%s)\n", + fprintf(stderr, "RelativeYearlyRecurrence missing essential fields (%s,%s,%s)\n", week, month, weekday); return -1; } @@ -804,7 +735,194 @@ int process_relativeyearlyrecurrence(xmlNode *xml_node, struct icalrecurrencetyp return 0; } +int process_absoluteyearlyrecurrence(xmlNode *xml_node, struct icalrecurrencetype *ical_recur) +{ + const char *day_of_month = NULL; + const char *month = NULL; + int daynr, monthnr; + + for (xml_node = xml_node->children; xml_node; + xml_node = xml_node->next) { + if (xml_node->type != XML_ELEMENT_NODE) + continue; + if (!strcmp((char *)xml_node->name, "DayOfMonth")) + day_of_month = (char *)xmlNodeGetContent(xml_node); + else if (!strcmp((char *)xml_node->name, "Month")) + month = (char *)xmlNodeGetContent(xml_node); + } + if (!day_of_month || !month) { + fprintf(stderr, "AbsoluteYearlyRecurrence missing essential fields (%s,%s)\n", + day_of_month, month); + return -1; + } + daynr = strtol(day_of_month, NULL, 10); + if (!daynr) { + fprintf(stderr, "Failed to parse DayOfMonth '%s'\n", day_of_month); + return -1; + } + monthnr = month_to_number(month); + if (!month) + return -1; + + icalrecurrencetype_clear(ical_recur); + ical_recur->freq = ICAL_YEARLY_RECURRENCE; + ical_recur->by_month[0] = monthnr; + ical_recur->by_month_day[0] = daynr; + return 0; +} + +int process_relativemonthlyrecurrence(xmlNode *xml_node, struct icalrecurrencetype *ical_recur) +{ + const char *week = NULL, *interval = NULL, *weekday = NULL; + int weeknr, intervalnr, daynr; + + for (xml_node = xml_node->children; xml_node; xml_node = xml_node->next) { + if (xml_node->type != XML_ELEMENT_NODE) + continue; + if (!strcmp((char *)xml_node->name, "DaysOfWeek")) { + weekday = (char *)xmlNodeGetContent(xml_node); + } else if (!strcmp((char *)xml_node->name, "Interval")) { + interval = (char *)xmlNodeGetContent(xml_node); + } else if (!strcmp((char *)xml_node->name, "DayOfWeekIndex")) { + week = (char *)xmlNodeGetContent(xml_node); + } + } + if (!week || !interval || !weekday) { + fprintf(stderr, "RelativeMonthlyRecurrence missing essential fields (%s,%s,%s)\n", + week, interval, weekday); + return -1; + } + intervalnr = strtol(interval, NULL, 10); + if (!intervalnr) { + fprintf(stderr, "Failed to parse Interval '%s'\n", interval); + return -1; + } + weeknr = weekindex_to_ical(week); + if (!weeknr) + return -1; + + daynr = weekday_to_number(weekday); + if (!daynr) + return -1; + + icalrecurrencetype_clear(ical_recur); + ical_recur->freq = ICAL_MONTHLY_RECURRENCE; + ical_recur->interval = intervalnr; + if (weeknr > 0) + ical_recur->by_day[0] = daynr + (weeknr * 8); + else + ical_recur->by_day[0] = -8 - daynr; + + return 0; +} +int process_absolutemonthlyrecurrence(xmlNode *xml_node, struct icalrecurrencetype *ical_recur) +{ + const char *interval = NULL, *monthday = NULL; + int intervalnr, monthdaynr; + + for (xml_node = xml_node->children; xml_node; xml_node = xml_node->next) { + if (xml_node->type != XML_ELEMENT_NODE) + continue; + if (!strcmp((char *)xml_node->name, "DayOfMonth")) { + monthday = (char *)xmlNodeGetContent(xml_node); + } else if (!strcmp((char *)xml_node->name, "Interval")) { + interval = (char *)xmlNodeGetContent(xml_node); + } + } + if (!interval || !monthday) { + fprintf(stderr, "AbsoluteMonthlyRecurrence missing essential fields (%s,%s)\n", + interval, monthday); + return -1; + } + intervalnr = strtol(interval, NULL, 10); + if (!intervalnr) { + fprintf(stderr, "Failed to parse Interval '%s'\n", interval); + return -1; + } + monthdaynr = strtol(monthday, NULL, 10); + if (!monthday) { + fprintf(stderr, "Failed to parse DayOfMonth '%s'\n", monthday); + return -1; + } + + icalrecurrencetype_clear(ical_recur); + ical_recur->freq = ICAL_MONTHLY_RECURRENCE; + ical_recur->interval = intervalnr; + ical_recur->by_month_day[0] = monthdaynr; + return 0; +} + +int process_weeklyrecurrence(xmlNode *xml_node, struct icalrecurrencetype *ical_recur) +{ + const char *interval = NULL, *weekday = NULL, *firstday = NULL; + int intervalnr, daynr, firstdaynr; + + for (xml_node = xml_node->children; xml_node; xml_node = xml_node->next) { + if (xml_node->type != XML_ELEMENT_NODE) + continue; + if (!strcmp((char *)xml_node->name, "DaysOfWeek")) { + weekday = (char *)xmlNodeGetContent(xml_node); + } else if (!strcmp((char *)xml_node->name, "Interval")) { + interval = (char *)xmlNodeGetContent(xml_node); + } else if (!strcmp((char *)xml_node->name, "FirstDayOfWeek")) { + firstday = (char *)xmlNodeGetContent(xml_node); + } + } + if (!interval || !weekday) { + fprintf(stderr, "WeeklyRecurrence missing essential fields (%s,%s)\n", + interval, weekday); + return -1; + } + intervalnr = strtol(interval, NULL, 10); + if (!intervalnr) { + fprintf(stderr, "Failed to parse Interval '%s'\n", interval); + return -1; + } + daynr = weekday_to_number(weekday); + if (!daynr) + return -1; + + if (firstday) + firstdaynr = weekday_to_number(firstday); + else + firstdaynr = 0; + + icalrecurrencetype_clear(ical_recur); + ical_recur->freq = ICAL_WEEKLY_RECURRENCE; + ical_recur->interval = intervalnr; + ical_recur->by_day[0] = daynr; + ical_recur->week_start = firstdaynr; + return 0; +} +int process_dailyrecurrence(xmlNode *xml_node, struct icalrecurrencetype *ical_recur) +{ + const char *interval = NULL; + int intervalnr; + for (xml_node = xml_node->children; xml_node; xml_node = xml_node->next) { + if (xml_node->type != XML_ELEMENT_NODE) + continue; + if (!strcmp((char *)xml_node->name, "Interval")) { + interval = (char *)xmlNodeGetContent(xml_node); + } + } + if (!interval) { + fprintf(stderr, "DailyRecurrence missing essential fields (%s)\n", + interval); + return -1; + } + intervalnr = strtol(interval, NULL, 10); + if (!intervalnr) { + fprintf(stderr, "Failed to parse Interval '%s'\n", interval); + return -1; + } + + icalrecurrencetype_clear(ical_recur); + ical_recur->freq = ICAL_DAILY_RECURRENCE; + ical_recur->interval = intervalnr; + + return 0; +} icalcomponent *process_timezone_rule(xmlNode *xml_node, icalcomponent_kind kind, int *offset) { -- 2.49.0