From: David Woodhouse Date: Sat, 17 Jul 2010 21:15:50 +0000 (+0100) Subject: Not entirely sober attempt at relative monthly/annual recurrence X-Git-Url: https://www.infradead.org/git/?a=commitdiff_plain;h=9cdfd6f1a5a7b3e31fae2a13bf6b4e674d9e5e04;p=users%2Fdwmw2%2Fews-sync.git Not entirely sober attempt at relative monthly/annual recurrence Need to work out how to handle 'Day', 'Weekday', etc. --- diff --git a/ews2ical.c b/ews2ical.c index 9805363..338b21e 100644 --- a/ews2ical.c +++ b/ews2ical.c @@ -304,19 +304,81 @@ int process_subject(xmlNode *xml_node) return 0; } -char *months[] = { - "January", "February", "March", "April", "May", "June", "July", - "August", "September", "October", "November", "December" -}; +static int month_to_number(const char *month) +{ + static char *months[] = { + "January", "February", "March", "April", "May", "June", "July", + "August", "September", "October", "November", "December" + }; + int monthnr; + for (monthnr = 0; monthnr < 12; monthnr++) { + if (!strcmp(month, months[monthnr])) + return monthnr + 1; + } + + fprintf(stderr, "Unrecognised month name '%s'\n", month); + 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", "SO" }, + { "Monday", "MO" }, + { "Tuesday", "TU" }, + { "Wednesday", "WE" }, + { "Thursday", "TH" }, + { "Friday", "FR" }, + { "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) +{ + static struct { + char *exch; + int week; + } table[] = { + { "First", 1 }, + { "Second", 2 }, + { "Third", 3 }, + { "Fourth", 4 }, + { "Last", -1 } + }; + int i; + + for (i = 0; i < ARRAY_SIZE(table); i++) { + if (!strcmp(week, table[i].exch)) + return table[i].week; + } + fprintf(stderr, "Unrecognised DayOfWeekIndex '%s'\n", week); + return 0; +} + int process_recurrence(xmlNode *xml_node) { 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; @@ -352,11 +414,41 @@ int process_recurrence(xmlNode *xml_node) month = (char *)xmlNodeGetContent(xml_node2); } } else if (!strcmp((char *)xml_node->name, "RelativeYearlyRecurrence")) { - fprintf(stderr, "Cannot yet handle %s\n", xml_node->name); + 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); + } } else if (!strcmp((char *)xml_node->name, "AbsoluteMonthlyRecurrence")) { - fprintf(stderr, "Cannot yet handle %s\n", xml_node->name); + 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, "DayOfWeekIndex")) + week_index = (char *)xmlNodeGetContent(xml_node2); + else if (!strcmp((char *)xml_node2->name, "Month")) + month = (char *)xmlNodeGetContent(xml_node2); + } } else if (!strcmp((char *)xml_node->name, "RelativeMonthlyRecurrence")) { - fprintf(stderr, "Cannot yet handle %s\n", xml_node->name); + 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); + } } else if (!strcmp((char *)xml_node->name, "EndDateRecurrence")) { for (xml_node2 = xml_node->children; xml_node2; xml_node2 = xml_node2->next) { @@ -377,17 +469,32 @@ int process_recurrence(xmlNode *xml_node) } 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; - for (monthnr = 0; monthnr < 12; monthnr++) - if (!strcmp(month, months[monthnr])) - break; - if (monthnr == 12) { - fprintf(stderr, "Unrecognised month name '%s'\n", month); + int monthnr = month_to_number(month); + if (!monthnr) return -1; - } fprintf(calfile, "RRULE:FREQ=YEARLY;BYMONTH=%d;BYMONTHDAY=%s", - monthnr+1, day_of_month); + 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]);